spring

Spring Framework Groovy Tutorial

In this article, we will explain Spring Framework using Groovy. Spring is a Java application framework that provides many useful services for building applications. It has supported Apache Groovy fully since version 4. In this tutorial, we will build a Spring boot application in Groovy.

1. Introduction

Apache Groovy (Groovy) is an object-oriented dynamic programming language for the Java platform. It is dynamically compiled to the Java Virtual Machine (JVM) bytecode, and inter-operates with other Java source codes and libraries. Groovy is written in Java. The first version 1.0 was released in 2007 to help developers to write a simple, elegant source code instead of the complicated Java code.

Spring Framework (Spring) is a Java application framework that provides many useful services for building applications. Spring 1.0 was released in 2004. Spring has supported Groovy fully since version 4 in 2013.

Spring boot defines a list of starter projects which each project includes a set of default component dependencies and automatic configuration of components.

In this example, I will create a Spring boot application which utilizes Spring’s features in Groovy.

2. Technologies Used

The example code in this article was built and run using:

  • Java 1.8.101 (1.8.x will do fine)
  • Maven 3.3.9 (3.3.x will do fine)
  • Eclipse Mars (Any Java IDE would work)
  • Spring boot 1.5.10.RELEASE
  • Groovy 2.4

3. Spring-boot Application

The easiest way to generate a Spring-boot application is via the Spring starter tool. Please check my other article here for more details. A maven project will be generated and downloaded to your workstation. Import it into your Eclipse work space. You should have no errors on building it and running it as a Spring Boot Application.

We will change it to a Groovy spring application with three steps:

  1. Add a Groovy dependency in the pom.xml
  2. Add a Groovy source folder
  3. Change Spring Application to a Groovy class

3.1 Groovy Dependency

The generated pom.xml does not include the Groovy library. We will add it as a dependency.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>jcg.zheng.demo</groupId>
	<artifactId>groovy-spring</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>groovy-spring</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.10.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.codehaus.groovy</groupId>
			<artifactId>groovy-all</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

3.2 Groovy Folders

The generated project has a Java source folder. We will add two folders: src/main/groovy and src/test/groovy. Then we will include them as the build resources.

spring framework groovy - Project Structure
Figure 1 Project Structure

3.3 Spring Framework Application in Groovy

The generated GroovySpringApplication is a Java class. We will change it to a Groovy class and move it under the src/main/groovy folder.

You can execute mvn install to build it and then run it as a Spring boot application.

4. Java and Groovy

We will define Payroll interface and implement it with both Java and Groovy and compare their performance.

4.1 Payroll Interface

Define Payroll interface to calculate the department’s budget based on the time period.

Payroll.java

package jcg.zheng.demo.groovyspring.service;

import java.math.BigDecimal;

import jcg.zheng.demo.groovyspring.model.BudgetType;
import jcg.zheng.demo.groovyspring.model.GDepartment;
import jcg.zheng.demo.groovyspring.model.JDepartment;

public interface Payroll {

	BigDecimal caculateBudget(JDepartment department, BudgetType type);
	BigDecimal caculateBudget(GDepartment department, BudgetType type);

}

Note:  It defines caculateBudget method for both Java Department and Groovy Department. We use it to demonstrate the method’s performance.

Define BudgetType enum for four time periods.

BudgetType.java

package jcg.zheng.demo.groovyspring.model;

import java.math.BigDecimal;

public enum BudgetType {

	YEARLY, QUARTERLY, MONTHLY, WEEKLY;

	public BigDecimal workingHours() {
		BigDecimal workingHours = new BigDecimal(0);
		switch (this) {
		case YEARLY:
			workingHours = new BigDecimal(2080);
		case QUARTERLY:
			workingHours = new BigDecimal(520);
		case MONTHLY:
			workingHours = new BigDecimal(173.34);
		case WEEKLY:
			workingHours = new BigDecimal(40);
		}
		return workingHours;
	}

}

