If you’re a Java programmer looking for an expressive, flexible, and readable alternative to Spring xml configuration you should consider Groovy/Grails support for the above. It’s easy to use from Java as the following example illustrates.
Only a few lines of code are needed to produce the Spring ApplicationContext defined in the file “beans.groovy” on the classpath. A list of Flight objects (each containing a Pilot object) is retrieved and displayed with the toString() method.
package synaptic;
import java.beans.PropertyDescriptor;
import java.util.Date;
import java.util.List;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.context.ApplicationContext;
import grails.spring.BeanBuilder;
/**
* Demonstrate use of Groovy/Grails Spring configuration in Java.
*/
public class Main {
public static void main(String[] args) throws Exception {
BeanBuilder bb = new BeanBuilder();
bb.loadBeans("classpath:beans.groovy");
ApplicationContext context = bb.createApplicationContext();
System.out.println(context.getBean("title"));
System.out.println();
List<Flight> flights = (List<Flight>) context.getBean("sampleFlights");
for (Flight flight : flights) {
System.out.println(toString(flight, 0));
}
}
/**
* Generate human readable representation of a Java bean (hierarchy)
*/
public static String toString(Object bean, int depth) throws Exception {
StringBuilder sb = new StringBuilder();
BeanWrapper w = new BeanWrapperImpl(bean);
for (PropertyDescriptor pd : w.getPropertyDescriptors()) {
Class<?> type = pd.getPropertyType();
String name = pd.getDisplayName();
Object value = pd.getReadMethod().invoke(bean);
if (type.isPrimitive()
|| type.isAssignableFrom(String.class)
|| type.isAssignableFrom(Date.class)) {
value = value.toString() + "\n";
}
else if (type.isAssignableFrom(Class.class)) {
value = ((Class<?>) value).getCanonicalName() + "\n";
}
else {
value = "\n" + toString(value, depth + 1);
}
for (int i = 0; i < depth; i++) {
sb.append(" ");
}
sb.append(name + " = " + value);
}
return sb.toString();
}
}
The file “beans.groovy” uses some groovy and the Grails Spring DSL to create some beans from configuration data. More details on that DSL are available here.
import java.util.Random
import groovy.util.ConfigSlurper
import org.springframework.core.io.DefaultResourceLoader
import synaptic.Pilot
import synaptic.Flight
def rand = new Random(24L);
def random = { it.get(rand.nextInt(it.size())) }
def url = new DefaultResourceLoader().getResource("classpath:beans.config").getURL()
ConfigObject config = new ConfigSlurper().parse(url)
def pilots = [];
def flights = [];
config.pilot.names.each {
def pilot = new Pilot()
pilot.name = it
pilot.hours = rand.nextInt(6000)
pilots << pilot
}
(1..5).each {
def flight = new Flight()
flight.origin = random(config.airport.east.symbols)
flight.destination = random(config.airport.west.symbols)
flight.date = new Date()
flight.jet = random(config.jet.types)
flight.pilot = random(pilots)
flights << flight
}
beans {
title(String, config.title) {
}
sampleFlights(ArrayList, flights) {
}
}
The file “beans.config” uses the handy Groovy hierarchical configuration syntax. More on that here.
title = "Sample Flights"
airport {
east {
symbols = [ "BOS", "JFK", "PHL", "BWI", "CLT" ]
}
west {
symbols = [ "SAN", "LAX", "SFO", "PDX", "SEA" ]
}
}
pilot {
names = [ "Washington", "Adams", "Jefferson", "Madison", "Monroe" ]
}
jet {
types = [ "B737", "B747", "B777", "A320", "A340" ]
}
And just in case you were wondering here’s the output:
Sample Flights
class = synaptic.Flight
date = Fri Jun 10 23:09:35 EDT 2011
destination = SFO
jet = B737
origin = PHL
pilot =
class = synaptic.Pilot
hours = 1010
name = Monroe
class = synaptic.Flight
date = Fri Jun 10 23:09:35 EDT 2011
destination = PDX
jet = A340
origin = JFK
pilot =
class = synaptic.Pilot
hours = 1010
name = Monroe
class = synaptic.Flight
date = Fri Jun 10 23:09:35 EDT 2011
destination = SEA
jet = B777
origin = BWI
pilot =
class = synaptic.Pilot
hours = 4776
name = Jefferson
class = synaptic.Flight
date = Fri Jun 10 23:09:35 EDT 2011
destination = PDX
jet = A320
origin = CLT
pilot =
class = synaptic.Pilot
hours = 1010
name = Monroe
class = synaptic.Flight
date = Fri Jun 10 23:09:35 EDT 2011
destination = PDX
jet = A320
origin = CLT
pilot =
class = synaptic.Pilot
hours = 4224
name = Madison
The .classpath file in the complete source download indicates the required jar files.


