CHAPTER 12

Deploying and Upgrading

The previous chapters have been related to developing Grails applications. One of the strengths of Grails is that it comes bundled with everything you need to begin developing and testing your application. Grails embeds a web container (Jetty) and a relational database (HSQLDB). All you have to do is execute the Grails run-app target, and you have your entire runtime environment. However, at some point in time, you will want to expose your application to your users. The embedded runtime environment is for development and testing only, and it is not intended to scale or support the load necessary in a production environment.

This chapter focuses on deploying Grails applications to Java EE application servers and more robust database servers. It also covers some other miscellaneous, operational aspects, such as upgrading a Grails application when a new version of the Grails framework is released and automating tasks using Gant.

Deploying Grails Applications

Deploying a Grails application involves three steps. First, you need to configure the application. This typically involves environment-specific configurations. Second, you package the application. For Grails applications, this means bundling all the code and related artifacts into a WAR file. The final step is to actually deploy the application to an application server or web container.

Using Environments

Many organizations have multiple environments or gates that an application must pass through before reaching production and users. At a minimum, each application should have to pass through development, test, and production environments. The development environment is the developer's machine. In the test environment, which mimics production, somebody other than the developer completes quality assurance by validating that the application meets requirements and generally works. The production environment is where real users use the application. In each of these environments, you're likely to have environment-specific configurations and, rarer, behavioral differences. For example, in development, you may want to point to a local HSQLDB in-memory database, but in the test and production environments, you may need to point at a remote server database such as MySQL.1

As you might expect, Grails follows these best practices and is aware of these three environments. You can use these environments when calling the grails command line as the second parameter or in configuration files such as DataSource.groovy and Config.groovy, which you'll see in the next section. Table 12-1 shows the mapping per environment.

Table 12-1. Environment Mappings

Environment Command Line Configuration File Reference
Development dev development
Test test test
Production prod production

Depending on the size of the organization and the criticalness of the application or the system, you may have additional environments such as integration testing (IT), user acceptance testing (UAT), and performance testing (PT). You can use custom environments as well. The only requirement is that the grails.env system property must be passed to the grails command line. For example, the following would specify the performance environment:

> grails -Dgrails.env=PT run-app

Understanding Grails Configurations

Grails contains four primary configuration categories. The first is URL mapping, which we explained and demonstrated thoroughly in Chapter 9, so we won't be revisiting it here. The second is behavior when the application starts up and shuts down. The third and fourth are data source and logging configurations. You can find all these configurations in the grails-app/config directory.

Startup and Shutdown Behavior

Sometimes when an application starts up and/or shuts down, you need to do things such as acquire and release resources, respectively, or cache data. Grails makes this possible in the grails-app/config/BootStrap.groovy file, which you first saw in Chapter 7. Listing 12-1 is an example of a BootStrap.groovy file. It includes comments where startup and shutdown code would go.

__________

Listing 12-1. Using BootStrap.groovy to Perform Startup and Shutdown Activities

class BootStrap {

  def init = { servletContext ->
     // perform startup activities here
  }

  def destroy = {
    // perform shutdown activities here
  }
}

The init action is invoked when the application starts up or is redeployed. The javax.servlet.ServletContext2 is passed in, providing access to the application attributes, initialization parameters configured in web.xml, the context path, and more. The destroy action is invoked when the application is shut down, but it is not guaranteed to be called. For example, it is not likely the destroy method will be called when the application server is shut down, but it is likely to be called when the application is redeployed or undeployed.


Note As discussed and demonstrated in Chapter 7's "Bootstrapping" sidebar, you can use the GrailsUtil.environment() to determine which environment the application is running in and perform the appropriate bootstrapping code.


Data Source Configurations

By default, Grails is configured out of the box to use an embedded, in-memory HSQLDB database. This is not likely to be the database used in the test and production environments and possibly not even in most development environments, because as you've seen, each time the application restarts, the database gets re-created in memory and is therefore empty. It's more likely that an application will use a server database such as MySQL, Oracle,3 DB2,4 Microsoft SQL Server,5 or maybe even Apache Derby.6 It might even use HSQLDB in a file mode. Any Hibernate-supported database7 should be able to be used.

__________

You can set database and Hibernate configurations in the grails-app/config/Data Source.groovy file. Listing 12-2 shows an example of a DataSource.groovy file that has been customized to include a production database configuration for a local MySQL database.



Note You can find installation and configuration instructions for MySQL at http://www.beginninggroovyandgrails.com.



Listing 12-2. DataSource.groovy Containing a MySQL Production Configuration