4.2 Java Classes

In this step, we will create three Java classes to implement the Payroll interface.

Define a department class which contains a list of employees.

JDepartment.java

package jcg.zheng.demo.groovyspring.model;

import java.util.List;

public class JDepartment {
	private int id;

	private List employees;

	public List getEmployees() {
		return employees;
	}

	public void setEmployees(List employees) {
		this.employees = employees;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
}

Define an employee class which contains the employee’s first name, last name, and hourly pay rate.

JEmployee.java

package jcg.zheng.demo.groovyspring.model;

import java.math.BigDecimal;

public class JEmployee {
	public JEmployee() {
		super();
	}

	private String firstName;
	private String lastName;
	private int id;
	private BigDecimal hourlyRate;

	public BigDecimal caculatePay(BigDecimal hours) {
		return hourlyRate.multiply(hours);
	}

	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 int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public BigDecimal getHourlyRate() {
		return hourlyRate;
	}

	public void setHourlyRate(BigDecimal hourlyRate) {
		this.hourlyRate = hourlyRate;
	}

}

Implement the Payroll interface’s two methods to calculate a given department’s budget.

JPayrollImpl.java

package jcg.zheng.demo.groovyspring.service.impl;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Component;

import jcg.zheng.demo.groovyspring.model.BudgetType;
import jcg.zheng.demo.groovyspring.model.GDepartment;
import jcg.zheng.demo.groovyspring.model.JDepartment;
import jcg.zheng.demo.groovyspring.service.Payroll;

@Component("javaPayroll")
public class JPayrollImp implements Payroll {

	@Override
	public BigDecimal caculateBudget(JDepartment department, BudgetType type) {
		Instant start = Instant.now();

		List values = new ArrayList();
		department.getEmployees().forEach(emp -> values.add(emp.caculatePay(type.workingHours())));

		BigDecimal result = values.stream().reduce(BigDecimal::add).get();

		Instant end = Instant.now();

		System.out.println("Java caculateBudget for JDepartment took " + Duration.between(start, end));

		return result;
	}

	@Override
	public BigDecimal caculateBudget(GDepartment department, BudgetType type) {
		Instant start = Instant.now();

		List values = new ArrayList();
		department.getEmployees().forEach(emp -> values.add(emp.caculatePay(type.workingHours())));

		BigDecimal result = values.stream().reduce(BigDecimal::add).get();

		Instant end = Instant.now();

		System.out.println("Java caculateBudget for GDepartment took " + Duration.between(start, end));

		return result;
	}

}

Create a Junit test class for JPayrollImp.

JPayrollImpTest.java

package jcg.zheng.demo.groovyspring.service.impl;

import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import jcg.zheng.demo.groovyspring.model.BudgetType;
import jcg.zheng.demo.groovyspring.model.GDepartment;
import jcg.zheng.demo.groovyspring.model.GEmployee;
import jcg.zheng.demo.groovyspring.model.JDepartment;
import jcg.zheng.demo.groovyspring.model.JEmployee;
import jcg.zheng.demo.groovyspring.service.Payroll;

@RunWith(SpringRunner.class)
@SpringBootTest
public class JPayrollImpTest {

	@Autowired
	@Qualifier("javaPayroll")
	private Payroll javaPayroll;

	@Test
	public void test_JavaPayroll_caculateBudget_for_JDepartment_yearly() {
		JDepartment dept = new JDepartment();

		List reports = new ArrayList();
		reports.add(buildJEmployee("Mary", "Zheng", new BigDecimal(20)));
		reports.add(buildJEmployee("Alex", "Zheng", new BigDecimal(10)));
		reports.add(buildJEmployee("Allen", "Zheng", new BigDecimal(8)));

		dept.setEmployees(reports);

		BigDecimal budget = javaPayroll.caculateBudget(dept, BudgetType.YEARLY);
		assertTrue(budget.compareTo(new BigDecimal(1520)) == 0);
	}

