(Quick Reference)
3 Upgrading from Grails 2.x - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 3.0.17
3 Upgrading from Grails 2.x
Grails 3.0 is a complete ground up rewrite of Grails and introduces new concepts and components for many parts of the framework.
When upgrading an application or plugin from Grails 3.0 there are many areas to consider including:
- Removal of dynamic scaffolding from Grails 3.0.0 till 3.0.4 when it was re-introduced
- Removal of before and after interceptors
- Project structure differences
- File location differences
- Configuration differences
- Package name differences
- Legacy Gant Scripts
- Gradle Build System
- Changes to Plugins
- Source vs Binary Plugins
The best approach to take when upgrading a plugin or application (and if your application is using several plugins the plugins will need upgrading first) is to create a new Grails 3.0 application of the same name and copy the source files into the correct locations in the new application.
Removal of before and after interceptors
Before and after interceptors were removed. So all
beforeInterceptor
and
afterInterceptor
need to be replaced by Stand alone interceptors.
File Location Differences
The location of certain files have changed or been replaced with other files in Grails 3.0. The following table lists old default locations and their respective new locations:
Old Location | New Location | Description |
---|
grails-app/conf/BuildConfig.groovy | build.gradle | Build time configuration is now defined in a Gradle build file |
grails-app/conf/Config.groovy | grails-app/conf/application.groovy | Renamed for consistency with Spring Boot |
grails-app/conf/UrlMappings.groovy | grails-app/controllers/UrlMappings.groovy | Moved since grails-app/conf is not a source directory anymore |
grails-app/conf/BootStrap.groovy | grails-app/init/BootStrap.groovy | Moved since grails-app/conf is not a source directory anymore |
scripts | src/main/scripts | Moved for consistency with Gradle |
src/groovy | src/main/groovy | Moved for consistency with Gradle |
src/java | src/main/groovy | Moved for consistency with Gradle |
test/unit | src/test/groovy | Moved for consistency with Gradle |
test/integration | src/integration-test/groovy | Moved for consistency with Gradle |
web-app | src/main/webapp or src/main/resources/ | Moved for consistency with Gradle |
*GrailsPlugin.groovy | src/main/groovy | The plugin descriptor moved to a source directory |
src/main/resources/public
is recommended as
src/main/webapp
only gets included in WAR packaging but not in JAR packaging.
For plugins the plugin descriptor (a Groovy file ending with "GrailsPlugin") which was previously located in the root of the plugin directory should be moved to the
src/main/groovy
directory under an appropriate package.
New Files Not Present in Grails 2.x
The reason it is best to create a new application and copy your original sources to it is because there are a number of new files that are not present in Grails 2.x by default. These include:
File | Description |
---|
build.gradle | The Gradle build descriptor located in the root of the project |
gradle.properties | Properties file defining the Grails and Gradle versions |
grails-app/conf/logback.groovy | Logging previously defined in Config.groovy is now defined using Logback |
grails-app/conf/application.yml | Configuration can now also be defined using YAML |
grails-app/init/PACKAGE_PATH/Application.groovy | The Application class used By Spring Boot to start the application |
Files Not Present in Grails 3.x
Some files that were previously created by Grails 2.x are no longer created. These have either been removed or an appropriate replacement added. The following table lists files no longer in use:
File | Description |
---|
application.properties | The application name and version is now defined in build.gradle |
grails-app/conf/DataSource.groovy | Merged together into application.yml |
lib | Dependency resolution should be used to resolve JAR files |
web-app/WEB-INF/applicationContext.xml | Removed, beans can be defined in grails-app/conf/spring/resources.groovy |
src/templates/war/web.xml | Grails 3.0 no longer requires web.xml. Customizations can be done via Spring |
web-app/WEB-INF/sitemesh.xml | Removed, sitemesh filter no longer present. |
web-app/WEB-INF/tld | Removed, can be restored in src/main/webapp or src/main/resources/WEB-INF |
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 {
…
}
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'
}
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 - 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 7 - 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.)
3.2 Upgrading Applications
Upgrading applications to Grails 3.x will require that you upgrade all plugins the application uses first, hence you should follow the steps in the previous section to first upgrade your plugins.
Step 1 - Create a New Application
Once the plugins are Grails 3.x compatible you can upgrade the application. To upgrade an application it is again best to create a new Grails 3 application using the "web" profile:
$ grails create-app myapp
$ cd myapp
Step 2 - Migrate Sources
The next step is to copy the sources from the original Grails 2 application to the Grails 3 application:
# first the sources
cp -rf ../old_app/src/groovy/ src/main/groovy
cp -rf ../old_app/src/java/ src/main/groovy
cp -rf ../old_app/grails-app/ grails-app# then the tests
cp -rf ../old_app/test/unit/ src/test/groovy
mkdir -p src/integration-test/groovy
cp -rf ../old_app/test/integration/ src/integration-test/groovy
Step 3 - Update the Gradle build with required dependencies
The repositories and dependencies defined in
grails-app/conf/BuildConfig.groovy
of the original Grails 2.x application will need to be defined in
build.gradle
of the new Grails 3.x application.
Step 4 - 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 Configuration
The configuration of the application will need to be migrated, this can normally be done by simply renaming
grails-app/conf/Config.groovy
to
grails-app/conf/application.groovy
and merging the content of
grails-app/conf/DataSource.groovy
into
grails-app/conf/application.groovy
.
Note however that Log4j has been replaced by
grails-app/conf/logback.groovy
for logging, so any logging configuration in
grails-app/conf/Config.groovy
should be migrated to
logback format.
Step 6 - Migrate web.xml Modifications to Spring
If you have a modified
web.xml
template then you will need to migrate this to Spring as Grails 3.x does not use a web.xml (although it is still possible to have on in
src/main/webapp/WEB-INF/web.xml
).
New servlets and filters can be registered as Spring beans or with
ServletRegistrationBean and
FilterRegistrationBean respectively.
Step 7 - Migrate Static Assets not handled by Asset Pipeline
If you have static assets in your
web-app
directory of your Grails 2.x application such as HTML files, TLDs etc. these need to be moved. For public assets such as static HTML pages and so on these should go in
src/main/resources/public
.
TLD descriptors and non public assets should go in
src/main/resources/WEB-INF
.
As noted earlier,
src/main/webapp
folder can also be used for this purpose but it is not recommended.
Step 8 - Migrate Tests
Once the package names are corrected unit tests will continue to run, however any tests that extend the deprecated and removed JUnit 3 hierarchy will need to be migrated to Spock or JUnit 4.
Integration tests will need to be annotated with the
Integration annotation and should not extend GroovyTestCase or any JUnit 3 super class.