(Quick Reference)

3.3.1 Upgrading Plugins

Version: 3.2.3

3.3.1 Upgrading Plugins

To upgrade a Grails 2.x plugin to Grails 3.x you need to make a number of different changes. This documentation will outline the steps that were taken to upgrade the Quartz plugin to Grails 3, each individual plugin may differ.

Step 1 - Create a new Grails 3 plugin

The first step is to create a new Grails 3 plugin using the command line:

$ grails create-plugin quartz

This will create a Grails 3 plugin in the quartz directory.

Step 2 - Copy sources from the original Grails 2 plugin

The next step is to copy the sources from the original Grails 2 plugin to the Grails 3 plugin:

# first the sources
cp -rf ../quartz-2.x/src/groovy/ src/main/groovy
cp -rf ../quartz-2.x/src/java/ src/main/groovy
cp -rf ../quartz-2.x/grails-app/ grails-app
cp -rf ../quartz-2.x/QuartzGrailsPlugin.groovy src/main/groovy/grails/plugins/quartz

# then the tests
cp -rf ../quartz-2.x/test/unit/* src/test/groovy
mkdir -p src/integration-test/groovy
cp -rf ../quartz-2.x/test/integration/* src/integration-test/groovy

# then templates / other resources
cp -rf ../quartz-2.x/src/templates/ src/main/templates

Step 3 - Alter the plugin descriptor

You will need to add a package declaration to the plugin descriptor. In this case QuartzGrailsPlugin is modified as follows:

// add package declaration
package grails.plugins.quartz
...
class QuartzGrailsPlugin extends Plugin {
 ...
}

In addition you should remove the version property from the descriptor as this is now defined in build.gradle.

Step 4 - Update the Gradle build with required dependencies

The repositories and dependencies defined in grails-app/conf/BuildConfig.groovy of the original Grails 2.x plugin will need to be defined in build.gradle of the new Grails 3.x plugin:

compile("org.quartz-scheduler:quartz:2.2.1") {
    exclude group: 'slf4j-api', module: 'c3p0'
  }

It is recommended to use the latest stable, Grails 3+ compatible version of plugins. (Grails 2.x plugin versions will not work.)

Step 5 - Modify Package Imports

In Grails 3.x all internal APIs can be found in the org.grails package and public facing APIs in the grails package. The org.codehaus.groovy.grails package no longer exists.

All package declaration in sources should be modified for the new location of the respective classes. Example org.codehaus.groovy.grails.commons.GrailsApplication is now grails.core.GrailsApplication.

Step 5 - Migrate Plugin Specific Config to application.yml

Some plugins define a default configuration file. For example the Quartz plugin defines a file called grails-app/conf/DefaultQuartzConfig.groovy. In Grails 3.x this default configuration can be migrated to grails-app/conf/application.yml and it will automatically be loaded by Grails without requiring manual configuration merging.

Step 6 - Update plugin exclusions

Old plugins may have a pluginExcludes property defined that lists the patterns for any files that should not be included in the plugin package. This is normally used to exclude artifacts such as domain classes that are used in the plugin’s integration tests. You generally don’t want these polluting the target application.

This property is no longer sufficient in Grails 3, and nor can you use source paths. Instead, you must specify patterns that match the paths of the compiled classes. For example, imagine you have some test domain classes in the grails-app/domain/plugin/tests directory. You should first change the pluginExcludes value to

def pluginExcludes = ["plugin/test/**"]

and then add this block to the build file:

jar {
    exclude "plugin/test/**"
}

The easiest way to ensure these patterns work effectively is to put all your non-packaged class into a distinct Java package so that there is a clean separation between the main plugin classes and the rest.

Step 7 - Register ArtefactHandler Definitions

In Grails 3.x ArtefactHandler definitions written in Java need to be declared in a file called src/main/resources/META-INF/grails.factories since these need to be known at compile time.

If the ArtefactHandler is written in Groovy this step can be skipped as Grails will automatically create the grails.factories file during compilation.

The Quartz plugin requires the following definition to register the ArtrefactHandler:

grails.core.ArtefactHandler=grails.plugins.quartz.JobArtefactHandler

Step 8 - Migrate Code Generation Scripts

Many plugins previously defined command line scripts in Gant. In Grails 3.x command line scripts have been replaced by two new features: Code generation scripts and Gradle tasks.

If your script is doing simple code generation then for many cases a code generation script can replace an old Gant script.

The create-job script provided by the Quartz plugin in Grails 2.x was defined in scripts/CreateJob.groovy as:

includeTargets << grailsScript("_GrailsCreateArtifacts")

target(createJob: "Creates a new Quartz scheduled job") {
    depends(checkVersion, parseArguments)

    def type = "Job"
    promptForName(type: type)

    for (name in argsMap.params) {
        name = purgeRedundantArtifactSuffix(name, type)
        createArtifact(name: name, suffix: type, type: type, path: "grails-app/jobs")
        createUnitTest(name: name, suffix: type)
    }
}

setDefaultTarget 'createJob'

A replacement Grails 3.x compatible script can be created using the create-script command:

$ grails create-script create-job

Which creates a new script called src/main/scripts/create-job.groovy. Using the new code generation API it is simple to implement:

description("Creates a new Quartz scheduled job") {
    usage "grails create-job <<JOB NAME>>"
    argument name:'Job Name', description:"The name of the job"
}

model = model( args[0] )
render  template:"Job.groovy",
        destination: file( "grails-app/jobs/$model.packagePath/${model.simpleName}Job.groovy"),
        model: model

Please refer to the documentation on Creating Custom Scripts for more information.

Migrating More Complex Scripts Using Gradle Tasks

Using the old Grails 2.x build system it was relatively common to spin up Grails inside the command line. In Grails 3.x it is not possible to load a Grails application within a code generation script created by the create-script command.

Instead a new mechanism specific to plugins exists via the create-command command. The create-command command will create a new ApplicationCommand, for example the following command will execute a query:

import grails.dev.commands.*
import javax.sql.*
import groovy.sql.*
import org.springframework.beans.factory.annotation.*

class RunQueryCommand implements ApplicationCommand {

  @Autowired
  DataSource dataSource

  boolean handle(ExecutionContext ctx) {
      def sql = new Sql(dataSource)
      println sql.executeQuery("select * from foo")
      return true
  }
}

With this command in place once the plugin is installed into your local Maven cache you can add the plugin to both the build classpath and the runtime classpath of the application’s build.gradle file:

buildscript {
  ...
  dependencies {
    classpath "org.grails.plugins:myplugin:0.1-SNAPSHOT"
  }
}
...
dependencies {
  runtime "org.grails.plugins:myplugin:0.1-SNAPSHOT"
}

Grails will automatically create a Gradle task called runQuery and a command named run-query so both the following examples will execute the command:

$ grails run-query
$ gradle runQuery

Step 8 - Delete Files that were migrated or no longer used

You should now delete and cleanup the project of any files no longer required by Grails 3.x (BuildConfig.groovy, Config.groovy, DataSource.groovy etc.)