	@Test
	public void test_JavaPayroll_caculateBudget_for_GDepartment_yearly() {
		GDepartment dept = new GDepartment();

		List reports = new ArrayList();
		reports.add(buildGEmployee("Mary", "Zheng", new BigDecimal(20)));
		reports.add(buildGEmployee("Alex", "Zheng", new BigDecimal(10)));
		reports.add(buildGEmployee("Allen", "Zheng", new BigDecimal(8)));

		dept.setEmployees(reports);

		BigDecimal budget = javaPayroll.caculateBudget(dept, BudgetType.YEARLY);
		assertTrue(budget.compareTo(new BigDecimal(1520)) == 0);
	}

	private JEmployee buildJEmployee(String fname, String lname, BigDecimal money) {
		JEmployee mary = new JEmployee();
		mary.setFirstName(fname);
		mary.setLastName(lname);
		mary.setHourlyRate(money);
		return mary;
	}

	private GEmployee buildGEmployee(String fname, String lname, BigDecimal money) {
		GEmployee mary = new GEmployee();
		mary.setFirstName(fname);
		mary.setLastName(lname);
		mary.setHourlyRate(money);
		return mary;
	}

}

4.3 Groovy Classes

Groovy was introduced to ease the Java syntax’s complexity. The @Canonical annotation assists Groovy developers to write shorter code. In this step, we will create three Groovy classes to implement the Payroll interface.

Define a department class which contains a list of employees. It’s much shorter and cleaner comparing to the Java class created in step 4.2.

GDepartment.groovy

package jcg.zheng.demo.groovyspring.model

import groovy.transform.*

@Canonical
class GDepartment {
	int id	
	List employees

}

Define an employee class which contains the employee’s first name, last name, and hourly pay rate.

GEmployee.groovy

package jcg.zheng.demo.groovyspring.model

import groovy.transform.*

@Canonical
class GEmployee {
	String firstName
	String lastName
	int id
	BigDecimal hourlyRate
	
	public BigDecimal caculatePay(BigDecimal hours) {
		hourlyRate.multiply(hours)
	}
}

Implement the Payroll interface’s two methods to calculate a given department’s budget.

We can use Spring @Component annotation to name it groovyPayroll as a Spring bean. We also add time tracking to calculate the performance time.

GPayrollImpl.groovy

package jcg.zheng.demo.groovyspring.component

import java.time.Duration
import java.util.ArrayList
import java.util.List

import org.springframework.stereotype.Component

import groovy.time.TimeCategory
import groovy.time.TimeDuration
import jcg.zheng.demo.groovyspring.model.BudgetType
import jcg.zheng.demo.groovyspring.model.GDepartment
import jcg.zheng.demo.groovyspring.model.JDepartment
import jcg.zheng.demo.groovyspring.service.Payroll

@Component("groovyPayroll")
class GPayrollImpl implements Payroll{

	@Override
	public BigDecimal caculateBudget(JDepartment department, BudgetType type) {
		def timeStart = new Date()
		List values = new ArrayList()

		department.getEmployees().each { 
			values.add(it.caculatePay(type.workingHours()))}

		def timeStop = new Date()
		TimeDuration duration = TimeCategory.minus(timeStop, timeStart)
		println "Groovy caculateBudget for JDepartment took " + duration

		values.sum();
	}

