1. Overview

Groovy is a powerful and dynamic JVM language that has numerous features. Using Groovy in Spring can greatly enhance the application’s capability in terms of flexibility and improved readability. Spring supports Groovy-based configurations since version 4.

In this tutorial, we’ll look at the different ways that we can use Groovy with Spring. First, we’ll see how to create Groovy bean definitions with multiple options provided by Spring. Next, we’ll discuss how to bootstrap the Application Context using Groovy scripts. Finally, we’ll see how to execute Groovy as a script (without compilation) using XML and the GroovyScriptEngine class.

2. Maven Dependencies

Let’s start by defining the Groovy dependency in the pom.xml:

<dependency>
    <groupId>org.apache.groovy</groupId>
    <artifactId>groovy</artifactId>
    <version>4.0.11</version>
</dependency>

In addition, we need to add the GMavenPlus plugin to compile the Groovy files:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.gmavenplus</groupId>
            <artifactId>gmavenplus-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>addSources</goal>
                        <goal>addTestSources</goal>
                        <goal>generateStubs</goal>
                        <goal>compile</goal>
                        <goal>generateTestStubs</goal>
                        <goal>compileTests</goal>
                        <goal>removeStubs</goal>
                        <goal>removeTestStubs</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

3. Bean Definitions

Traditionally, developers used to declare beans via XML configuration. This style was later replaced by defining the beans programmatically via Java annotations. Another way to declare beans is through Groovy scripts.

Since we’re using the GMavenPlus plugin, the Groovy source files can be mixed alongside other Java code within the src/main/java source folder. However, it’s better to place the Groovy files in the dedicated src/main/groovy source folder to avoid confusion at a later stage.

3.1. Using Groovy Bean Builder

Groovy Bean Builder is a powerful alternative to Java’s @Configuration annotation-based configurations and XML-based configurations. Let’s look at some basic bean definitions using Groovy code:

beans {
    
    // Declares a simple bean with a constructor argument
    company(Company, name: 'ABC Inc');

    // The same bean can be declared using a simpler syntax: beanName(type, constructor-args) 
    company String, 'ABC Inc'

    // Declares an employee object with setters referencing the previous bean
    employee(Employee) {
        firstName = 'Lakshmi'
        lastName = 'Priya'
        // References to other beans can be done in both the ways
        vendor = company // or vendor = ref('company')
    }
    // Allows import of other configuration files, both XML and Groovy
    importBeans('classpath:ApplicationContext.xml')
    importBeans('classpath:GroovyContext.groovy')
}

Here, the top-level beans construct that wraps all the declared beans is a closure that the GroovyBeanDefinitionReader processes as a DSL.

3.2. Using Annotations

Alternatively, Groovy classes can be valid Spring beans and Groovy can be used in place of Java for annotation-based configuration:

@Configuration
class SpringGroovyConfiguration{
    
    @Bean
    List<String> fruits() {
        ['Apple', 'Orange', 'Banana', 'Grapes']
    }

    @Bean
    Map<Integer, String> rankings() {
        [1: 'Gold', 2: 'Silver', 3: 'Bronze']
    }
}

3.3. Using XML

Surely, both the Groovy Bean Builder and annotation-based configurations are more flexible. However, we can still use XML to declare beans defined in Groovy scripts. Groovy is a dynamic language for which Spring provides comprehensive support. Accordingly, we need to use a special element in XML configuration (<lang:groovy>) to indicate that we’re defining dynamic-language-backed beans.

For example, let’s see an example XML configuration that references the correct schema so that the tags in the lang namespace are available:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd">
    <lang:groovy id="notification" script-source="file:NotificationServiceImpl.groovy" refresh-check-delay="10000" >
        <lang:property name="message" value="Hello" />
    </lang:groovy>
</beans>

Here, we declared the notification bean that refers to a Groovy script via the script-source attribute. We can specify the exact location of the script with the file prefix. Alternatively, we can use the classpath prefix to access the resources directly from the classpath. The refresh-check-delay attribute defines the refresh interval of the script, which can be refreshed automatically when the content of the script changes.

4. Bootstrap Application Context

Spring needs to know how to bootstrap the Groovy context file to make the beans available to the application. We can do this either by configuring it in the web.xml or by loading the context programmatically.

