BAEL-359: Introduction to Spring Groovy Configuration (#12864)

* BAEL-359: Introduction to Spring Groovy Configuration

* BAEL-359: Removed unused import

* BAEL-359: Moved groovy files under src/main/groovy

* BAEL-359: Upgraded Groovy version to 3.0.13
This commit is contained in:
Palaniappan Arunachalam 2022-10-31 09:48:31 +05:30 committed by GitHub
parent 6ba4332f87
commit 1cd1a6cf24
11 changed files with 314 additions and 0 deletions

View File

@ -27,6 +27,7 @@
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -70,6 +71,7 @@
<properties>
<start-class>com.baeldung.springwithgroovy.SpringBootGroovyApplication</start-class>
<groovy.version>3.0.13</groovy.version>
</properties>
</project>

View File

@ -0,0 +1,23 @@
package com.baeldung.springgroovyconfig
beans {
// Declares a simple bean with a constructor argument
companyBean(Company, name: 'ABC Inc');
// The same bean can be declared using a simpler syntax: beanName(type, constructor-args)
company String, 'XYZ 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
company = company // or vendor = ref('company')
}
// Allows import of other configuration files, both XML and Groovy
importBeans('classpath:xml-bean-config.xml')
}

View File

@ -0,0 +1,7 @@
package com.baeldung.springgroovyconfig;
interface NotificationService {
String getMessage();
}

View File

@ -0,0 +1,6 @@
package com.baeldung.springgroovyconfig;
class NotificationServiceImpl implements NotificationService {
String message;
}

View File

@ -0,0 +1,25 @@
package com.baeldung.springgroovyconfig
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class SpringGroovyConfiguration {
public static void main(String[] args) { }
@Bean
List<String> fruits() {
[
'Apple',
'Orange',
'Banana',
'Grapes'
]
}
@Bean
Map<Integer, String> rankings() {
[1: 'Gold', 2: 'Silver', 3: 'Bronze']
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.springgroovyconfig;
public class Company {
private String name;
private String contact;
private String type;
public Company() {
}
public Company(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContact() {
return contact;
}
public void setContact(String contact) {
this.contact = contact;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

View File

@ -0,0 +1,32 @@
package com.baeldung.springgroovyconfig;
public class Employee {
private String firstName;
private String lastName;
private Company company;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}

View File

@ -0,0 +1,7 @@
class StringJoiner {
String join(String arg1, String arg2) {
arg1 + arg2;
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<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:src/main/groovy/com/baeldung/springgroovyconfig/NotificationServiceImpl.groovy" refresh-check-delay="10000">
<lang:property name="message" value="Hello" />
</lang:groovy>
<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>
</beans>

View File

@ -0,0 +1,144 @@
package com.baeldung.springgroovyconfig;
import static org.assertj.core.api.Assertions.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeansException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericGroovyApplicationContext;
import org.springframework.util.ResourceUtils;
import groovy.lang.Binding;
import groovy.lang.GroovyObject;
import groovy.util.GroovyScriptEngine;
class SpringGroovyConfigUnitTest {
private static final String FILE_NAME = "GroovyBeanBuilder.groovy";
private static final String FILE_PATH = "src/main/groovy/com/baeldung/springgroovyconfig/";
@Test
void givenGroovyConfigFile_whenCalledWithBeanName_thenReturnCompanyBean() {
try (GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext()) {
ctx.load("file:" + getPath(FILE_PATH) + FILE_NAME);
ctx.refresh();
Company company = (Company) ctx.getBean("companyBean");
assertEquals("ABC Inc", company.getName());
} catch (BeansException | IllegalStateException e) {
fail(e.getMessage());
}
}
@Test
void givenGroovyConfigFile_whenCalledWithRefBean_thenReturnEmployeeBean() {
try (GenericGroovyApplicationContext ctx = new GenericGroovyApplicationContext()) {
ctx.load("file:" + getPath(FILE_PATH) + FILE_NAME);
ctx.refresh();
Employee employee = ctx.getBean(Employee.class);
assertEquals("Lakshmi", employee.getFirstName());
assertEquals("Priya", employee.getLastName());
assertEquals("XYZ Inc", employee.getCompany()
.getName());
} catch (BeansException | IllegalStateException e) {
fail(e.getMessage());
}
}
@SuppressWarnings("unchecked")
@Test
void givenGroovyFileWithSpringAnnotations_whenCalledWithBeanName_thenReturnValidBean() {
try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();) {
ctx.register(SpringGroovyConfiguration.class);
ctx.refresh();
List<String> fruits = (List<String>) ctx.getBean("fruits");
assertNotNull(fruits);
assertTrue(fruits.size() == 4);
assertEquals("Apple", fruits.get(0));
} catch (BeansException | IllegalStateException e) {
fail(e.getMessage());
}
}
@Test
void givenGroovyBeanConfiguredInXml_whenCalledWithBeanName_thenReturnValidBean() {
try (ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-xml-config.xml")) {
ctx.refresh();
NotificationService notifier = (NotificationService) ctx.getBean("notification");
assertEquals("Hello", notifier.getMessage());
} catch (BeansException | IllegalStateException e) {
fail(e.getMessage());
}
}
@Test
void givenGroovyBeanConfiguredAsInlineScript_whenCalledWithBeanName_thenReturnValidBean() {
try (ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("groovy-xml-config.xml")) {
ctx.refresh();
NotificationService notifier = (NotificationService) ctx.getBean("notifier");
assertEquals("Have a nice day!", notifier.getMessage());
} catch (BeansException | IllegalStateException e) {
fail(e.getMessage());
}
}
@SuppressWarnings("unchecked")
@Test
void givenGroovyScript_whenCalledWithScriptEngine_thenReturnsResult() {
try {
GroovyScriptEngine engine = new GroovyScriptEngine(ResourceUtils.getFile("file:src/main/resources/")
.getAbsolutePath(), this.getClass().getClassLoader());
Class<GroovyObject> joinerClass = engine.loadScriptByName("StringJoiner.groovy");
GroovyObject joiner = joinerClass.getDeclaredConstructor()
.newInstance();
Object result = joiner.invokeMethod("join", new Object[] { "Mr.", "Bob" });
assertEquals("Mr.Bob", result.toString());
} catch (Exception e) {
fail(e.getMessage());
}
}
@Test
void givenGroovyScript_whenCalledWithBindingObject_thenReturnsResult() {
try {
GroovyScriptEngine engine = new GroovyScriptEngine(ResourceUtils.getFile("file:src/main/resources/")
.getAbsolutePath(), this.getClass().getClassLoader());
Binding binding = new Binding();
binding.setVariable("arg1", "Mr.");
binding.setVariable("arg2", "Bob");
Object result = engine.run("StringJoinerScript.groovy", binding);
assertEquals("Mr.Bob", result.toString());
} catch (Exception e) {
fail(e.getMessage());
}
}
private String getPath(String filePath) {
String pathPart = new File(".").getAbsolutePath();
pathPart = pathPart.replace(".", "");
pathPart = pathPart.replace("\\", "/");
pathPart = pathPart + filePath;
return pathPart;
}
}