	@Override
	public BigDecimal caculateBudget(GDepartment department, BudgetType type) {
		def timeStart = new Date()
		List values = new ArrayList()

		department.getEmployees().each {
			values.add(it.caculatePay(type.workingHours()))}

		def timeStop = new Date()
		TimeDuration duration = TimeCategory.minus(timeStop, timeStart)
		println "Groovy caculateBudget for GDepartment took " + duration
		values.sum();
	}
}

Create a Junit test class for GPayrollImp. We use Spring @Autowired annotation along with @Qualifier to find the Groovy Payroll bean.

GPayrollImpTest.groovy

package jcg.zheng.demo.groovyspring.component

import static org.junit.Assert.assertTrue

import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner

import jcg.zheng.demo.groovyspring.model.BudgetType
import jcg.zheng.demo.groovyspring.model.GDepartment
import jcg.zheng.demo.groovyspring.model.GEmployee
import jcg.zheng.demo.groovyspring.model.JDepartment
import jcg.zheng.demo.groovyspring.model.JEmployee
import jcg.zheng.demo.groovyspring.service.Payroll

@RunWith(SpringRunner.class)
@SpringBootTest
class GroovyPayrollTest {

	@Autowired
	@Qualifier("groovyPayroll")
	private Payroll groovyPayroll

	@Test
	public void test_GroovyPayroll_caculateBudget_for_GDepartment_yearly() {
		GDepartment department = new GDepartment()

		List reports = [
			new GEmployee(firstName:"Mary", lastName:"Zheng", hourlyRate:new BigDecimal(20)),
			new GEmployee(firstName:"Alex", lastName:"Zheng", hourlyRate:new BigDecimal(10)),
			new GEmployee(firstName:"Allen", lastName:"Zheng", hourlyRate:new BigDecimal(8))
		]

		department.setEmployees(reports);

		def ret = groovyPayroll.caculateBudget(department, BudgetType.YEARLY)
		assertTrue(ret.compareTo(new BigDecimal(1520)) == 0);
	}

	@Test
	public void test_GroovyPayroll_caculateBudget_for_JDepartment_yearly() {
		JDepartment department = new JDepartment()

		List reports = [
			new JEmployee(firstName:"Mary", lastName:"Zheng", hourlyRate:new BigDecimal(20)),
			new JEmployee(firstName:"Alex", lastName:"Zheng", hourlyRate:new BigDecimal(10)),
			new JEmployee(firstName:"Allen", lastName:"Zheng", hourlyRate:new BigDecimal(8))
		]

		department.setEmployees(reports);

		def ret = groovyPayroll.caculateBudget(department, BudgetType.YEARLY)
		assertTrue(ret.compareTo(new BigDecimal(1520)) == 0);
	}
}

5. Demo Java vs Groovy

Execute mvn install to build and run JPayrollImpTest and GPayrollImpTest and see the output below.

JPayrollImpTest output

2018-03-28 21:16:58.299  INFO 10460 --- [           main] j.z.d.g.service.impl.JPayrollImpTest     : Started JPayrollImpTest in 8.053 seconds (JVM running for 9.671)
Java caculateBudget for GDepartment took PT0.039S
Java caculateBudget for JDepartment took PT0.003S

GPayrollImpTest output

2018-03-28 21:18:37.369  INFO 7588 --- [           main] j.z.d.g.component.GroovyPayrollTest      : Started GroovyPayrollTest in 5.96 seconds (JVM running for 7.935)
Groovy caculateBudget for GDepartment took 0.036 seconds
Groovy caculateBudget for JDepartment took 0.007 seconds

Testing output shows that the Java implementation of the payroll service with the Java POJO class is the fastest of all four tests.

6. Spring Framework and Groovy

In this step, I will demonstrate how to invoke a Rest service and parse the results in Groovy.

6.1 Spring Properties

The Rest service is a public service which gets all the country’s information and gets state’s information for given country.

Add the service host name and logging level in the Spring properties file.

application.properties

AddressService.HostUrl=http://services.groupkt.com

logging.level.org.springframework=INFO
logging.level.jcg.zheng.demo=DEBUG

6.2 POGOs

Open browser and go to http://services.groupkt.com/country/get/all get all the country’s information.  Go to http://services.groupkt.com/state/get/USA/all to get all the state’s information for USA. Both services return a Json object which contains a List of String messages and List of countries or states.

We will create four POGOs to match the Rest service results. Then use JsonSlurper to parse the results to the expected data type.

GCountry class contains namealpha2_code, and alpha3_code.

GCountry.groovy

package jcg.zheng.demo.groovyspring.model;

import groovy.transform.*

@Canonical
class GCountry {

