Integrating Groovy Scripts with Spring Boot: A Step‑by‑Step Guide
This article introduces Groovy as a JVM scripting language, outlines its typical use cases, and provides a detailed, code‑rich tutorial on how to integrate Groovy scripts into a Spring Boot application, including dependency setup, script execution, bean access, and security considerations.
Groovy Introduction
Groovy is a scripting language that enhances the Java platform, offering Java‑like syntax, built‑in maps, lists, closures, and generators. It complements system programming languages rather than replacing them, and is widely used behind tools such as Gradle and increasingly within Spring projects.
Application Scenarios
Connecting existing components
Handling frequently changing heterogeneous entities
Providing graphical user interfaces
Supporting rapidly evolving features
For more basic concepts, see the linked Groovy tutorial.
Integration and Usage with Spring Boot
The following steps demonstrate how to embed Groovy scripts in a Spring Boot project.
Step 1 – Add Groovy Dependency
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>Step 2 – Write a Simple "Hello World" Script
Groovy script (HelloWorld.groovy):
package groovy
def HelloWorld() {
println "hello world"
}Java test class (GroovyTest.java):
package com.example.springbootgroovy.service;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
/**
* This is the first Groovy program.
*/
public class GroovyTest {
public static void main(String[] args) throws Exception {
// Create GroovyShell
GroovyShell groovyShell = new GroovyShell();
// Load and parse script code
Script script = groovyShell.parse("package groovy\n" +
"def HelloWorld(){\n" +
" println \"hello world\"\n" +
"}");
// Execute
script.invokeMethod("HelloWorld", null);
}
}Step 3 – Pass Variables and Retrieve Return Values
Groovy utility script (contains add and mapToString methods):
package groovy
/**
* Simple addition
* @param a first number
* @param b second number
* @return sum
*/
def add(int a, int b) {
return a + b
}
/**
* Convert a map to a string
* @param paramMap map of parameters
* @return concatenated string
*/
def mapToString(Map
paramMap) {
StringBuilder stringBuilder = new StringBuilder();
paramMap.forEach({ key, value ->
stringBuilder.append("key:" + key + ";value:" + value)
})
return stringBuilder.toString()
}Java test class (GroovyTest2.java) demonstrates invoking these methods and printing results.
Step 4 – Access Spring Beans from Groovy
Utility class to obtain the Spring context:
package com.example.springbootgroovy.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/** Spring context accessor */
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() { return applicationContext; }
public static Object getBean(String name) { return getApplicationContext().getBean(name); }
public static
T getBean(Class
clazz) { return getApplicationContext().getBean(clazz); }
public static
T getBean(String name, Class
clazz) { return getApplicationContext().getBean(name, clazz); }
}A service class annotated with @Service (GroovyTestService) is called from Groovy:
package com.example.springbootgroovy.service;
import org.springframework.stereotype.Service;
@Service
public class GroovyTestService {
public void test() {
System.out.println("I am a SpringBoot bean invoked by Groovy script");
}
}Groovy script that retrieves the bean:
package groovy
import com.example.springbootgroovy.service.GroovyTestService
import com.example.springbootgroovy.util.SpringContextUtil
class Globals {
static String PARAM1 = "static variable"
static int[] arrayList = [1, 2]
}
def getBean() {
GroovyTestService service = SpringContextUtil.getBean(GroovyTestService.class)
service.test()
}Spring Boot main application exposing an endpoint "/groovy/test" that runs the above script:
package com.example.springbootgroovy;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/groovy")
@SpringBootApplication
public class SpringBootGroovyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootGroovyApplication.class, args);
}
@RequestMapping("/test")
public String test() {
GroovyShell groovyShell = new GroovyShell();
Script script = groovyShell.parse("package groovy\n" +
"import com.example.springbootgroovy.service.GroovyTestService\n" +
"import com.example.springbootgroovy.util.SpringContextUtil\n" +
"class Globals { static String PARAM1 = \"static variable\"; static int[] arrayList = [1,2]; }\n" +
"def getBean() {\n" +
" GroovyTestService s = SpringContextUtil.getBean(GroovyTestService.class);\n" +
" s.test();\n" +
"}\n");
script.invokeMethod("getBean", null);
return "ok";
}
}After starting the application, accessing http://localhost:8080/groovy/test executes the Groovy script and prints the bean message.
Security Warning
While retrieving the Spring context from Groovy is convenient, it can be dangerous; without proper permission control, Groovy scripts could become a powerful attack vector against the system.
Readers are encouraged to discuss, ask questions, and share viewpoints responsibly.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.