(Quick Reference)

19 Grails and Spring

Version: 5.2.4

19 Grails and Spring

This section is for advanced users and those who are interested in how Grails integrates with and builds on the Spring Framework. It is also useful for plugin developers considering doing runtime configuration Grails.

19.1 Configuring Additional Beans

Using the Spring Bean DSL

You can easily register new (or override existing) beans by configuring them in grails-app/conf/spring/resources.groovy which uses the Grails Spring DSL. Beans are defined inside a beans property (a Closure):

beans = {
    // beans here
}

As a simple example you can configure a bean with the following syntax:

import my.company.MyBeanImpl

beans = {
    myBean(MyBeanImpl) {
        someProperty = 42
        otherProperty = "blue"
    }
}

Once configured, the bean can be auto-wired into Grails artifacts and other classes that support dependency injection (for example BootStrap.groovy and integration tests) by declaring a public field whose name is your bean’s name (in this case myBean):

class ExampleController {

     def myBean
     ...
}

Using the DSL has the advantage that you can mix bean declarations and logic, for example based on the environment:

import grails.util.Environment
import my.company.mock.MockImpl
import my.company.MyBeanImpl

beans = {
    switch(Environment.current) {
        case Environment.PRODUCTION:
            myBean(MyBeanImpl) {
                someProperty = 42
                otherProperty = "blue"
            }
            break

        case Environment.DEVELOPMENT:
            myBean(MockImpl) {
                someProperty = 42
                otherProperty = "blue"
            }
            break
    }
}

The GrailsApplication object can be accessed with the application variable and can be used to access the Grails configuration (amongst other things):

import grails.util.Environment
import my.company.mock.MockImpl
import my.company.MyBeanImpl

beans = {
    if (application.config.my.company.mockService) {
        myBean(MockImpl) {
            someProperty = 42
            otherProperty = "blue"
        }
    } else {
        myBean(MyBeanImpl) {
            someProperty = 42
            otherProperty = "blue"
        }
    }
}
If you define a bean in resources.groovy with the same name as one previously registered by Grails or an installed plugin, your bean will replace the previous registration. This is a convenient way to customize behavior without resorting to editing plugin code or other approaches that would affect maintainability.

Using XML

Beans can also be configured using a grails-app/conf/spring/resources.xml. In earlier versions of Grails this file was automatically generated for you by the run-app script, but the DSL in resources.groovy is the preferred approach now so it isn’t automatically generated now. But it is still supported - you just need to create it yourself.

This file is typical Spring XML file and the Spring documentation has an excellent reference on how to configure Spring beans.

The myBean bean that we configured using the DSL would be configured with this syntax in the XML file:

<bean id="myBean" class="my.company.MyBeanImpl">
    <property name="someProperty" value="42" />
    <property name="otherProperty" value="blue" />
</bean>

Like the other bean it can be auto-wired into any class that supports dependency injection:

class ExampleController {

     def myBean
}

Referencing Existing Beans

Beans declared in resources.groovy or resources.xml can reference other beans by convention. For example if you had a BookService class its Spring bean name would be bookService, so your bean would reference it like this in the DSL:

beans = {
    myBean(MyBeanImpl) {
        someProperty = 42
        otherProperty = "blue"
        bookService = ref("bookService")
    }
}

or like this in XML:

<bean id="myBean" class="my.company.MyBeanImpl">
    <property name="someProperty" value="42" />
    <property name="otherProperty" value="blue" />
    <property name="bookService" ref="bookService" />
</bean>

The bean needs a public setter for the bean reference (and also the two simple properties), which in Groovy would be defined like this:

package my.company

class MyBeanImpl {
    Integer someProperty
    String otherProperty
    BookService bookService // or just "def bookService"
}

or in Java like this:

package my.company;

class MyBeanImpl {

    private BookService bookService;
    private Integer someProperty;
    private String otherProperty;

    public void setBookService(BookService theBookService) {
        this.bookService = theBookService;
    }

    public void setSomeProperty(Integer someProperty) {
        this.someProperty = someProperty;
    }

    public void setOtherProperty(String otherProperty) {
        this.otherProperty = otherProperty;
    }
}

Using ref (in XML or the DSL) is very powerful since it configures a runtime reference, so the referenced bean doesn’t have to exist yet. As long as it’s in place when the final application context configuration occurs, everything will be resolved correctly.

For a full reference of the available beans see the plugin reference in the reference guide.

19.2 Runtime Spring with the Beans DSL

This Bean builder in Grails aims to provide a simplified way of wiring together dependencies that uses Spring at its core.

In addition, Spring’s regular way of configuration (via XML and annotations) is static and difficult to modify and configure at runtime, other than programmatic XML creation which is both error prone and verbose. Grails' BeanBuilder changes all that by making it possible to programmatically wire together components at runtime, allowing you to adapt the logic based on system properties or environment variables.

