
- •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

Refreshable beans |
175 |
testing. From Spring’s point of view, Groovy beans are just bytecodes by another name. As long as the groovy-all JAR file is in the classpath, Spring is quite happy to use beans written in Groovy.
Spring manages beans from Groovy as easily as it manages beans from Java. There are special capabilities that Spring offers beans from dynamic languages, though. I’ll illustrate them in the next sections, beginning with beans that can be modified in a running system.
7.2Refreshable beans
Since version 2.0, Spring has provided special capabilities for beans from dynamic languages like Groovy. One particularly interesting, if potentially dangerous, option is to deploy what are known as refreshable beans.
For refreshable beans, rather than compile classes as usual, you deploy the actual source code and tell Spring where to find it and how often to check to see if it has changed. Spring checks the source code at the end of each refresh interval, and if the file has been modified it reloads the bean. This gives you the opportunity to change deployed classes even while the system is still running.3
I’ll demonstrate a somewhat contrived but hopefully amusing example. In the previous section I presented an application for managing accounts. Let me now assume that the account manager, presumably some kind of bank, decides to get into the mortgage business. I now need a class representing a mortgage application, which a client would submit for approval. I’m also going to need a mortgage evaluator, which I’ll implement both in Java and in Groovy. The overall system is shown in figure 7.3.
To keep this example simple, the mortgage application class only has fields representing the loan amount, the interest rate, and the number of years desired, as shown in the next listing.
Mortgage |
|
|
|
<<interface>> |
|
|
|
|
||
application |
|
|
|
Evaluator |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JavaEvaluator |
|
GroovyEvaluator |
|
|
Modify source code. |
||||
|
|
(refreshable) |
|
|
Spring loads new version. |
|||||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
Figure 7.3 The GroovyEvaluator is a refreshable bean. The source code is deployed, and Spring checks it for changes after each refresh interval. If it has changed, Spring reloads the bean.
3Yes, that’s a scary notion to me, too. The Spider-Man corollary applies: With Great Power Comes Great Responsibility.
www.it-ebooks.info

176 |
CHAPTER 7 The Spring framework |
Listing 7.8 A trivial mortgage application class in Groovy
class MortgageApplication { BigDecimal amount BigDecimal rate
int years
}
As before, Groovy is used just to reduce the amount of code and to make it easier to work with BigDecimal instances. An instance of this class is submitted to the bank, which runs it through a mortgage evaluator to decide whether or not to approve it. The following listing shows a Java interface representing the evaluator, which will be implemented in both Java and Groovy.
Listing 7.9 The Evaluator interface in Java
public interface Evaluator {
boolean approve(MortgageApplication application);
}
The interface contains only one method, approve, which takes a mortgage application as an argument and returns true if the application is approved and false otherwise.
Pretend now that it is currently the summer of 2008. The general public is blissfully unaware of terms like credit default swaps, and banks are eager to loan as much money as possible to as many people as possible. In other words, here’s a Java implementation of the Evaluator interface.
Listing 7.10 A Java evaluator, with a rather lenient loan policy
public class JavaEvaluator implements Evaluator {
public boolean approve(MortgageApplication application) { return true;
}
}
That’s a very forgiving loan policy, but if everyone else is doing it, what could go wrong? What went wrong, of course, is that in the late summer and early fall of 2008, Bear Stearns collapsed, Lehman Brothers went bankrupt, and the U.S. economy nearly collapsed. The bank needs to stop the bleeding as soon as possible. If the evaluator in place is the Java evaluator just shown, then the system has to be taken out of service in order to modify it. The fear is that if the system is taken offline, then customers might
worry that it will never come back again.4
There’s another possibility, however. Consider the Groovy version of the mortgage evaluator, whose behavior is equivalent to the Java version, as shown in the following listing.
4 That’s an It’s a Wonderful Life reference: “George, if you close those doors, you’ll never open them again!”
www.it-ebooks.info

