(Quick Reference)

3 Upgrading from Grails 3.2.x

Version: 3.3.5

3 Upgrading from Grails 3.2.x

Grails 3.3 includes several changes to dependencies and Event publishing that may require changes to your application if you are upgrading from Grails 3.2.x.

For information on upgrading from versions of Grails prior to Grails 3.2.x, see the Grails 3.2.x documentation on upgrading

GORM 6.1 Upgrade

GORM 6.1 includes changes that may require you to change your application.

GORM Async Now Optional

Notably grails-datastore-gorm-async is now optional and if you use the task method of GORM you will need to manually implement the AsyncEntity trait.

Domain Autowiring Disabled

Domain class autowiring is disabled by default due to its impact on performance. You can re-enable autowiring for all domains using the Default Mapping setting:

grails-app/conf/application.groovy
grails.gorm.default.mapping = {
        autowire true
}

You can turn it on only for one domain class:

grails-app/domain/demo/Book.groovy
class Book {
    BookService bookService

    String name

    static mapping {
       autowire true
    }
    ...
    ..
    .
}

Flush Mode now COMMIT by Default

The default flush mode has been change to COMMIT due to the impact the previous flush mode AUTO has on read performance. You can switch back to AUTO use the hibernate.flush.mode setting in application.yml

TransactionManager Chaining for Multiple Data Sources Disabled by Default

In previous versions of Grails for multiple data sources a best effort transaction chain was used to attempt to manage a transaction across all configured data sources.

As of Grails 3.3 this is disabled as it caused confusion since it isn’t a true XA implementation and also impacts performance as for every transaction you have a transaction for each data source bound regardless if that is the actual requirement.

If your application depends on this feature you can re-enable it with the following configuration:

grails:
  transaction:
    chainedTransactionManager:
      enabled: true
      blacklistPattern: '.*'

Tomcat JDBC

GORM 6.1 and above now supports multiple connection pool options, so the tomcat-jdbc dependency is now optional. If you are upgrading you may need to add it (or another pool implementation) to your build.gradle:

build.gradle
runtime 'org.apache.tomcat:tomcat-jdbc'

@TestMixin, @TestFor etc. Deprecated

Since Grails 3.3, the Grails Testing Support Framework is used for all unit tests. The new testing framework is much simpler and provides a set of traits that improve readability, debugging and code completion. An example hello world test can be seen below:

import spock.lang.Specification
import grails.testing.web.controllers.ControllerUnitTest

class HelloControllerTests extends Specification implements ControllerUnitTest<HelloController> {

    void "Test message action"() {
        when:"The message action is invoked"
        controller.message()

        then:"Hello is returned"
        response.text == 'Hello'
    }
}

For more information on writing tests with Grails Testing Support see the dedicated documentation.

To simplify upgrades you can can still use the previous AST transformation based framework by adding the following dependency to your Grails application:

build.gradle
testCompile "org.grails:grails-test-mixins:3.3.0"

Default Logger Name

In previous versions of Grails, if you did not specify a logger in the controller, service, etc, a log variable was injected for you. The naming convention of that logger was grails.app.${artefactType}.package.class. For example:

grails.app.controllers.foo.bar.MyController

To make the logger names more intuitive as well as to increase consistency between custom code, plugin dependencies, and third party libraries, the grails.app.${artefactType} convention was removed. The same class as above will now be referenced the same way as any standard class. The way the log variable gets injected was also changed to defer to the Slf4j transformation. That means it is no longer necessary to check if (log.isDebugEnabled()).

The downside of this change is that it isn’t immediately simple to set up the same logging configuration for all controllers, for example. We think this can be solved with a package naming strategy that represents what your requirements are.

Dependency Alterations

In an effort to trim the size of the produced WAR file by Grails several dependencies are no longer resolved transtively including:

  • commons-lang

  • gson

  • aspectjweaver

  • aspectjrt

  • ehcache

If you are upgrading and have referenced any of these dependencies in your application you may need to alter your build to reference them.

Spring Boot 1.5.x

Spring Boot 1.5.x removes a number of deprecated classes, notably several of the classes within the org.springframework.boot.context.embedded package.

If your application is referencing any of the classes within this package you will need to alter your imports to use org.springframework.boot.web.servlet instead.

All classes in the org.springframework.boot.context.web package have been deprecated and relocated per the Spring Boot 1.4 Release Notes.

Reactor 2.x Deprecated and Removed

Since Reactor 2.x is no longer being maintained and a new EventBus abstraction has been implemented, Reactor 2.x and all its dependencies have been removed.

A compatibility layer has been provided to allow classes compiled with the previous version that uses Reactor to run, however all plugins and application code should be re-compiled and direct references to Reactor 2.x should be removed.

Externalized Plugins

Several plugins and libraries have been separated from Grails core into standalone projects. The following table summarizes the previous artefact id, the new artefact id and the location of the new sources:

Table 1. Externalized Plugins
Sources Previous Artefact ID New Artefact ID

GSP

org.grails:grails-plugin-gsp

org.grails.plugins:gsp

Converters

org.grails:grails-plugin-converters

org.grails.plugins:converters

Async

org.grails:grails-plugin-async

org.grails.plugins:async

Events

org.grails:grails-plugin-events