This enables the code to adapt to its environment and avoids unnecessary duplication of code (having different Spring configs for test, development and production environments)

The BeanBuilder class

Grails provides a grails.spring.BeanBuilder class that uses dynamic Groovy to construct bean definitions. The basics are as follows:

import org.apache.commons.dbcp.BasicDataSource
import org.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean
import org.springframework.context.ApplicationContext
import grails.spring.BeanBuilder

def bb = new BeanBuilder()

bb.beans {

    dataSource(BasicDataSource) {
        driverClassName = "org.h2.Driver"
        url = "jdbc:h2:mem:grailsDB"
        username = "sa"
        password = ""
    }

    sessionFactory(ConfigurableLocalSessionFactoryBean) {
        dataSource = ref('dataSource')
        hibernateProperties = ["hibernate.hbm2ddl.auto": "create-drop",
                               "hibernate.show_sql":     "true"]
    }
}

ApplicationContext appContext = bb.createApplicationContext()
Within plugins and the grails-app/conf/spring/resources.groovy file you don’t need to create a new instance of BeanBuilder. Instead the DSL is implicitly available inside the doWithSpring and beans blocks respectively.

This example shows how you would configure Hibernate with a data source with the BeanBuilder class.

Each method call (in this case dataSource and sessionFactory calls) maps to the name of the bean in Spring. The first argument to the method is the bean’s class, whilst the last argument is a block. Within the body of the block you can set properties on the bean using standard Groovy syntax.

Bean references are resolved automatically using the name of the bean. This can be seen in the example above with the way the sessionFactory bean resolves the dataSource reference.

Certain special properties related to bean management can also be set by the builder, as seen in the following code:

sessionFactory(ConfigurableLocalSessionFactoryBean) { bean ->
    // Autowiring behaviour. The other option is 'byType'. <<autowire>>
    bean.autowire = 'byName'
    // Sets the initialisation method to 'init'. [init-method]
    bean.initMethod = 'init'
    // Sets the destruction method to 'destroy'. [destroy-method]
    bean.destroyMethod = 'destroy'
    // Sets the scope of the bean. <<scope>>
    bean.scope = 'request'
    dataSource = ref('dataSource')
    hibernateProperties = ["hibernate.hbm2ddl.auto": "create-drop",
                           "hibernate.show_sql":     "true"]
}

The strings in square brackets are the names of the equivalent bean attributes in Spring’s XML definition.

Using BeanBuilder with Spring MVC

Include the grails-spring-<version>.jar file in your classpath to use BeanBuilder in a regular Spring MVC application. Then add the following <context-param> values to your /WEB-INF/web.xml file:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.groovy</param-value>
</context-param>

<context-param>
    <param-name>contextClass</param-name>
    <param-value>
      grails.web.servlet.context.GrailsWebApplicationContext
    </param-value>
</context-param>

Then create a /WEB-INF/applicationContext.groovy file that does the rest:

import org.apache.commons.dbcp.BasicDataSource

beans {
    dataSource(BasicDataSource) {
        driverClassName = "org.h2.Driver"
        url = "jdbc:h2:mem:grailsDB"
        username = "sa"
        password = ""
    }
}

Loading Bean Definitions from the File System

You can use the BeanBuilder class to load external Groovy scripts that define beans using the same path matching syntax defined here. For example:

def bb = new BeanBuilder()
bb.loadBeans("classpath:*SpringBeans.groovy")

def applicationContext = bb.createApplicationContext()

Here the BeanBuilder loads all Groovy files on the classpath ending with SpringBeans.groovy and parses them into bean definitions. An example script can be seen below:

import org.apache.commons.dbcp.BasicDataSource
import org.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean

beans {

    dataSource(BasicDataSource) {
        driverClassName = "org.h2.Driver"
        url = "jdbc:h2:mem:grailsDB"
        username = "sa"
        password = ""
    }

    sessionFactory(ConfigurableLocalSessionFactoryBean) {
        dataSource = dataSource
        hibernateProperties = ["hibernate.hbm2ddl.auto": "create-drop",
                               "hibernate.show_sql":     "true"]
    }
}

Adding Variables to the Binding (Context)

If you’re loading beans from a script you can set the binding to use by creating a Groovy Binding:

def binding = new Binding()
binding.maxSize = 10000
binding.productGroup = 'finance'

def bb = new BeanBuilder()
bb.binding = binding
bb.loadBeans("classpath:*SpringBeans.groovy")

def ctx = bb.createApplicationContext()

Then you can access the maxSize and productGroup properties in your DSL files.

19.3 The BeanBuilder DSL Explained

Using Constructor Arguments

