
- •brief contents
- •contents
- •foreword
- •preface
- •acknowledgments
- •about this book
- •Roadmap
- •Code conventions and downloads
- •Author Online
- •About the author
- •about the cover illustration
- •1 Why add Groovy to Java?
- •1.1 Issues with Java
- •1.1.1 Is static typing a bug or a feature?
- •1.1.2 Methods must be in a class, even if you don’t need or want one
- •1.1.3 Java is overly verbose
- •1.1.4 Groovy makes testing Java much easier
- •1.1.5 Groovy tools simplify your build
- •1.2 Groovy features that help Java
- •1.3 Java use cases and how Groovy helps
- •1.3.1 Spring framework support for Groovy
- •1.3.2 Simplified database access
- •1.3.3 Building and accessing web services
- •1.3.4 Web application enhancements
- •1.4 Summary
- •2 Groovy by example
- •2.1 Hello, Groovy
- •2.2 Accessing Google Chart Tools
- •2.2.1 Assembling the URL with query string
- •2.2.2 Transmitting the URL
- •2.2.3 Creating a UI with SwingBuilder
- •2.3 Groovy Baseball
- •2.3.1 Database data and Plain Old Groovy Objects
- •2.3.2 Parsing XML
- •2.3.3 HTML builders and groovlets
- •2.4 Summary
- •3 Code-level integration
- •3.1 Integrating Java with other languages
- •3.2 Executing Groovy scripts from Java
- •3.2.1 Using JSR223 scripting for the Java Platform API
- •3.2.2 Working with the Groovy Eval class
- •3.2.3 Working with the GroovyShell class
- •3.2.4 Calling Groovy from Java the easy way
- •3.2.5 Calling Java from Groovy
- •3.3 Summary
- •4 Using Groovy features in Java
- •4.1 Treating POJOs like POGOs
- •4.2 Implementing operator overloading in Java
- •4.3 Making Java library classes better: the Groovy JDK
- •4.4 Cool AST transformations
- •4.4.1 Delegating to contained objects
- •4.4.2 Creating immutable objects
- •4.4.3 Creating singletons
- •4.5 Working with XML
- •4.6 Working with JSON data
- •4.7 Summary
- •5 Build processes
- •5.1 The build challenge
- •5.2 The Java approach, part 1: Ant
- •5.3 Making Ant Groovy
- •5.3.1 The <groovy> Ant task
- •5.3.2 The <groovyc> Ant task
- •5.3.3 Writing your build in Groovy with AntBuilder
- •5.3.4 Custom build scripts with Gant
- •5.3.5 Ant summary
- •5.4 The Java approach, part 2: Maven
- •5.4.2 The GMaven project
- •5.4.3 Maven summary
- •5.5 Grapes and @Grab
- •5.6 The Gradle build system
- •5.6.1 Basic Gradle builds
- •5.6.2 Interesting configurations
- •5.7 Summary
- •6 Testing Groovy and Java projects
- •6.1 Working with JUnit
- •6.1.1 A Java test for the Groovy implementation
- •6.1.2 A Groovy test for the Java implementation
- •6.1.3 A GroovyTestCase test for a Java implementation
- •6.2 Testing scripts written in Groovy
- •6.2.1 Useful subclasses of GroovyTestCase: GroovyShellTestCase
- •6.2.2 Useful subclasses of GroovyTestCase: GroovyLogTestCase
- •6.3 Testing classes in isolation
- •6.3.1 Coerced closures
- •6.3.2 The Expando class
- •6.3.3 StubFor and MockFor
- •6.4 The future of testing: Spock
- •6.4.1 The Search for Spock
- •6.4.2 Test well, and prosper
- •6.4.4 The trouble with tribbles
- •6.4.5 Other Spock capabilities
- •6.5 Summary
- •7 The Spring framework
- •7.1 A Spring application
- •7.2 Refreshable beans
- •7.3 Spring AOP with Groovy beans
- •7.4 Inline scripted beans
- •7.5 Groovy with JavaConfig
- •7.6 Building beans with the Grails BeanBuilder
- •7.7 Summary
- •8 Database access
- •8.1 The Java approach, part 1: JDBC
- •8.2 The Groovy approach, part 1: groovy.sql.Sql
- •8.3 The Java approach, part 2: Hibernate and JPA
- •8.4 The Groovy approach, part 2: Groovy and GORM
- •8.4.1 Groovy simplifications
- •8.5 Groovy and NoSQL databases
- •8.5.1 Populating Groovy vampires
- •8.5.2 Querying and mapping MongoDB data
- •8.6 Summary
- •9 RESTful web services
- •9.1 The REST architecture
- •9.3 Implementing JAX-RS with Groovy
- •9.4 RESTful Clients
- •9.5 Hypermedia
- •9.5.1 A simple example: Rotten Tomatoes
- •9.5.2 Adding transitional links
- •9.5.3 Adding structural links
- •9.5.4 Using a JsonBuilder to control the output
- •9.6 Other Groovy approaches
- •9.6.1 Groovlets
- •9.6.2 Ratpack
- •9.6.3 Grails and REST
- •9.7 Summary
- •10 Building and testing web applications
- •10.1 Groovy servlets and ServletCategory
- •10.2 Easy server-side development with groovlets
- •10.2.1 A “Hello, World!” groovlet
- •10.2.2 Implicit variables in groovlets
- •10.3.2 Integration testing with Gradle
- •10.3.3 Automating Jetty in the Gradle build
- •10.4 Grails: the Groovy “killer app”
- •10.4.1 The quest for the holy Grails
- •10.5 Summary
- •A.1 Installing a JDK
- •A.2 Installing Groovy
- •A.3 Testing your installation
- •A.4 IDE support
- •A.5 Installing other projects in the Groovy ecosystem
- •B.1 Scripts and the traditional example
- •B.2 Variables, numbers, and strings
- •B.2.1 Numbers
- •B.2.2 Strings and Groovy strings
- •B.3 Plain Old Groovy Objects
- •B.4 Collections
- •B.4.1 Ranges
- •B.4.2 Lists
- •B.4.3 Maps
- •B.5 Closures
- •B.6 Loops and conditionals
- •B.6.1 Loops
- •B.6.2 Conditionals
- •B.6.3 Elvis
- •B.6.4 Safe de-reference
- •B.7 File I/O
- •B.8.1 Parsing and slurping XML
- •B.8.2 Generating XML
- •B.8.3 Validation
- •B.9 JSON support
- •B.9.1 Slurping JSON
- •B.9.2 Building JSON
- •index
- •Symbols

