(Quick Reference)

3 Advanced Plugin Configuration & Usage - Reference Documentation

Authors: Luke Daley, Graeme Rocher, Peter Ledbrook, John Engelman

Version: 2.1.1

3 Advanced Plugin Configuration & Usage

This section covers advanced topics in the Gradle Grails Plugin. It includes topics related to configuring the underlying JVM that is executing the Grails tasks and integrating Grails builds into larger multi-project build.

3.1 Overview of Plugin Integration with Grails

Integration of Grails into Gradle via this plugin is a complicated endeavour. The Grails framework contains its own build tooling that performs source compilation, test execution, and artifact packaging. Additionally, it has an extensive and mature plugin community of its own. Each plugin can add its own scripts to a Grails build and provide additional dependencies.

Because Grails contains is own build tooling, Grails projects, despite being based on Java & Groovy, do NOT use the Groovy, Java, or War plugins for Gradle. As a consequence, these projects lose many of the conveniences for configuration that a standard Gradle project would receive. The Gradle Grails Plugin tries to address many of these shortcomings but some may not be possible with the current state of the frameworks.

The Grails 3 Road Map currently includes re-writing the Grails build system to be based on Gradle.

The Grails Gradle Plugin integrates with Grails through another library Grails Launcher This library functions by creating a LaunchContext instance that contains the necessary classpath information, script name, and arguments and serializing it to disk in a known location. Gradle then forks a JVM instance that will execute the Main class in the Grails Launcher project with the path to the serialized LaunchContext.

The Grails Launcher project is a library that integrates at a low-level into the Grails framework. In short, it configures the JVM is the same manner that the grails scripts on the command line do when executing Grails natively.

3.2 Passing arguments to Grails Tasks

The plugin tries to configure the known Grails tasks to the best of its abilities. However, sometimes additional parameters are necessary to be be passed from the command line. In order to pass options to the underlying JVM that is forked using the grailsArgs system property from the command line:

$ gradle -PgrailsArgs="FooController" grails-create-controller

The above line with pass the FooController string to the underlying Grails create-controller command.

The grailsArgs property is a single system property. You can only specify it once and it is not parsed in anyway before being passed to the Grails JVM. It is strongly recommended to use "" around the value being passed to avoid any type of shell interpretation of the value.

The grailsArgs property is wired ONLY to dynamically created tasks using the grails- prefix. Tasks created by the plugin are intended to provide for a repeatable build experience and as such do NOT accept additional parameters via the command line. The proper way to configure these tasks is via the Gradle build file

3.3 Setting the Grails Environment

The plugin allows you to override the Grails environment on the command line by using the grailsEnv property on the command line:

$ gradle -PgrailsEnv=prod grails-run-app

The above command will execute the Grails run-app command in the prod environment.

The PgrailsEnv property is wired ONLY to dynamically created tasks using the grails- prefix. Tasks created by the plugin are intended to provide for a repeatable build experience and as such do NOT accept additional parameters via the command line. The proper way to configure these tasks is via the Gradle build file

3.4 Debugging Grails tasks

The plugin allows Grails tasks to enable a debugger by setting the grailsDebug property to true.

$ gradle -PgrailsDebug="true" run

The above command will execute the Grails run-app command with debug mode activated. This flag sets the debug mode by setting jvmOptions.debug=true on the underlying Gradle JavaExec instance for the Grails task. By default this activates debugging in a suspended mode on port 5005.

The grailsDebug is passed to ALL Grails tasks in Gradle.

To manually configure the debug properties (i.e., suspend mode, port, etc) for the tasks, configure the options via the jvmOptions.jvmArgs property:

run {
  jvmOptions {
    jvmArgs([
      '-Xdebug',
      '-Xnoagent',
      '-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5006'
    ])
  }
}

The above block configures the JVM that Grails executes in to have a remote debugger on port 5006 and does NOT suspend the JVM on startup.

3.5 Configuring JVM Memory for Grails Tasks

Grails applications are known for quickly growing in memory size (especially in PermGen). Currently, the plugin makes no efforts to configure the memory settings for the Grails JVM. By default then, the Grails JVM will have the same memory settings as the Gradle JVM which forked it.

Each GrailsTask exposes a jvmOptions property that can be used to configure the underlying JVM. The jvmOptions property is an instance of JavaForkOptions and all the properties and methods from that class are available.

run {
    jvmOptions {
        minHeapSize = '512m'
        maxHeapSize = '1g'
        jvmArgs '-XX:MaxPermSize=512m'
    }
}

Alternatively, it may be beneficial to configure all the GrailsTask in the build to have the same memory settings.

project.tasks.withType(GrailsTask) { GrailsTask task ->
    task.jvmOptions {
        minHeapSize = '512m'
        maxHeapSize = '1g'
        jvmArgs '-XX:MaxPermSize=512m'
    }
}

3.6 Capturing Grails task output to INFO log

By default GrailsTasks will send their output and error stream to System.out and System.err respectively. However, any task can be configured to instead capture their output to the Logger.INFO level by setting the captureOutputToInfo property to true on the task. When enabled, the task will capture its output and error streams to a buffer. If the task encounters an error, then both the output and error streams will be rendered onto System.out and System.err respectively.

This allows a successful build to minimize the amount of logging produced to the console during the build and also allows the output from failed tasks in a parallel multi-project build to rendered their output without interleaving it with the output of other tasks.

The property can be configured on all GrailsTask instances using the following:

project.tasks.withType(GrailsTask) {
  captureOutputToInfo = true
}

3.7 Managing Grails Plugins with Gradle

The plugin configures the build task to call the appropriate package-plugin task for Grails plugin projects to produce the plugin zip file. Additionally, the plugin configures the Gradle configuration inheritance so that including Grails plugin projects via a Gradle project dependency should include the transitive dependencies for the plugin.

Plugin Publication

Plugin Publication is not fully supported at this time. Additional information will be added to this page as use cases are defined.

Publishing a Simple Grails Plugin

For simple Grails plugin projects, that is projects that have NO external dependencies, plugin release and publication can be accomplished using the Grails Release Plugin Add the release plugin to the bootstrap configuration and execute the grails-release-plugin task.

dependencies {
    bootstrap 'org.grails.plugin:release:2.2.1'
}

$ gradle grails-release-plugin

See the plugin page http://grails.org/plugin/release for compatibility notes regarding the release plugin and the Grails version

Using the Release Plugin is only supported when there are no external dependencies because the release-plugin command utilizes the dependencies configured in BuildConfig.groovy to build the plugin's pom.xml file. Since dependencies are being configure through Gradle, the BuildConfig.groovy will not have the correct information and the pom.xml will be incorrect (especially when using Gradle project dependencies).

Publishing Using the Gradle Maven Plugin

Plugin publication using the maven plugin is currently untested.

Publishing Using the Gradle Maven-Publish (incubating) Plugin

Plugin publication using the maven-publish plugin is not fully supported. This is an incubating plugin and dependency information is not generated correctly in the POM. Specifically, at the time of writing, all dependencies were added to the runtime scope in the POM and installing the resulting plugin in a project did not resolve transitive dependencies correctly.