
- •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
Collections |
307 |
One of the nicest features of Groovy collections is that they’re searchable. Groovy adds both find and findAll methods to collections. The find method takes a closure and returns the first element that satisfies the closure:
assert 'New Hampshire' ==
['New Hampshire','New Jersey','New York'].find { it =~ /New/ }
The findAll method returns all the elements that satisfy the closure. This example returns all the cities that have the letter e in their name:
def withE = cities.findAll { city -> city =~ /e/ } assert withE == ['Seattle', 'New York', 'Cleveland']
Groovy also supplies the methods any and every, which also take closures:
assert cities.any { it.size() < 7 } assert cities.every { it.size() < 10 }
The first expression states that there’s at least one city whose name is less than 7 characters. The second expression says that all of the city names are 10 characters or less.
Table B.1 summarizes the searchable methods.
Table B.1 Searchable methods added to Groovy collections
Method |
Description |
|
|
any |
Returns true if any element satisfies closure |
every |
Returns true if all elements satisfy closure |
find |
Returns first element satisfying closure |
findAll |
Returns list of all elements satisfying closure |
|
|
Finally, the join method concatenates all the elements of the list into a single string, using the supplied separator:
assert cities.join(',') == "Boston,Seattle,New York,Cleveland"
The combination of native syntax and added convenience methods makes Groovy lists much easier to work with than their Java counterparts. As it turns out, maps are improved the same way.
B.4.3 Maps
Groovy maps are like Java maps, but again with a native syntax and additional helper methods. Groovy uses the same square-bracket syntax for maps as for lists, but each entry in the map uses a colon to separate the key from its corresponding value.
You can populate a map right away by adding the elements when you declare the map itself:
www.it-ebooks.info

308 |
APPENDIX B Groovy by feature |
def trivialMap = [x:1, y:2, z:3] assert 1 == trivialMap['x']
assert trivialMap instanceof java.util.HashMap
This defines a map with three entries. When adding elements to the map, the keys are assumed to be strings, so you don’t need to put quotes around them. The values can be anything.
MAP KEYS When adding to a map, the keys are assumed to be of type string, so no quotes are necessary.
You can add to a map using either Java or Groovy syntax:
def ALEast10 = [:] ALEast.put('Boston','Red Sox')
assert 'Red Sox' == ALEast.get('Boston') assert ALEast == [Boston:'Red Sox'] ALEast['New York'] = 'Yankees'
Accessing values can be done with either the array-like syntax shown, or using a dot. If the key has spaces in it, wrap the key in quotes:
assert 'Red Sox' == ALEast.Boston assert 'Yankees' == ALEast.'New York'
I’ve been using def to define the map reference, but Groovy understands Java generics:
Map<String,String> ALCentral = [Cleveland:'Indians', Chicago:'White Sox',Detroit:'Tigers']
assert 3 == ALCentral.size()
assert ALCentral.Cleveland == 'Indians'
Maps have a size method that returns the number of entries. Actually, the size method is universal.
SIZE In Groovy, the size method works for arrays, lists, maps, strings, and more.
Maps have an overloaded plus operation that combines the entries from two maps:
def both = ALEast + ALCentral assert 5 == both.size()
Like Java maps, you can extract the set of keys from a map using the keySet method:
assert ALEast.keySet() == ['Boston','New York'] as Set
Maps also have a rather controversial method that lets you add a new element with a default in case the element doesn’t exist:
assert 'Blue Jays' == ALEast.get('Toronto','Blue Jays') assert 'Blue Jays' == ALEast['Toronto']
Here I’m trying to retrieve a value using a key that isn’t in the map (Toronto). If the key exists, its value is returned. If not, it’s added to the map, with the second argument
10 For non-baseball people, ALEast is short for the Eastern division of the American League.
www.it-ebooks.info