Refreshable beans |
177 |
Listing 7.11 A Groovy mortgage evaluator deployed as source code
class GroovyEvaluator implements Evaluator {
boolean approve(MortgageApplication application) { true }
}
Again, it simply returns true, just as the Java version did. Rather than compiling this class and deploying it as usual, however, this time I want to create a refreshable bean. To do so, I need to work with the lang namespace in the Spring configuration file (assuming I’m using XML; alternatives exist for Java configuration files). I also need to deploy the source code itself, rather than the compiled version of this file.
DEPLOYING SOURCE Note that for refreshable beans you deploy the source, not the compiled bean.
The next listing shows the bean configuration file with both evaluators. Note the addition of the lang namespace and the Groovy bean.
Listing 7.12 The bean configuration file with the refreshable Groovy evaluator bean
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd">
Namespace for dynamic languages
<bean id="javaEvaluator" class="mjg.spring.JavaEvaluator" />
<lang:groovy id="groovyEvaluator" script-source="file:resources/GroovyEvaluator.groovy" refresh-check-delay="1000" />
</beans>
Refreshable bean
Groovy provides a namespace for beans from dynamic languages, including Groovy, BeanShell, and JRuby. One of the elements declared in that namespace is <lang: groovy>, whose script-source attribute is used to point to the source code of a Groovy class. Note that unlike the Java evaluator bean in the same file, this attribute points to the actual source file, rather than the compiled bean. The other important attribute for the element is refresh-check-delay, which indicates the time period, in milliseconds, after which Spring will check to see if the source file has changed. Here the delay has been set to one second.
Now comes the fun part.5 The next listing shows a demo application that loads the Groovy evaluator bean and calls the approve method 10 times, sleeping for one second between each call.
5 Seriously. This is a fun demo to do in front of a live audience. Try it and see.
www.it-ebooks.info

178 |
CHAPTER 7 The Spring framework |
|
|||
|
|
|
|
|
|
|
Listing 7.13 A demo application that loads the Groovy bean and calls approve 10 times |
||||
|
public class Demo { |
|
|||
|
public static void main(String[] args) { |
|
|||
|
ApplicationContext ctx = |
|
|||
|
new FileSystemXmlApplicationContext( |
|
|||
|
"resources/applicationContext.xml"); |
|
|||
|
Evaluator e = null; |
Load |
|||
|
boolean ok; |
||||
|
refreshable |
||||
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++) { |
bean |
|||
|
|
||||
|
e = (Evaluator) ctx.getBean("groovyEvaluator"); |
|
|
|
|
|
|
|
|
||
|
ok = e.approve(null); |
|
|
Check |
|
|
System.out.println(ok ? "approved" : "denied"); |
|
|||
|
|
approval |
try { Thread.sleep(1000);
} catch (InterruptedException ie) { ie.printStackTrace();
}
}
}
}
Gives time to change the implementation of approve
The idea is to start the demo running and then, while the iteration is going, edit the source code to change the return value of the approve method from true to false.6 The output of the program resembles
approved |
|
|
|
approved |
|
|
|
approved |
|
|
|
approved |
|
|
|
approved |
|
Code |
|
|
|||
denied |
|
|
changed |
|
|
||
denied |
|
here |
|
denied |
|
|
|
denied |
|
|
|
denied |
|
|
The source code is changed halfway through the loop to stop the bleeding. If Congress should then spring7 into action and award a massive government bailout, it can be changed back.8
The ability to change the implementation of a bean inside a running system is powerful, but obviously risky. Spring only makes it available to beans from dynamic languages like Groovy.
6Did you notice that the approve method was invoked with a null argument, acknowledging that the mortgage application doesn’t matter at all? That’s part of the gag, so be sure to chuckle when you do it.
7Ouch. Yes, a bad pun, but an irresistible one.
8Or not.
www.it-ebooks.info