
- •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
File I/O |
315 |
if (employee == null) { loc = null;
} else {
Department dept = employee.getDepartment(); if (dept == null) {
loc = null; } else {
loc = dept.getLocation();
}
}
That’s quite an expansion just to check for nulls. Here’s the Groovy version:
Location loc = employee?.department?.location
The safe de-reference operator returns null if the reference is null. Otherwise it proceeds to access the property. It’s a small thing, but the savings in lines of code is nontrivial.
Continuing on the theme of simplifying code over the Java version, consider input/output streams. Groovy introduces several methods in the Groovy JDK that help Groovy simplify Java code when dealing with files and directories.
B.7 File I/O
File I/O in Groovy isn’t fundamentally different from the Java approach. Groovy adds several convenience methods and handles issues like closing your files for you. A few short examples should suffice to give you a sense of what’s possible.
First, Groovy adds a getText method to File, which means that by asking for the text property you can retrieve all the data out of a file at once in the form of a string:
String data = new File('data.txt').text
Accessing the text property invokes the getText method, as usual, and returns all the text in the file. Alternatively, you can retrieve all the lines in the file and store them in a list using the readLines method:
List<String> lines = new File("data.txt").readLines()*.trim()
The trim method is used in this example with the spread-dot operator to remove leading and trailing spaces on each line. If your data is formatted in a specific way, the splitEachLine method takes a delimiter and returns a list of the elements. For example, if you have a data file that contains the following lines
1,2,3
a,b,c
then the data can be retrieved and parsed at the same time:
List dataLines = []
new File("data.txt").splitEachLine(',') { dataLines << it
}
assert dataLines == [['1','2','3'],['a','b','c']]
www.it-ebooks.info