	String name
	String alpha2_code
	String alpha3_code
}

GState class contains nameabbr, and capital, etc.

GState.groovy

package jcg.zheng.demo.groovyspring.model;

import groovy.transform.*

@Canonical
class GState {
	Long id
	String country
	String name
	String abbr
	String area
	String capital
	String largest_city
}

GResponse class contains messages and result.

GResponse.groovy

package jcg.zheng.demo.groovyspring.model;
import groovy.transform.*

@Canonical
class GResponse {
	List<String> messages

	List<Object> result
}

GResponseWrapper class contains RestResponse.

GResponseWrapper.groovy

package jcg.zheng.demo.groovyspring.model;

import groovy.json.internal.LazyMap
import groovy.transform.*
@Canonical
class GResponseWrapper {
	GResponse RestResponse
}

6.3 Address Service

Create an address service and annotate it with @Component. It invokes a REST API service to get all the country’s information. The results is cached into the memory with the @Memoized annotation.

AddressService class contains two methods: getCountries and getStates.

AddressService.groovy

package jcg.zheng.demo.groovyspring.component

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component

import groovy.json.JsonSlurper
import groovy.transform.Memoized
import jcg.zheng.demo.groovyspring.model.GCountry
import jcg.zheng.demo.groovyspring.model.GResponseWrapper
import jcg.zheng.demo.groovyspring.model.GState

@Component
class AddressService {
	@Value('${AddressService.HostUrl}')
	private String serviceHostUrl

	private String countryPath = "/country/get/all"

	private String statePath = "/state/get/"


	private static final Logger logger = LoggerFactory.getLogger(AddressService.class)

	@Memoized
	List<GState> getStates(String countryCode){
		List<GState> states = new ArrayList<>()
		String getResult = new URL(serviceHostUrl + statePath + countryCode + "/all").text
		logger.debug( "getStates called rest service.")
		def jsonMap = new JsonSlurper().parseText(getResult)

		GResponseWrapper rep = new GResponseWrapper(jsonMap)
		return rep.getRestResponse().getResult()
	}

	@Memoized
	List<GCountry> getCountries(){
		List<GCountry> countryList = new ArrayList<>()
		String getResult = new URL(serviceHostUrl + countryPath).text
		logger.debug( "getCountries called rest service.")
		def jsonMap = new JsonSlurper().parseText(getResult)

		GResponseWrapper rep = new GResponseWrapper(jsonMap)
		
		return rep.getRestResponse().getResult()
	}
}

Create AddressServiceTest to test both getCountries and getStates.

AddressServiceTest.groovy

package jcg.zheng.demo.groovyspring.component

import static org.junit.Assert.*

import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner

import groovy.time.TimeCategory
import groovy.time.TimeDuration

import jcg.zheng.demo.groovyspring.component.AddressService
import jcg.zheng.demo.groovyspring.model.*

@RunWith(SpringRunner.class)
@SpringBootTest
class AddressServiceTest {

	@Autowired
	private AddressService addressService

	@Test
	public void test_get_allcountries() {
		def timeStart = new Date()

		List countries = addressService.getCountries();

		def timeStop = new Date()

		countries = addressService.getCountries();

		def timeStop2 = new Date()

		TimeDuration duration = TimeCategory.minus(timeStop, timeStart)
		TimeDuration duration2 = TimeCategory.minus(timeStop2, timeStop)

		println "Groovy first getCountries took " + duration
		println "Groovy second getCountries took " + duration2

		assertTrue(countries.size() == 249)
	}

