(Quick Reference)

5.2 Forked Execution - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari

Version: 2.3.8

5.2 Forked Execution

Forked Execution

Since Grails 2.3, the run-app, run-war, test-app and console commands are now executed in a forked JVM in order to isolate the build classpath from the runtime classpath.

Forked execution is configured via the grails-app/conf/BuildConfig.groovy file. The following is the default configuration:

grails.project.fork = [
   test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, daemon:true], // configure settings for the test-app JVM
   run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256], // configure settings for the run-app JVM
   war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256], // configure settings for the run-war JVM
   console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256]// configure settings for the Console UI JVM
]

The memory requirements of the forked JVM can be tweaked as per the requirements of the application.

Forked Test Execution

When running the test-app command, a separate JVM is launched to execute this tests. This will have a notable impact on the speed of execution of the tests when running the command directly:

grails test-app

To mitigate this, Grails 2.3 and above include a feature that launches a background JVM on standby to run tests when using interactive mode. In other words, running test-app from interactive mode will result in faster test execution times:

$ grails
$ grails> test-app

It is recommended that forked execution is used for tests, however it does require modern hardware due to the use of multiple JVMs. You can therefore disable forked execution by setting the grails.project.fork.test setting to false:

forkConfig = [maxMemory: 1024, minMemory: 64, debug: false, maxPerm: 256]
grails.project.fork = [
   test: false,
   …
]

Using the Test Runnner Deamon to Speed-up Test Execution

The defaut configuration for the testing is to activate a daemon to run tests using the daemon argument:

grails.project.fork = [
   test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, daemon:true], // configure settings for the test-app JVM
   ...

This only works in interactive mode, so if you start Grails with the 'grails' command and then using test-app the daemon will be used:

$ grails
$ grails> test-app

This has the effect of speeding-up test executions times. You can disable the daemon by setting daemon to false. If the daemon becomes unresponsive you can restart it with restart-daemon:

$ grails> restart-daemon

Debugging and Forked Execution (--debug vs --debug-fork)

An important consideration when using forked execution is that the debug argument will allow a remote debugger to be attached to the build JVM but not the JVM that your application is running in. To debug your application you should use the debug-fork argument:

grails test-app --debug-fork

Or for run-app:

grails run-app --debug-fork

Forked Tomcat Execution

Grails 2.2 and above support forked JVM execution of the Tomcat container in development mode. This has several benefits including:

  • Reduced memory consumption, since the Grails build system can exit
  • Isolation of the build classpath from the runtime classpath
  • The ability to deploy other Grails/Spring applications in parallels without conflicting dependencies

To enable forked execution you can set the grails.project.fork.run property to true:

grails.project.fork.run=true

Then just us the regular run-app command as per normal. Note that in forked mode the grails process will exit and leave the container running in the background. To stop the server there is a new stop-app command:

grails stop-app

To customize the JVM arguments passed to the forked JVM you can specify a map instead:

grails.project.fork.run= [maxMemory:1024, minMemory:64, debug:false, maxPerm:256, jvmArgs: '..arbitrary JVM arguments..']

Auto-deploying additional WAR files in Forked Mode

Since forked execution isolates classpaths more effectively than embedded execution you can deploy additional WAR files (such as other Grails or Spring applications) to the container.

The easiest way to do so is to drop the WAR files into the src/autodeploy directory (if it doesn't exist you can create it).

You can customize the location of the autodeploy directory by specifying an alternative location in BuildConfig.groovy:

grails.project.autodeploy.dir="/path/to/my/war/files"

Customizing the Forked Tomcat instance

If you want to programmatically customize the forked Tomcat instance you can do so by implementing a class named org.grails.plugins.tomcat.ForkedTomcatCustomizer which provides a method with the following signature:

void customize(Tomcat tomcat) {
 // your code here
}