01 dataSource {
02     pooled = false
03     driverClassName = "org.hsqldb.jdbcDriver"
04     username = "sa"
05     password = ""
06 }
07 hibernate {
08     cache.use_second_level_cache=true
09     cache.use_query_cache=true
10     cache.provider_class='org.hibernate.cache.EhCacheProvider'
11 }
12 // environment specific settings
13 environments {
14     development {
15         dataSource {
16             dbCreate = "create-drop" // one of 'create', 'create-drop','update'
17             url = "jdbc:hsqldb:mem:devDB"
18         }
19     }
20     test {
21         dataSource {
22             dbCreate = "update"
23             url = "jdbc:hsqldb:mem:testDb"
24         }
25     }
26     production {
27         dataSource {
28             pooled = true
29             driverClassName = "com.mysql.jdbc.Driver"
30             username = "root"
31             password = "<password>"
32             dbCreate = "update"
33             url = "jdbc:mysql://localhost:3306/collab_todo"
34         }
35     }
36 }

_________

The configuration file in Listing 12-2 is separated into three main parts: dataSource (lines 1–6), hibernate (lines 7–11), and environment-specific settings (lines 12–36). The dataSource section provides default database settings that environment-specific settings may override or append to. Other than the pooled property, these default settings all relate to standard JDBC configuration information, such as the JDBC driver class name, the username, and the password for the database.

The hibernate section relates to Hibernate-specific settings. By default, it configures Hibernate caching settings. See the Hibernate documentation8 for more configuration options.

Finally, the environment-specific settings can provide specific data source or Hibernate configurations for a particular named environment. Notice in lines 28–33 that the production dataSource is configured to use a MySQL database by setting the driverClassName and url to be MySQL-specific. It also overrides the pooled property by setting it to true, since most production environments have more concurrent needs than a developer's workstation. Finally, note that the dbCreate property is configured only for update. This means that at deployment time, Hibernate will update any of the tables it is able to, but it will leave the existing data intact. On the other hand, the default development configuration will create the table at startup and destroy the tables and data when the application is shut down.

The DataSource.groovy configuration file is not the only application configuration that you must complete to support connection to the database. You also must include the database driver JAR in the classpath of the application. The easiest way to do this is to simply copy the JAR(s) to the project lib directory. At deployment or packaging time, Grails will copy the JAR file to the WEB-INF/lib directory. For a MySQL database, you would need to copy the mysql-connector-java-X.X.X-bin.jar file to the lib directory.

__________

Logging Configurations

Logging is an important part of gathering feedback about the state of an application. As you learned in Chapter 5, Grails provides logging support using the Apache Commons Logging component9 and Apache log4j.10 You can make the log4j configurations, as well as a couple other configurations, in grails-app/config/Config.groovy. Listing 12-3 shows the default version of Config.groovy.

Listing 12-3. Config.groovy File Containing Logging Configurations

01 // log4j configuration
02 log4j {
03   appender.stdout = "org.apache.log4j.ConsoleAppender"
04   appender.'stdout.layout'="org.apache.log4j.PatternLayout"
05   appender.'stdout.layout.ConversionPattern'='[%r] %c{2} %m%n'
06   rootLogger="error,stdout"
07   logger {
08     grails="info,stdout"
09     org {
10       codehaus.groovy.grails.web.servlet="off,stdout"  //  controllers
11       codehaus.groovy.grails.web.pages="off,stdout" //  GSP
12       codehaus.groovy.grails.web.sitemesh="off,stdout" //  layouts
13       codehaus.groovy.grails."web.mapping.filter"="off,stdout" // URL mapping
14       codehaus.groovy.grails."web.mapping"="off,stdout" // URL mapping
15       codehaus.groovy.grails.commons="off,stdout" // core / classloading
16       codehaus.groovy.grails.plugins="off,stdout" // plugins
17       codehaus.groovy.grails.orm.hibernate="info,stdout" // hibernate integration
18       springframework="off,stdout"
19       hibernate="off,stdout"
20     }
21   }
22   additivity.'default' = false
23   additivity {
24     grails=false
25     org {
26       codehaus.groovy.grails=false
27       springframework=false
28       hibernate=false
29     }
30   }
31 }
32
33 // The following properties have been added by the Upgrade process...
34 grails.views.default.codec="none" // none, html, base64
35 grails.views.gsp.encoding="UTF-8"

__________

In Listing 12-3, lines 2–31 configure log4j, while the remaining lines set some default configurations for views. When the application logs a message, something has to be done with the message. Lines 3–5 configure a ConsoleAppender, which takes the message and writes it to standard out with the format defined by the pattern in line 5. Line 6 instructs log4j to send only messages with severities of error or greater to the appender unless explicitly overwritten. Lines 7–20 show examples of overriding some logging. For example, on line 8, the grails logger says to include anything with a log level of info or above, while line 10 turns off org.codehaus.groovy.grails.web.servlet completely.