	@Test
	public void test_get_USA_states() {
		def timeStart = new Date()

		List usStates = addressService.getStates("USA");

		def timeStop = new Date()

		usStates = addressService.getStates("USA");

		def timeStop2 = new Date()

		TimeDuration duration = TimeCategory.minus(timeStop, timeStart)

		TimeDuration duration2 = TimeCategory.minus(timeStop2, timeStop)

		println "Groovy second getStates took " + duration
		println "Groovy second getStates took " + duration2

		assertTrue(usStates.size() == 55)
	}
}

Run the AddressServiceTest and confirm data for the countries and states is cached.

AddressServiceTest output

2018-03-28 22:01:06.764  INFO 5060 --- [           main] j.z.d.g.component.AddressServiceTest     : Started AddressServiceTest in 4.743 seconds (JVM running for 6.208)
2018-03-28 22:01:07.070 DEBUG 5060 --- [           main] j.z.d.g.component.AddressService         : getCountries called rest service.
Groovy first getCountries took 0.256 seconds
Groovy second getCountries took 0
2018-03-28 22:01:07.210 DEBUG 5060 --- [           main] j.z.d.g.component.AddressService         : getStates called rest service.
Groovy second getStates took 0.079 seconds
Groovy second getStates took 0

6.4 Groovy Spring Application

GroovySpringApplication is a Groovy class which annotates with Spring annotation driven configuration annotation @SpringBootApplication. It finds javaPayroll and invokes its caculateBudget for a given department. It also finds the AddressService beans and finds the USA from the getCountries returned countries and then gets all the USA states from getStates service.

GroovySpringApplication.groovy

package jcg.zheng.demo.groovyspring

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.ConfigurableApplicationContext

import jcg.zheng.demo.groovyspring.component.AddressService
import jcg.zheng.demo.groovyspring.model.BudgetType
import jcg.zheng.demo.groovyspring.model.GCountry
import jcg.zheng.demo.groovyspring.model.GDepartment
import jcg.zheng.demo.groovyspring.model.GEmployee
import jcg.zheng.demo.groovyspring.model.GState
import jcg.zheng.demo.groovyspring.service.Payroll

@SpringBootApplication
public class GroovySpringApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(GroovySpringApplication.class, args)
		
		printYearlyBudget(context)
	
		printAddress(context)
	}

	private static printYearlyBudget(ConfigurableApplicationContext context) {
		GDepartment department = new GDepartment(id:1)

		List reports = [
			new GEmployee(firstName:"Mary", lastName:"Zheng", hourlyRate:new BigDecimal(20)),
			new GEmployee(firstName:"Alex", lastName:"Zheng", hourlyRate:new BigDecimal(10)),
			new GEmployee(firstName:"Allen", lastName:"Zheng", hourlyRate:new BigDecimal(8))
		]

		department.setEmployees(reports)
		Payroll payroll = context.getBean("javaPayroll")
		println "Departement 1 yearly budget: " + payroll.caculateBudget(department, BudgetType.YEARLY)
	}

	private static printAddress(ConfigurableApplicationContext context) {
		AddressService addressService = context.getBean(AddressService.class)
		List countries = addressService.getCountries()
		def usa = countries.find{it.get("alpha3_code").equalsIgnoreCase("USA")}
		println "Found USA " + usa

		List usStates = addressService.getStates("USA")
		println "US States :" + usStates
	}
}

7. Demo Spring Groovy Application

Execute the Spring boot application.

Application Output