4.1. Add Groovy Configuration to the web.xml

To make things simpler, Spring version 4.1 added support for loading the Groovy configuration file through web.xml with the help of GroovyWebApplicationContext.

By default, the configuration will be loaded from /WEB-INF/applicationContext.groovy. However, this location can be overridden through the contextConfigLocation servlet context parameter:

<web-app>
    
    ...
    
    <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>

4.2. Using GenericGroovyApplicationContext 

Spring provides GenericGroovyApplicationContext to bootstrap Groovy bean definitions. In addition, the context can be loaded with an inline bean definition closure:

def context = new GenericGroovyApplicationContext()
context.reader.beans {
    department(Department) {
        name = 'Finance'
        floor = 3
    }
}
context.refresh()

Alternatively, we can externalize this bean definition and load the application context from a Groovy config file:

GenericGroovyApplicationContext context = new GenericGroovyApplicationContext();
context.load("config/applicationContext.groovy");
context.refresh();

As we can see, loading the Groovy context is similar to the Java-style instantiation of XmlWebApplicationContext or ClassPathXmlApplicationContext.

In case of no extra configuration, the code can be even more concise:

ApplicationContext context = new GenericGroovyApplicationContext("config/applicationContext.groovy");
String foo = context.getBean("foo", String.class);

Additionally, GenericGroovyApplicationContext also understands XML bean definition files. This adds more flexibility by allowing seamless mixing and matching with Groovy bean definition files. 

5. Executing Groovy Scripts

In addition to the Groovy bean definitions, Spring also supports executing Groovy scripts, without compilation. This execution can be as a standalone bean or by calling the Groovy script in a bean so that the script becomes an executable part of it.

5.1. As Inline Script

As we saw earlier, we can use the dynamic language support provided by Spring to embed the Groovy source file directly inside Spring bean definitions. Accordingly, we can make use of the <lang:inline-script/> element to define the Groovy source immediately inside the Spring configuration XML file.

For example, we can create a Notifier bean with the use of the inline script feature:

<lang:groovy id="notifier">
    <lang:inline-script>

    package com.baeldung.springgroovyconfig;
    import com.baeldung.springgroovyconfig.NotificationService;

    class Notifier implements NotificationService {
        String message
    }

    </lang:inline-script>
    <lang:property name="message" value="Have a nice day!" />
</lang:groovy>

5.2. Using GroovyScriptEngine

Alternatively, we can use the GroovyScriptEngine class to execute Groovy scripts. GroovyScriptEngine is provided by Groovy itself, and there’s no dependency on Spring to use it.

This class supports reloading the scripts automatically whenever there’s a change. In addition, it also loads all the classes that depend on it.

There are two ways to execute the script. In the first approach, we get a GroovyObject and execute the script by calling invokeMethod():

GroovyScriptEngine engine = new GroovyScriptEngine(ResourceUtils.getFile("file:src/main/resources/")
.getAbsolutePath(), this.getClass().getClassLoader());
Class<GroovyObject> joinerClass = engine.loadScriptByName("StringJoiner.groovy");
GroovyObject joiner = joinerClass.newInstance();

Object result = joiner.invokeMethod("join", new Object[]{"Mr.", "Bob"});
assertEquals("Mr.Bob", result.toString());

In the second approach, we can call the Groovy script directly. We use the Binding class to pass variables to the Groovy script:

Binding binding = new Binding();
binding.setVariable("arg1", "Mr.");
binding.setVariable("arg2", "Bob");
Object result = engine.run("StringJoinerScript.groovy", binding); 
assertEquals("Mr.Bob", result.toString());

6. Conclusion

Spring provides numerous options to integrate Groovy. Along with the scripting capabilities, using a dynamic language such as Groovy in Spring applications can be powerful. The adaptability of Spring together with the flexibility of Groovy gives us a wonderful combination.

In this article, we learned how the Spring framework provides extensive support for Groovy so that we can have valid bean definitions using different approaches. Also, we saw how to bootstrap Groovy scripts into valid Spring beans. Finally, we discussed how to invoke Groovy scripts on the fly.

As always, the code for these examples is available over on GitHub.

Course – LS (cat=Spring)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!