316 |
APPENDIX B Groovy by feature |
Writing to a file is just as easy:
File f = new File("$base/output.dat") f.write('Hello, Groovy!')
assert f.text == 'Hello, Groovy!'
In Java, it’s critical to close a file if you’ve written to it, because otherwise it may not flush the buffer and your data may never make into the file. Groovy does that for you automatically.
Groovy also makes it easy to append to a file:
File temp = new File("temp.txt") temp.write 'Groovy Kind of Love' assert temp.readLines().size() == 1
temp.append "\nGroovin', on a Sunday afternoon..." temp << "\nFeelin' Groovy"
assert temp.readLines().size() == 3 temp.delete()
The append method does what it sounds like, and the left-shift operator has been overridden to do the same.
Several methods are available that iterate over files, like eachFile, eachDir, and even eachFileRecurse. They each take closures that can filter what you want.
Finally, I have to show you an example that illustrates how much simpler Groovy I/O streams are than Java streams. Consider writing a trivial application that does the following:
1Prompts the user to enter numbers on a line, separated by spaces
2Reads the line
3Adds up the numbers
4Prints the result
Nothing to it, right? The next listing shows the Java version.
Listing B.4 SumNumbers.java, an application to read a line of numbers and add them
package io; |
|
|
|
|
||
import java.io.BufferedReader; |
|
|
|
|
||
import java.io.IOException; |
|
|
|
|
||
import java.io.InputStreamReader; |
|
Must be |
|
|||
|
|
|||||
public class SumNumbers { |
|
in a class |
|
|||
public static void main(String[] args) { |
|
|
|
Has readLine |
||
|
|
|
||||
System.out.println("Please enter numbers to sum"); |
method |
|||||
BufferedReader br = |
|
|
|
|
||
|
|
|
|
|||
new BufferedReader(new InputStreamReader(System.in)); |
||||||
String line = ""; |
|
|
|
|
||
try { |
|
|
|
|
||
line = br.readLine(); |
|
|
try/catch for |
|
||
} catch (IOException e) { |
|
|
||||
|
checked exception |
|
||||
e.printStackTrace(); |
|
|
||||
|
|
|
|
|
||
} |
|
|
|
|
|
|
www.it-ebooks.info

XML
String[] inputs = line.split(" "); double total = 0.0;
for (String s : inputs) {
total += Double.parseDouble(s);
}
System.out.println("The sum is " + total);
}
}
317
Convert strings to doubles
That’s nearly 30 lines to do something extremely simple. All Java code has to be in a class with a main method. The input stream System.in is available, but I want to read a full line of data, so I wrap the stream in an InputStreamReader and wrap that in a BufferedReader, all so I can call readLine. That may throw an I/O exception, so I need a try/catch block for it. Finally, the incoming data is in string form, so I need to parse it before adding up the numbers and printing the results.
Here’s the corresponding Groovy version:
println 'Please enter some numbers' System.in.withReader { br ->
println br.readLine().tokenize()*.toBigDecimal().sum()
}
That’s the whole program. The withReader method creates a Reader implementation that has a readLine method and automatically closes it when the closure completes. Several similar methods are available for both input and output, including withReader, withInputStream, withPrintWriter, and withWriterAppend.
That was fun, but here’s another version that has more capabilities. In this case, the code has a loop that sums each line and prints its result until no input is given:
println 'Sum numbers with looping' System.in.eachLine { line ->
if (!line) System.exit(0)
println line.split(' ')*.toBigDecimal().sum()
}
The eachLine method repeats the closure until the line variable is empty.
Groovy’s contribution to file I/O is to add convenience methods that simplify the Java API and ensure that streams or files are closed correctly. It provides a clean façade on the Java I/O package.
Groovy makes input/output streams much simpler to deal with than in Java, so if I have a Java system and I need to work with files, I try to add a Groovy module for that purpose. That’s a savings, but nothing compared to the savings that result from using Groovy over Java when dealing with XML, as shown in the next section.
B.8 XML
I’ve saved the best for last. XML is where the ease-of-use gap between Groovy and Java is the largest. Working with XML in Java is a pain at best, while parsing and generating XML in Groovy is almost trivial. If I ever have to deal with XML in a Java system, I always add a Groovy module for that purpose. This section is intended to show why.
www.it-ebooks.info
318 |
APPENDIX B Groovy by feature |
B.8.1 Parsing and slurping XML
Some time ago, I was teaching a training course on XML and Java. One of the exercises started by presenting an XML file similar to this one:
<books>
<book isbn="9781935182443">
<title>Groovy in Action (2nd edition)</title> <author>Dierk Koenig</author> <author>Guillaume Laforge</author> <author>Paul King</author>
<author>Jon Skeet</author> <author>Hamlet D'Arcy</author>
</book>
<book isbn="9781935182948"> <title>Making Java Groovy</title> <author>Ken Kousen</author>
</book>
<book isbn="1933988932"> <title>Grails in Action</title> <author>Glen Smith</author> <author>Peter Ledbrook</author>
</book>
</books>
The goal of the exercise was to parse this file and print out the title of the second book. Because this file is small, you might as well use a DOM parser to read it. To do that in Java you need a factory, which then yields the parser, and then you can invoke a parse method to build the DOM tree. Then, to extract the data, there are three options:
■Walk the tree by getting child elements and iterating over them.
■Use the getElementById method to find the right node, and then get the first text child and retrieve its value.
■Use the getElementsByTagName method, iterate over the resulting NodeList to find the right node, and then retrieve the value of the first text child.
The first approach runs into problems with whitespace. This document has carriage returns and tabs in it, and because no DTD or schema is provided, the parser doesn’t know which whitespace elements are significant. Traversing the DOM is complicated by the fact that methods like getFirstChild will return whitespace nodes as well as elements. It can be done, but you’ll need to check the node type of each element to make sure you are working with an element rather than a text node.
The second approach only works if the elements have an attribute of type ID, and that’s not the case here.
You’re left with the getElementsByTagName method, which results in the following code:
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;
www.it-ebooks.info

XML |
319 |
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException;
public class ProcessBooks {
public static void main(String[] args) { DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance(); Document doc = null;
try {
DocumentBuilder builder = factory.newDocumentBuilder(); doc = builder.parse("books.xml");
}catch (ParserConfigurationException e) { e.printStackTrace();
}catch (SAXException e) { e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
NodeList titles = doc.getElementsByTagName("title"); Element titleNode = (Element) titles.item(1);
String title = titleNode.getFirstChild().getNodeValue(); System.out.println("The second title is " + title);
}
}
Parsing the document can throw all sorts of exceptions, as shown. Assuming nothing goes wrong, after parsing, the code retrieves all the title elements. After getting the proper element out of the NodeList and casting it to type Element, you then have to remember that the character data in the element is in the first text child of the element rather than the element itself.
Here’s the Groovy solution:
root = new XmlSlurper().parse('books.xml')
assert root.book[1].title == 'Making Java Groovy'
Wow. Groovy includes the XmlSlurper class, which is in the groovy.util package (no import required). XmlSlurper has a parse method that builds the DOM tree and returns the root element. Then it’s a question of walking the tree, using the dot notation for child elements. Elements that appear multiple times form a collection that can be accessed with an index in the normal way. The contrast in both size and complexity between the Groovy version and the Java version is clear.
The next listing demonstrates working with the XML file.
Listing B.5 Slurping XML
String fileName = 'books.xml'
def books = new XmlSlurper().parse(fileName)
assert books.book.size() == 4
assert books.book[0].title == "Groovy in Action"
www.it-ebooks.info