2018-03-28 21:36:19.045  INFO 9708 --- [           main] j.z.d.g.GroovySpringApplication          : Started GroovySpringApplication in 5.715 seconds (JVM running for 7.525)
Java caculateBudget for GDepartment took PT0.011S
Departement 1 yearly budget: 1520
2018-03-28 21:36:19.358 DEBUG 9708 --- [           main] j.z.d.g.component.AddressService         : getCountries called rest service.
Found USA [name:United States of America, alpha2_code:US, alpha3_code:USA]
2018-03-28 21:36:19.468 DEBUG 9708 --- [           main] j.z.d.g.component.AddressService         : getStates called rest service.
US States :[[id:1, country:USA, name:Alabama, abbr:AL, area:135767SKM, largest_city:Birmingham, capital:Montgomery], [id:2, country:USA, name:Alaska, abbr:AK, area:1723337SKM, largest_city:Anchorage, capital:Juneau], [id:3, country:USA, name:Arizona, abbr:AZ, area:113594SKM, largest_city:Phoenix, capital:Phoenix], [id:4, country:USA, name:Arkansas, abbr:AR, area:52035SKM, largest_city:Little Rock, capital:Little Rock], [id:5, country:USA, name:California, abbr:CA, area:423967SKM, largest_city:Los Angeles, capital:Sacramento], [id:6, country:USA, name:Colorado, abbr:CO, area:103642SKM, largest_city:Denver, capital:Denver], [id:7, country:USA, name:Connecticut, abbr:CT, area:14357SKM, largest_city:Bridgeport, capital:Hartford], [id:8, country:USA, name:Delaware, abbr:DE, area:6446SKM, largest_city:Wilmington, capital:Dover], [id:9, country:USA, name:Florida, abbr:FL, area:170312SKM, largest_city:Jacksonville, capital:Tallahassee], [id:10, country:USA, name:Georgia, abbr:GA, area:57513SKM, largest_city:Atlanta, capital:Atlanta], [id:11, country:USA, name:Hawaii, abbr:HI, area:6423SKM, largest_city:Honolulu, capital:Honolulu], [id:12, country:USA, name:Idaho, abbr:ID, area:82643SKM, largest_city:Boise, capital:Boise], [id:13, country:USA, name:Illinois, abbr:IL, area:149995SKM, largest_city:Chicago, capital:Springfield], [id:14, country:USA, name:Indiana, abbr:IN, area:35826SKM, largest_city:Indianapolis, capital:Indianapolis], [id:15, country:USA, name:Iowa, abbr:IA, area:55857SKM, largest_city:Des Moines, capital:Des Moines], [id:16, country:USA, name:Kansas, abbr:KS, area:213100SKM, largest_city:Wichita, capital:Topeka], [id:17, country:USA, name:Kentucky, abbr:KY, area:104656SKM, largest_city:Louisville, capital:Frankfort], [id:18, country:USA, name:Louisiana, abbr:LA, area:135659SKM, largest_city:New Orleans, capital:Baton Rouge], [id:19, country:USA, name:Maine, abbr:ME, area:91633SKM, largest_city:Portland, capital:Augusta], [id:20, country:USA, name:Maryland, abbr:MD, area:32131SKM, largest_city:Baltimore, capital:Annapolis], [id:21, country:USA, name:Massachusetts, abbr:MA, area:7800SKM, largest_city:Boston, capital:Boston], [id:22, country:USA, name:Michigan, abbr:MI, area:250487SKM, largest_city:Detroit, capital:Lansing], [id:23, country:USA, name:Minnesota, abbr:MN, area:225163SKM, largest_city:Minneapolis, capital:St. Paul], [id:24, country:USA, name:Mississippi, abbr:MS, area:46923SKM, largest_city:Jackson, capital:Jackson], [id:25, country:USA, name:Missouri, abbr:MO, area:180540SKM, largest_city:Kansas City, capital:Jefferson City], [id:26, country:USA, name:Montana, abbr:MT, area:380831SKM, largest_city:Billings, capital:Helena], [id:27, country:USA, name:Nebraska, abbr:NE, area:200330SKM, largest_city:Omaha, capital:Lincoln], [id:28, country:USA, name:Nevada, abbr:NV, area:286380SKM, largest_city:Las Vegas, capital:Carson City], [id:29, country:USA, name:New Hampshire, abbr:NH, area:24214SKM, largest_city:Manchester, capital:Concord], [id:30, country:USA, name:New Jersey, abbr:NJ, area:22591SKM, largest_city:Newark, capital:Trenton], [id:31, country:USA, name:New Mexico, abbr:NM, area:314917SKM, largest_city:Albuquerque, capital:Santa Fe], [id:32, country:USA, name:New York, abbr:NY, area:141297SKM, largest_city:New York City, capital:Albany], [id:33, country:USA, name:North Carolina, abbr:NC, area:139391SKM, largest_city:Charlotte, capital:Raleigh], [id:34, country:USA, name:North Dakota, abbr:ND, area:183108SKM, largest_city:Fargo, capital:Bismarck], [id:35, country:USA, name:Ohio, abbr:OH, area:40861SKM, largest_city:Columbus, capital:Columbus], [id:36, country:USA, name:Oklahoma, abbr:OK, area:68595SKM, largest_city:Oklahoma City, capital:Oklahoma City], [id:37, country:USA, name:Oregon, abbr:OR, area:254799SKM, largest_city:Portland, capital:Salem], [id:38, country:USA, name:Pennsylvania, abbr:PA, area:119280SKM, largest_city:Philadelphia, capital:Harrisburg], [id:39, country:USA, name:Rhode Island, abbr:RI, area:1034SKM, largest_city:Providence, capital:Providence], [id:40, country:USA, name:South Carolina, abbr:SC, area:82933SKM, largest_city:Charleston, capital:Columbia], [id:41, country:USA, name:South Dakota, abbr:SD, area:199729SKM, largest_city:Sioux Falls, capital:Pierre], [id:42, country:USA, name:Tennessee, abbr:TN, area:41235SKM, largest_city:Nashville, capital:Nashville], [id:43, country:USA, name:Texas, abbr:TX, area:695662SKM, largest_city:Houston, capital:Austin], [id:44, country:USA, name:Utah, abbr:UT, area:82170SKM, largest_city:Salt Lake City, capital:Salt Lake City], [id:45, country:USA, name:Vermont, abbr:VT, area:24906SKM, largest_city:Burlington, capital:Montpelier], [id:46, country:USA, name:Virginia, abbr:VA, area:110787SKM, largest_city:Virginia Beach, capital:Richmond], [id:47, country:USA, name:Washington, abbr:WA, area:184661SKM, largest_city:Seattle, capital:Olympia], [id:48, country:USA, name:West Virginia, abbr:WV, area:24038SKM, largest_city:Charleston, capital:Charleston], [id:49, country:USA, name:Wisconsin, abbr:WI, area:169635SKM, largest_city:Milwaukee, capital:Madison], [id:50, country:USA, name:Wyoming, abbr:WY, area:97093SKM, largest_city:Cheyenne, capital:Cheyenne], [id:51, country:USA, name:American Samoa, abbr:AS, area:1505SKM, capital:Pago Pago], [id:52, country:USA, name:Guam, abbr:GU, area:1478SKM, capital:Hagåtña], [id:53, country:USA, name:Northern Mariana Islands, abbr:MP, area:5117SKM, capital:Saipan], [id:54, country:USA, name:Puerto Rico, abbr:PR, area:13791SKM, capital:San Juan], [id:55, country:USA, name:U.S. Virgin Islands, abbr:VI, area:1898SKM, capital:Charlotte Amalie]]

8. Summary

In this example, we built a Spring Boot application with Groovy to demonstrate the integration between Spring and Groovy. We also demonstrated that Groovy source code is shorter and cleaner than Java. But Java is faster than Groovy.

9. References

10. Download the Source Code

This example consists of a Spring boot application which developed in Groovy.

Download
You can download the full source code of this example here: Spring Framework Groovy Tutorial

Last updated on Apr. 29th, 2021

Mary Zheng

Mary has graduated from Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She works as a senior Software Engineer in the telecommunications sector where she acts as a leader and works with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button