Using Groovy Based Spring Configuration

A guide to using Groovy for Spring configuration both JavaConfig and Grails style and adding Groovy configuration to web.xml using ContextLoaderListener..

Object Partners

Introduction

The Spring framework began with using XML as the only means for bean configuration. As Spring grew and more features were added to the framework, XML configuration got to be very verbose and it took a lot of XML to do simple things. Java configuration was added to solve this problem as beans could be created programmatically and method calls could be made. This was a big improvement from the overly verbose XML configuration that has been the staple of Spring since its inception. In this post, I would like to expand on this concept by using Groovy in place of Java for the annotation driven configuration as well as the Grails style of configuration added in Spring 4.

Using Groovy as Java Configuration

Since version 4, Spring added support for Groovy, so any Groovy classes can be Spring beans and Groovy can be used in place of Java for annotation driven configuration. The benefit of this is that all the features of Groovy can be used when creating a bean in Spring. Below are a couple examples of configuration in Java vs Groovy.

The first example is a Java configuration which creates a map and a list.

package com.yourcompany.config;

import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfiguration {

    @Bean
    public Map<Integer, String> people() {
        Map<Integer, String> peopleMap = new HashMap<Integer, String>();
        peopleMap.put(1, "Joe");
        peopleMap.put(2, "Bill");
        peopleMap.put(3, "Jane");
        peopleMap.put(4, "Mary");

        return peopleMap;
    }

    @Bean
    public List<String> places() {
        List<String> placesList = new ArrayList();
        placesList.add("Minneapolis");
        placesList.add("St Paul");
        placesList.add("Chicago");
        placesList.add("Denver");

        return placesList;
    }
}

The code is fairly standard, but now here is the same example written in Groovy.

package com.yourcompany.config

import java.util.Map
import java.util.List

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class SpringConfiguration {

    @Bean
    Map<Integer, String> people() {
        [1: 'Joe', 2: 'Bill', 3: 'Jane', 4: 'Mary']
    }

    @Bean
    List<String> places() {
        ['Minneapolis', 'St Paul', 'Chicago', 'Denver']
    }
}

The code is much more concise in creating the map and list, but any of Groovy’s features can be used, such as closures, XML and JSON slupers which all make the configuration more concise. Below is an example of using Groovy’s XmlSlurper to load in an XML file and put the results in a map to be used as a Spring bean. First the XML file.

<?xml version="1.0" encoding="UTF-8"?>
<people>
    <person nickName="jbrown" firstName="Joe" lastName="Brown" />
    <person nickName="banderson" firstName="Bill" lastName="Anderson" />
    <person nickName="jjohnson" firstName="Jane" lastName="Johnson" />
    <person nickName="msmith" firstName="Mary" lastName="Smith" />
</people>

Next is the Groovy configuration class.

package com.yourcompany.config

import com.mycompany.Person

import java.util.Map
import java.util.List

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class SlurperConfiguration {

    @Bean
    Map<String, Person> people() {
        def peopleMap = [:]
        def peopleSluper = new XmlSlurper().parse(new File('people.xml'))

        peopleSluper.person.each {
            peopleMap.put(it.@nickName.text(), new Person(firstName: it.@firstName.text(), lastName: it.@lastName.text()))
        }

        peopleMap
    }

}

It goes without saying that the amount of Java code to accomplish what is above could easily be doubled or even tripled.

Using Grails Style Groovy Configuration

Another new feature of Spring 4 was the addition of Grails style Groovy configuration. This style uses Groovys configuration style to create Spring beans and is used in Grails in resources.groovy and allows the use of all the Groovy features as well as concise syntax. Below is an example.

import org.springframework.jndi.JndiObjectFactoryBean
import com.mycompany.Person
import com.mycompany.Customer

beans {
    // Other name spaces can be imported this way
    xmlns([context:'http://www.springframework.org/schema/context', aop:'http://www.springframework.org/schema/aop'])

    // Allows import of other configuration files, both XML and Groovy
    importBeans('classpath:anXmlContext.xml')
    importBeans('classpath:anotherGroovyContext.groovy')

    // Calls to specific name space calls are done using a more Groovy like syntax.  Any calls with dashes need quotes around them.
    context.'component-scan'('base-package': 'com.mycompany.somepackage')
    aop.'aspectj-autoproxy'()

    // Create a data source, in this case the bean ID is 'myDataSource' and the class is 'JndiObjectFactoryBean'
    // and the 'jndiName' property is set with 'jdbc/myDataSource'
    myDataSource(JndiObjectFactoryBean) {
        jndiName = 'jdbc/myDataSource'
    }

    // A Person instance is created with firstName and lastName
    person(Person) {
        firstName = 'Bill'
        lastName = 'Jones'
        // References to other beans can be done in two ways
        dataSource = myDataSource // or dataSource = ref('myDataSource')
    }

    // Person is passed in as a constructor property
    customer(Customer, person: person)
}

Groovy’s configuration style is well suited for use for Spring configuration and adds the ability to programmatically add in method calls if necessary.

Adding a Groovy Configuration to web.xml

Spring version 4.1 added a way to get a Groovy configuration file added to web.xml with the addition of GroovyWebApplicationContext, the below example of web.xml shows how to configure it.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    ...

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.GroovyWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/applicationContext.groovy</param-value>
    </context-param>

    ...
</web-app>

By adding a contextClass parameter with GroovyWebApplicationContext and then the Groovy application context, Spring will know how to bootstrap the application with a Groovy context file. A dependency on spring-web 4.1.x will be needed to add this class into the application.

Summary

Using Groovy for Spring configuration opens up a number of advantages, including concise syntax, nicer looking configuration files and being able to add methods if needed. If a project is using Spring 4 or 4.1 and above, it’s worth a look.

Share this Post

Related Blog Posts

JVM

Changing the embedded server in Grails 3

January 7th, 2016

How to change the server from Tomcat to something else in Grails 3s fat jar

Mike Hostetler
JVM

Flirting with disaster: A dangerous use of Groovys dynamic method invocation

January 5th, 2016

An example of when not to use Groovys dynamic method invocation feature. Injection attack vulnerability.

Object Partners
JVM

Distributed Grails with Docker and Hazelcast

December 28th, 2015

Example of clustering Grails using Docker Compose and distributing data and processing within the cluster using Hazelcast.

Mike Plummer

About the author