Constructor arguments can be defined using parameters to each bean-defining method. Put them after the first argument (the Class):

bb.beans {
    exampleBean(MyExampleBean, "firstArgument", 2) {
        someProperty = [1, 2, 3]
    }
}

This configuration corresponds to a MyExampleBean with a constructor that looks like this:

MyExampleBean(String foo, int bar) {
   ...
}

Configuring the BeanDefinition (Using factory methods)

The first argument to the closure is a reference to the bean configuration instance, which you can use to configure factory methods and invoke any method on the AbstractBeanDefinition class:

bb.beans {
    exampleBean(MyExampleBean) { bean ->
        bean.factoryMethod = "getInstance"
        bean.singleton = false
        someProperty = [1, 2, 3]
    }
}

As an alternative you can also use the return value of the bean defining method to configure the bean:

bb.beans {
    def example = exampleBean(MyExampleBean) {
        someProperty = [1, 2, 3]
    }
    example.factoryMethod = "getInstance"
}

Using Factory beans

Spring defines the concept of factory beans and often a bean is created not directly from a new instance of a Class, but from one of these factories. In this case the bean has no Class argument and instead you must pass the name of the factory bean to the bean defining method:

bb.beans {

    myFactory(ExampleFactoryBean) {
        someProperty = [1, 2, 3]
    }

    myBean(myFactory) {
        name = "blah"
    }
}

Another common approach is provide the name of the factory method to call on the factory bean. This can be done using Groovy’s named parameter syntax:

bb.beans {

    myFactory(ExampleFactoryBean) {
        someProperty = [1, 2, 3]
    }

    myBean(myFactory: "getInstance") {
        name = "blah"
    }
}

Here the getInstance method on the ExampleFactoryBean bean will be called to create the myBean bean.

Creating Bean References at Runtime

Sometimes you don’t know the name of the bean to be created until runtime. In this case you can use a string interpolation to invoke a bean defining method dynamically:

def beanName = "example"
bb.beans {
    "${beanName}Bean"(MyExampleBean) {
        someProperty = [1, 2, 3]
    }
}

In this case the beanName variable defined earlier is used when invoking a bean defining method. The example has a hard-coded value but would work just as well with a name that is generated programmatically based on configuration, system properties, etc.

Furthermore, because sometimes bean names are not known until runtime you may need to reference them by name when wiring together other beans, in this case using the ref method:

def beanName = "example"
bb.beans {

    "${beanName}Bean"(MyExampleBean) {
        someProperty = [1, 2, 3]
    }

    anotherBean(AnotherBean) {
        example = ref("${beanName}Bean")
    }
}

Here the example property of AnotherBean is set using a runtime reference to the exampleBean. The ref method can also be used to refer to beans from a parent ApplicationContext that is provided in the constructor of the BeanBuilder:

ApplicationContext parent = ...//
def bb = new BeanBuilder(parent)
bb.beans {
    anotherBean(AnotherBean) {
        example = ref("${beanName}Bean", true)
    }
}

Here the second parameter true specifies that the reference will look for the bean in the parent context.

Using Anonymous (Inner) Beans

You can use anonymous inner beans by setting a property of the bean to a block that takes an argument that is the bean type:

bb.beans {

    marge(Person) {
        name = "Marge"
        husband = { Person p ->
            name = "Homer"
            age = 45
            props = [overweight: true, height: "1.8m"]
        }
        children = [ref('bart'), ref('lisa')]
    }

    bart(Person) {
        name = "Bart"
        age = 11
    }

    lisa(Person) {
        name = "Lisa"
        age = 9
    }
}

In the above example we set the marge bean’s husband property to a block that creates an inner bean reference. Alternatively if you have a factory bean you can omit the type and just use the specified bean definition instead to setup the factory:

bb.beans {

    personFactory(PersonFactory)

    marge(Person) {
        name = "Marge"
        husband = { bean ->
            bean.factoryBean = "personFactory"
            bean.factoryMethod = "newInstance"
            name = "Homer"
            age = 45
            props = [overweight: true, height: "1.8m"]
        }
        children = [ref('bart'), ref('lisa')]
    }
}

Abstract Beans and Parent Bean Definitions

To create an abstract bean definition define a bean without a Class parameter:

class HolyGrailQuest {
    def start() { println "lets begin" }
}
class KnightOfTheRoundTable {

    String name
    String leader
    HolyGrailQuest quest

    KnightOfTheRoundTable(String name) {
        this.name = name
    }

    def embarkOnQuest() {
        quest.start()
    }
}
import grails.spring.BeanBuilder

def bb = new BeanBuilder()
bb.beans {
    abstractBean {
        leader = "Lancelot"
    }
    ...
}

