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
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.
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.
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.
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.
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.
How to change the server from Tomcat to something else in Grails 3s fat jar
An example of when not to use Groovys dynamic method invocation feature. Injection attack vulnerability.
Example of clustering Grails using Docker Compose and distributing data and processing within the cluster using Hazelcast.
Insert bio here