Note There are a lot of configuration options for log4j. Check out the "Short introduction to log4j"11 for more details.



Grails provides some special loggers for the different types of artifacts that it already understands by conventions. Table 12-2 documents the special loggers you will find helpful for seeing your log messages.

Table 12-2. Special Grails Artifact Loggers

Logger Description
grails.app.controller Configures logging for all your controllers
grails.app.domain Configures logging for all your domains
grails.app.service Configures logging for all your services
grails.app.tagLib Configures logging for all your tag libraries

The most likely log configuration you will want to make is adding environment-specific logging for your artifacts; you can use the loggers described in Table 12-2. For example, in your development environment, you may want to log messages at a debug level (as shown in Listing 12-4), but in your production environment, you may want to log fewer messages for performance reasons and to ensure that the log file doesn't consume all your disk space.

__________

Listing 12-4. Example of Adding Logging Specific to Your Development Environment

environments {
  development {
    log4j {
      logger {
        grails {
          app.controller="debug"
        }
      }
    }
  }
}

Listing 12-4 shows an example of logging all controllers at a debug level. You can simply add this configuration to the end of the Config.groovy file and then restart the application for the new development-specific logging configuration to take effect.

Packaging the Application for Deployment

After you complete the application functionality for an iteration or a release, you or your build master will have to package your application so it can be deployed on a machine other than your computer. At the most basic level, all you have to do is run the Grails war target to create a deployable WAR file. In reality, though, you should follow a more disciplined process to make it easier to identify the version of your application as it goes through environments. We recommended you follow this procedure for milestone releases:

  1. Update the code from your version control repository to make sure it's in sync with the head/trunk.
  2. Run unit and smoke tests to verify that the release is ready.
  3. Increment the app.version property in application.properties either manually or by using the grails set-version target to identify a milestone release number, such as X.X.X.
  4. Clean the project using the grails clean target to make sure there are no leftover artifacts.
  5. Package the application into a WAR file using the grails war target and an environment designation—for example, grails prod war. This creates a WAR file in the root of the project with a name containing the project name and version number.
  6. Increment the app.version property and append a -SNAPSHOT in application.properties either manually or by using the grails set-version target to indicate this version is a work in progress and not a milestone release.
  7. Commit the application.properties file back into your version control repository.

Now you have a WAR file ready for deployment. We'll discuss how to deploy it in the next section.

Deploying to an Application Server

A Grails application packaged as a WAR file can be deployed to Java EE application servers such as JBoss,12 GlassFish,13 ApacheGeronimo,14 BEA WebLogic,15 or IBM WebSphere,16 or to a web container such as Apache Tomcat17 or Jetty.18 Deployment between containers varies greatly, so consult your application server or web container documentation for details. However, standard mechanisms include special deployment directories where the WAR can be copied, a web-based administrator console, a command-line client, and/or Apache Ant tasks. Grails does not provide anything for simplifying deployments, so the next section explains how you can write your own script to automate the process.


Note The Grails FAQ19 has specific configurations and tips for deploying Grails applications to some common application servers.


__________

Automating Tasks with Gant

Development is full of cycles and repetitive tasks, such as compiling, packaging, and deploying. Performing such tasks manually can be boring and error prone. It is considered a best practice to automate such tasks. Many books have been written to this effect, and many frameworks have been developed to solve the problem. In fact, one of the primary conventions for Grails is the grails command line, which is used to automate common tasks in Grails development. The Grails command line utilizes Gant,20 a build system that uses the Groovy language to script Apache Ant21 tasks rather than Ant's XML format. Ant, and therefore Gant, are primarily made up of name collections of tasks referred to as targets, which you can execute to complete a unit of work.


Note Neal Ford,22 author and frequent speaker on the "No Fluff Just Stuff" symposium series,23 describes the importance of automation as, "Doing work like a manual laborer makes you dumber, figuring out how to automate it makes you smarter so be a craftsman not a laborer."


As you have seen throughout this book, the Grails command line provides a lot of functionality. However, it may not automate every task you perform during your development. For example, there is no task for deploying, and yet it is common to deploy your application to infrastructure that matches the application server and database you use in a production environment. So from time to time, you may want to simplify your development efforts by creating your own Gant scripts or modifying existing ones.