Here we define an abstract bean that has a leader property with the value of "Lancelot". To use the abstract bean set it as the parent of the child bean:

bb.beans {
    ...
    quest(HolyGrailQuest)

    knights(KnightOfTheRoundTable, "Camelot") { bean ->
        bean.parent = abstractBean
        quest = ref('quest')
    }
}
When using a parent bean you must set the parent property of the bean before setting any other properties on the bean!

If you want an abstract bean that has a Class specified you can do it this way:

import grails.spring.BeanBuilder

def bb = new BeanBuilder()
bb.beans {

    abstractBean(KnightOfTheRoundTable) { bean ->
        bean.'abstract' = true
        leader = "Lancelot"
    }

    quest(HolyGrailQuest)

    knights("Camelot") { bean ->
        bean.parent = abstractBean
        quest = quest
    }
}

In this example we create an abstract bean of type KnightOfTheRoundTable and use the bean argument to set it to abstract. Later we define a knights bean that has no Class defined, but inherits the Class from the parent bean.

Using Spring Namespaces

Since Spring 2.0, users of Spring have had easier access to key features via XML namespaces. You can use a Spring namespace in BeanBuilder by declaring it with this syntax:

xmlns context:"http://www.springframework.org/schema/context"

and then invoking a method that matches the names of the Spring namespace tag and its associated attributes:

context.'component-scan'('base-package': "my.company.domain")

You can do some useful things with Spring namespaces, such as looking up a JNDI resource:

xmlns jee:"http://www.springframework.org/schema/jee"

jee.'jndi-lookup'(id: "dataSource", 'jndi-name': "java:comp/env/myDataSource")

This example will create a Spring bean with the identifier dataSource by performing a JNDI lookup on the given JNDI name. With Spring namespaces you also get full access to all of the powerful AOP support in Spring from BeanBuilder. For example given these two classes:

class Person {

    int age
    String name

    void birthday() {
        ++age;
    }
}
class BirthdayCardSender {

    List peopleSentCards = []

    void onBirthday(Person person) {
        peopleSentCards << person
    }
}

You can define an aspect that uses a pointcut to detect whenever the birthday() method is called:

xmlns aop:"http://www.springframework.org/schema/aop"

fred(Person) {
    name = "Fred"
    age = 45
}

birthdayCardSenderAspect(BirthdayCardSender)

aop {
    config("proxy-target-class": true) {
        aspect(id: "sendBirthdayCard", ref: "birthdayCardSenderAspect") {
            after method: "onBirthday",
            pointcut: "execution(void ..Person.birthday()) and this(person)"
        }
    }
}

19.4 Property Placeholder Configuration

Grails supports the notion of property placeholder configuration through an extended version of Spring’s PropertyPlaceholderConfigurer.

Settings defined in either ConfigSlurper scripts or Java properties files can be used as placeholder values for Spring configuration in grails-app/conf/spring/resources.xml and grails-app/conf/spring/resources.groovy. For example given the following entries in grails-app/conf/application.groovy (or an externalized config):

database.driver="com.mysql.jdbc.Driver"
database.dbname="mysql:mydb"

You can then specify placeholders in resources.xml as follows using the familiar ${..} syntax:

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName">
        <value>${database.driver}</value>
    </property>
    <property name="url">
        <value>jdbc:${database.dbname}</value>
    </property>
 </bean>

To specify placeholders in resources.groovy you need to use single quotes:

dataSource(org.springframework.jdbc.datasource.DriverManagerDataSource) {
    driverClassName = '${database.driver}'
    url = 'jdbc:${database.dbname}'
}

This sets the property value to a literal string which is later resolved against the config by Spring’s PropertyPlaceholderConfigurer.

A better option for resources.groovy is to access properties through the grailsApplication variable:

dataSource(org.springframework.jdbc.datasource.DriverManagerDataSource) {
    driverClassName = grailsApplication.config.database.driver
    url = "jdbc\:${grailsApplication.config.database.dbname}"
}

Using this approach will keep the types as defined in your config.

19.5 Property Override Configuration

Grails supports setting of bean properties via configuration.

You define a beans block with the names of beans and their values:

beans {
    bookService {
        webServiceURL = "http://www.amazon.com"
    }
}

The general format is:

<<bean name>>.<<property name>> = <<value>>

The same configuration in a Java properties file would be:

beans.bookService.webServiceURL=http://www.amazon.com

19.6 Spring Boot Actuators

Spring Boot Actuator endpoints allow you to monitor and interact with your application. Spring Boot includes a number of built-in endpoints. For example the health endpoint provides basic application health information.

These endpoints are disabled by default since Grails 3.1.8.

You can enable actuator endpoints in your application.yml as follows:

grails-app/conf/application.yml
management:
  endpoints:
    enabled-by-default: true