org.grails.plugins:events

Testing Mixin

org.grails:grails-plugin-testing

org.grails:grails-test-mixins

New Cache Plugin

The Cache plugin has been re-written to no longer use Spring proxies but AST transformations instead.

This improves startup and runtime performance, however one caveat is controller action response caching is no longer supported.

Grails Domain Class API Deprecated

The legacy classes that represent domain classes and their properties have been deprecated in favor of the mapping context API.

The reason for this is to avoid duplicate parsing of the same class data between GORM and Grails and reduce overall startup time.

The internal implementation of the methods in those classes now delegates to the mapping context. Due to that change, information about your domain classes is not available until the application context is available.

In previous versions of Grails it was possible to access GrailsDomainClass instances and inspect the GrailsDomainClassProperty properties inside of the doWithSpring method in a plugin, for example.

If you have code that follows that example, an error will be thrown that looks like "The method …​ cannot be accessed before GORM has initialized". The solution is to move any logic that executes before the context is available to somewhere else that executes after the context is available.

All code that uses the GrailsDomainClass or GrailsDomainClassProperty classes should be re-written to use the mapping context api.

To get started, inject the grailsDomainClassMappingContext bean. See the api documentation for more information on the MappingContext, PersistentEntity (GrailsDomainClass), and PersistentProperty (GrailsDomainClassProperty).

The following table summarizes the deprecations:

Table 2. Deprecated Grails Domain Class API
Deprecated Class or Interface Replacement

GrailsDomainClass

PersistentEntity

GrailsDomainClassProperty

PersistentProperty

The GrailsDomainClassProperty interface had many more methods to evaluate the type of the property such as isOneToOne, isOneToMany etc. and while PersistentProperty does not provide direct equivalents you can use instanceof as a replacement using one of the subclasses found in the org.grails.datastore.mapping.model.types package.

The following table summarizes this:

Table 3. Deprecated GrailsDomainClassProperty method replacements
Deprecated Class or Interface Replacement

isAssociation()

property instanceof Association

isOneToOne()

property instanceof OneToOne

isManyToOne()

property instanceof ManyToOne

isEmbedded()

property instanceof Embedded

isManyToMany()

property instanceof ManyToMany

isBasicCollectionType()

property instanceof Basic

Grails Validator and ConstrainedProperty API Deprecated

Grails' previous validation API (part of the grails.validation package) has been externalized into a separate project not part of the grails-datastore-gorm-validation dependency.

This means that some interfaces previously part of Grails core are deprecated and the replacment in the external project should be used, including:

Table 4. Deprecated Grails Validator Classes
Deprecated Class or Interface Replacement

GrailsDomainClassValidator

PersistentEntityValidator

CascadingValidator

CascadingValidator

ConstrainedProperty

ConstrainedProperty

Constraint

Constraint

AbstractConstraint

AbstractConstraint

Generally all classes within the org.grails.validation package are now deprecated.

To register a custom constraint you should now use the ConstraintRegistry interface instead.

The default ValidatorRegistry implements the ConstraintRegistry interface and can be autowired into any controller or service by declaring the following property:

ValidatorRegistry gormValidatorRegistry
...
gormValidatorRegistry.addConstraint(MyConstraint)

Grails' Transactional AST Transforms Deprecated

The transaction management AST transforms that shipped as part of Grails have been ported to GORM and improved to make it possible to use them outside of Grails.

With this in mind Grails' versions of @Transactional and @Rollback found within the grails.transaction package have been deprecated in favour of GORMs versions. You should change your imports to use the GORM version instead of the Grails version.

The following table summarizes the deprecated classes and their replacements:

Table 5. Deprecated Grails Transaction Transforms
Deprecated Class or Interface Replacement

grails.transaction.Transactional

grails.gorm.transactions.Transactional

grails.transaction.Rollback

grails.gorm.transactions.Rollback

grails.transaction.NotTransactional

grails.gorm.transactions.NotTransactional

Spring Proxies for Services No Longer Supported

Earlier versions of Grails supported the use of Spring proxies for transaction management, but this support was disabled by default in Grails 3.2.x and developers encouraged to use the @Transactional AST transforms instead.

In Grails 3.3 the support for Spring proxies has been dropped completely and you must use Grails' AST transforms.

If you wish to continue to use Spring proxies for transaction management you will have to configure them manually use the appropriate Spring configuration.

Datasource Plugin Refactor

In previous versions of Grails and GORM the multiple data sources support relied on Grails' data sources plugin. The logic for configuring multiple data sources has moved to GORM and as a result of major changes to the dataSources plugin, beans for the lazy and unproxied representation of a dataSource are no longer available.

The beans include:

  • dataSourceUnproxied

  • dataSourceLazy

If you are referencing these beans you will need to remove these references and unwrap the single dataSource proxy manually.

Task Groups

Several tasks have had their groups changed to better reflect their purpose. If you’re having trouble finding a task, look through the different groups.

Legacy JSON Builder Option Removed

In a previous version of Grails, the JSON builder used by default for rendering JSON inline was changed. The previous behavior of using converters to build the JSON was able to be re-enabled by setting grails.json.legacy.builder to true. In Grails 3.3 that setting has been removed and it is no longer possible to use the legacy converter API to render JSON inline via the render method.