56 |
CHAPTER 3 Code-level integration |
In the next section I want to relax that requirement. If you’re willing to use some classes from the Groovy standard library, life gets simpler.
3.2.2Working with the Groovy Eval class
There are two special classes in the Groovy library, groovy.util.Eval and groovy
.lang.GroovyShell, specifically designed for executing scripts. In this section I’ll show examples using the Eval class, and in the next section I’ll show GroovyShell. In each case, the goal is still to invoke external Groovy scripts from Java.
The Eval class is a utility class (all its methods are static) for executing operations that take none, one, two, or three parameters. The relevant methods are shown in table 3.1.
Table 3.1 Static methods in groovy.util.Eval for executing Groovy from Java
Eval.me Overloaded to take a String expression or an expression with a String symbol and an Object
Eval.x One argument: the value of x
Eval.xy Two arguments, x and y
Eval.xyz Three arguments, x, y, and z
To demonstrate the methods I’ll add additional tests to the JUnit test case. The test is written in Java, so I’ll automatically call Groovy from Java.
The following listing shows four tests, one for each of the static methods in the Eval class.
Listing 3.4 JUnit 4 test class verifying results of calling Eval methods from Java
public class ScriptingTests { @Test
public void testEvalNoParams() {
String result = (String) Eval.me("'abc' - 'b'"); assertEquals("ac",result);
}
@Test
public void testEvalOneParam() {
String result = (String) Eval.x("a", "'abc' - x"); assertEquals("bc",result);
}
Zero-argument me method
One-argument x method
@Test |
Two-argument |
|
xy method |
||
public void testEvalTwoParams() { |
|
|
String result = (String) Eval.xy("a", "b", "'abc' - x - y"); |
|
|
|
||
assertEquals("c",result); |
|
|
} |
|
|
@Test |
Three-argument |
|
public void testEvalThreeParams() { |
xyz method |
|
String result = |
|
|
(String) Eval.xyz("a", "b", "d", "'abc' - x - y + z");
www.it-ebooks.info

Executing Groovy scripts from Java |
57 |
assertEquals("cd",result);
}
}
In each test the Groovy script to be evaluated is included as a string. Unlike the ScriptEngine there’s no overload for instances of Reader, so to execute a script in a separate file would require reading the file into a string. The methods also assume that the input variables are called x, y, and z, which might be asking too much. Still, it’s interesting that this mechanism exists at all.
In addition to illustrating the mechanics of calling Groovy scripts from Java, the tests also demonstrate operator overloading in the String class. The minus operator in Groovy corresponds to the minus method in String. Its implementation to remove the first instance of its argument from the given string is used with strings to remove instances of substrings. In Groovy, strings can be contained within either single or double quotes. Single-quoted strings are regular Java strings, and double-quoted strings are parameterized strings, diplomatically called Groovy strings, but formally called, unfortunately, GStrings.6
The process of using Eval from Java is shown in figure 3.4.
|
|
|
|
|
me, x, |
||
|
Args |
|
|
|
xy, xyz |
|
|
Java class |
|
|
eval (Groovy) |
|
|
|
Script in Groovy |
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
Figure 3.4 Java calls the me, x, xy, or xyz method in the Groovy Eval class to execute a script.
The Eval class is convenient and simple, but often it’s too simple. It rests on a more powerful foundation, the GroovyShell class, which I’ll discuss next.
3.2.3Working with the GroovyShell class
The GroovyShell class is used for scripts that aren’t restricted to the special cases described in the previous section on Eval. The class groovy.lang.GroovyShell can be used to execute scripts, particularly when combined with a Binding.
Unlike Eval, the GroovyShell class does not contain only static methods. It needs to be instantiated before invoking its evaluate method. As a simple example, consider adding the following test to the previous set of test cases:
@Test
public void testEvaluateString() { GroovyShell shell = new GroovyShell();
6To make matters worse, simple parameters are injected into GStrings using a dollar sign. This has led to far too many “insert a $ into a GString” jokes. To me, this is a clear demonstration that we don’t have enough women in computer science. Don’t you think that if there had been one woman on the team at the time, she could have said, “Hey, that’s a funny joke, but let’s not build it into the standard library that’s going to be used by everybody forever?” After all, it’s hard enough to get a language named Groovy taken seriously by the Fortune 500 without going there, too. For my part, I call them Groovy strings, which is what the class should have been called all along. It is a funny joke, though—for about 10 minutes.
www.it-ebooks.info

58 |
CHAPTER 3 Code-level integration |
Object result = shell.evaluate("3+4"); assertEquals(7, result);
}
The evaluate method is heavily overloaded. The version I’m using here takes a string representing the script to be evaluated. Other overloads take a java.io.File or a java.io.Reader instance, with various additional arguments. There are overloads that take a java.io.InputStream as well, but they’re deprecated due to possible encoding issues.
So far, using the GroovyShell looks a lot like using the ScriptEngine class, though you can instantiate it directly in this case. To deal with input and output variables, however, the GroovyShell uses the groovy.lang.Binding class to provide a map of input and output variables.
The next listing shows the Binding and GroovyShell classes in action. It’s another test to add to the growing JUnit 4 test case.
Listing 3.5 Using GroovyShell and Binding to invoke the Google geocoder
Use binding in GroovyShell
@Test
public void testLatLng() {
Binding binding = new Binding(); |
Create and |
|||
binding.setVariable("street", "Blackheath Avenue"); |
||||
populate the |
||||
binding.setVariable("city", "Greenwich"); |
||||
binding |
||||
binding.setVariable("state", "UK"); |
|
|
|
|
GroovyShell shell = new GroovyShell(binding); |
|
|
|
|
try { |
|
|
Execute script |
|
shell.evaluate(new File("src/geocode.groovy")); |
|
|
||
|
|
using binding |
||
assertEquals(51.475, |
|
|
||
|
|
|
Double.parseDouble(
(String) binding.getVariable("lat")),0.001); |
|
Retrieve |
|
|
|||
assertEquals(0.00143, |
|||
output |
|||
Double.parseDouble( |
|||
variables |
|||
(String) binding.getVariable("lng")),0.001); |
|
||
|
|
}catch (CompilationFailedException e) { e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
Passing parameters into the script is easy enough using the setVariable method on the Binding. The binding is then used as an argument to the GroovyShell constructor. The script is run from Java using the evaluate method as usual, and the results are extracted by getting the output variables from the shell. Using a GroovyShell and Binding is illustrated in figure 3.5.
There’s more to the GroovyShell than I’m presenting here. I can use the parse method, rather than evaluate, to parse the script and retrieve a reference to the generated Script object. That way I can set the binding variables and rerun the script without having to recompile every time. GroovyShell also works with a hierarchy of classloaders and configurations. Allthough all of that is interesting, it doesn’t really
www.it-ebooks.info

|
|
|
Executing Groovy scripts from Java |
59 |
||||||
|
|
setVariable |
|
|
|
|
|
|
|
|
|
|
Binding |
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
(Groovy) |
|
|
|
|
|
|
|
|
getVariable |
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
Java class |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Evaluate |
|
|
|
|
|
|
|
GroovyShell |
|
|
|
|
||
|
|
|
|
|
|
|
Script in Groovy |
|
||
|
|
Evaluate |
|
(Groovy) |
|
Parse |
|
|
||
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
Figure 3.5 Java code sets variables in the Binding, which is used in the GroovyShell to execute Groovy code. The results are returned via the getVariable method in
the Binding.
add a lot to the integration story, so I’ll refer you to Dierk Koenig’s most excellent
Groovy in Action for details.
THE HARD WAY Use the ScriptEngine class from Java, or the Eval and GroovyShell classes from Groovy, along with a Binding if necessary, to call Groovy scripts from Java.
Between the ScriptEngine, Eval, and GroovyShell classes, hopefully you’ll agree that there are a variety of ways to execute Groovy scripts from Java. Collectively I still refer to this as “the hard way,” though it isn’t terribly hard, but it’s awfully indirect compared to the easy way. From now on I’ll stop trying to maintain the artificial separation of Java code from Groovy code. In order to make progress all I need to do is put the Groovy code into a class.
3.2.4Calling Groovy from Java the easy way
All the techniques I’ve discussed so far—using the JSR 223 ScriptEngine, or using the Groovy API classes Eval and GroovyShell—work just fine but feel overly complicated. Groovy is supposed to simplify your life, so although the mechanisms shown in the previous section all work, for most use cases there’s an easier way.
The easiest way to call Groovy from Java is to put the Groovy code in a class and compile it. Then Java code can instantiate the class and invoke its methods the normal way.
THE EASY WAY To call Groovy from Java, put the Groovy code in a class, compile it as usual, and then instantiate it and invoke methods as though it was Java.
Let’s return, once again, to the geocoder. This time, however, I’ll refactor it into a class that can be instantiated, with methods that can be invoked from outside. The process is shown in figure 3.6.
As the figure shows, the Java application will use a Location class to store all the needed attributes. It will supply the street, city, and state fields as input parameters, but the Location class will also include latitude and longitude fields that will be updated by the Groovy geocoder. The geocoder itself will be written in Groovy, because it’s easy to write the RESTful web service client code that way.7
7Note this is just like the geocoder with the Stadium class used in chapter 2 when I discussed the Groovy Baseball application. The differences here are the CSV output and that I’m invoking the Groovy implementation from Java.
www.it-ebooks.info

60 |
|
|
CHAPTER 3 Code-level integration |
||
|
|
new, setStreet, |
|
|
|
|
|
setCity, setState |
|
class Location |
|
|
|
|
|
|
(POJO or POGO) |
|
|
|
|
|
|
|
Java application |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Geocoder |
|
|
fillInLatLng(Location) |
|
(Groovy) |
|
|
|
||||
|
|
updates |
lat, lng |
|
|
Figure 3.6 Mixing Java and Groovy classes. The Java app instantiates a Location and supplies it with street, city, and state values. It sends the new Location to the Groovy geocoder, whose fillInLatLng method supplies the latitude and longitude, which can then be retrieved by Java again.
Here’s the new Location class, which could be written in either Java or Groovy. This time, to keep the code simple I’ll use a Groovy POGO:
class Location { String street String city String state
double latitude double longitude
}
The Location class encapsulates the address information in strings and provides double variables for the latitude and longitude values that will be set using the geocoder. Speaking of the geocoder, the next listing shows a revised version that wraps the script into a class.
Listing 3.6 A Groovy class for geocoding
class Geocoder {
def base = 'http://maps.google.com/maps/geo?'
void fillInLatLong(Location loc) { def addressFields = loc.street ?
[loc.street,loc.city,loc.state] : [loc.city,loc.state] def address = addressFields.collect {
URLEncoder.encode(it,'UTF-8') }.join(',')
def params = [q:address,sensor:false, output:'csv',key:'ABQIAAAAa…']
def url = base + params.collect { k,v -> "$k=$v" }.join('&') def (code,level,lat,lng) = url.toURL().text.split(',') loc.latitude = lat.toDouble()
loc.longitude = lng.toDouble()
}
}
The fillInLatLong method takes a Location as an argument. Strictly speaking, I didn’t have to declare a type for the parameter at all. I could have relied on duck typing
www.it-ebooks.info
Executing Groovy scripts from Java |
61 |
within the method and just been careful not to call it with anything other than an object with street, city, and state properties. Still, I’m building the service with a Location in mind, so it doesn’t hurt to say so.
The addressFields variable uses the ternary operator to determine whether or not a street has been supplied when returning the collection of address components. Note that I’m appealing to the so-called “Groovy truth” here, in that I don’t need to compare loc.street to null or an empty string explicitly. Any non-blank value of the street field as part of the loc argument will return true, so it will be added to the collection.
The rest of the class is the same as the previous script, though to make the class more useful I went to the trouble of converting the string results to doubles before returning the location.
One final issue is notable, and it highlights an important difference between a script and a class. All of the variables, whether they are local variables or attributes, have to be declared. There are no undefined variables, so there’s also no binding to worry about any more.
How do I use these classes (Geocoder and Location) from Java? Just instantiate them and call methods as usual. In the previous section I started accumulating JUnit 4 tests into a test class. Here’s another test to add to that set:
@Test
public void testGeocoder() { Location loc = new Location();
loc.setState("1600 Pennsylvania Avenue"); loc.setCity("Washington"); loc.setState("DC");
Geocoder geocoder = new Geocoder(); geocoder.fillInLatLong(loc); assertEquals(38.895,loc.getLatitude(),0.001); assertEquals(-77.037,loc.getLongitude(),0.001);
}
It doesn’t get much easier than that. I don’t need to instantiate a script engine or worry about Groovy shells or class loaders. Just instantiate and populate a Location, instantiate a Geocoder, and invoke the desired method.
From now on all of the examples I show will do integration the easy way. Again, this isn’t a value judgment against all the techniques demonstrated earlier in the chapter. If you want to call an existing Groovy script from Java, or you’re required to keep Java and Groovy code separate in your application, the previous mechanisms all work. Freely intermixing classes the way this script does, however, is very easy.
One last issue remains before I start looking at how Groovy might help Java. So far in this chapter the goal was always to call Groovy from Java. What about the other direction? How do you call Java from Groovy?
www.it-ebooks.info