Grails makes it easy to incorporate your scripts into your development process. After all, every Grails command-line task is itself a Gant script already. The Grails command line uses the following directories to locate scripts for execution and incorporate them into the help system:

  • USER_HOME/.grails/scripts
  • PROJECT_HOME/scripts
  • PROJECT_HOME/plugins/*/scripts
  • GRAILS_HOME/scripts

__________

After writing your Gant script, you can place it in one of these directories, and it will automatically be available from the Grails command line and in the Grails help list.

Grails does not include a deployment script, because there are too many application servers and configuration options to keep up. Listing 12-5 shows an example of a simple script you can use to deploy a WAR file to an application server that supports automatic deployments via a deployment directory like JBoss has.


Note You can find installation and configuration instructions for JBoss at http://www.beginninggroovyandgrails.com.


Listing 12-5. Basic Deployment Script Deploy.groovy

01 /**
02 * Gant script that copies a WAR file to an application
03 * server deployment directory.
04 */
05
06 Ant.property(environment:"env")
07 grailsHome = Ant.antProject.properties."env.GRAILS_HOME"
08
09 includeTargets << new File ( "${grailsHome}/scripts/War.groovy" )
10
11 target ('default':'''Copies a WAR archive to a Java EE app server's deploy
12 directory.
13
14 Example:
15 grails deploy
16 grails prod deploy
17 ''') {
18   deploy()
19 }
20
21 target (deploy: "The implementation target") {
22   depends( war )
23
24   def deployDir = Ant.antProject.properties.'deploy.dir'
25
26   Ant.copy(todir:"${deployDir}", overwrite:true) {
27     fileset(dir:"${basedir}", includes:"*.war")
28   }
29
30  event("StatusFinal", ["Done copying WAR to ${deployDir}"])
31 }

The Deploy.groovy script shown in Listing 12-5 begins by loading all system environment variables and then storing the GRAILS_HOME environment variable into a local variable on lines 6 and 7. Line 9 imports another Gant script—specifically, the War.groovy script. The deploy script is dependent on the War.groovy script to build the WAR file, so it has something to deploy.

Lines 11–19 represent the first of two targets in this script. The first target is the default target, which means if no other target is specified, this will be the one executed. Since Grails calls the default target, it will definitely be the one executed. Notice that the default name is in single quotes; this is because the word default is a reserved word in Groovy. Quotes are not normally needed for target names. Following the name is the target description, which the Grails help system uses. The only behavior the default target has is to call the deploy target.

The deploy target, shown on lines 21–31, does all the real work. It begins by calling the war target from the War.groovy script. After the WAR file has been created, it looks up the deploy.dir property. It then copies the WAR file to the location of this property. You can put the destination of the WAR file in the application.properties file, since the Grails command line loads it automatically. Lines 26–28 use the Ant copy task to copy all WAR files to the deployment directory. Finally, a message is printed to the system out to indicate to the user that the script is complete and which directory the WAR file has been copied to.

Running the following target performs the deployment by copying the WAR file to your application server:

> grails deploy


Note If you need to deploy to a remote application server, you might be able to use Apache Ant's Secure Copy Protocol (SCP) task to copy a WAR to a remote server running Secure Shell (SSH).


Upgrading Grails Applications

Early in the development of the Grails framework, it must have become obvious that the framework would go through many iterations and that some mechanism was needed to ensure that applications could migrate easily to new releases of the Grails framework. As with many of the Grails conventions, this is accomplished through a Grails target, upgrade.

During the startup of an application using the run-app target, Grails checks the application metadata found in the application.properties file (see Listing 12-6) located in the root of the project directory structure for the app.grails.version number.

Listing 12-6. The application.properties File

#Do not edit app.grails.* properties, they may change automatically.
#DO NOT put application configuration in here, it is not the right place!
#Fri Dec 28 22:26:01 EST 2007
app.version=0.1
app.servlet.version=2.4
app.grails.version=1.0
app.name=collab-todo

If the currently configured version of Grails doesn't match the application metadata's app.grails.version number, Grails will display the following message:


Application expects grails version [1.0], but GRAILS_HOME is version [1.0.2] –
use the correct Grails version or run 'grails upgrade' if this Grails version is
newer than the version your application expects.

Upgrading the application is as easy as running grails upgrade.


Caution When upgrading, Grails may overwrite existing files. It's a good idea to ensure your application is in sync with your version control repository before running the upgrade target.


Summary

This chapter covered a lot of the operational aspects of developing Grails applications. Many of the topics related to things that happen after the code is written or to helping facilitate the development process. The topics included packaging and deploying the application as well as configuring environmental data sources and logging. It also covered how to automate your daily development processes and upgrade your applications to work with new versions of Grails. This chapter also ends the server-side discussion of Grails. The remaining chapter discusses aspects of writing clients that may utilize the deployed application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset