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

The Gradle build system |
117 |
Listing 5.13 Using Apache Commons Math and a database driver together
@GrabConfig(systemClassLoader=true)
@Grapes([ @Grab('org.apache.commons:commons-math3:3.0'),
@Grab(group='com.h2database', module='h2', version='1.2.140')
])
import static java.lang.Math.*
import org.apache.commons.math3.complex.Complex import org.apache.commons.math3.complex.ComplexUtils import groovy.sql.Sql
Sql sql = Sql.newInstance(url:'jdbc:h2:mem:',driver:'org.h2.Driver')
sql.execute '''
create table coordinates (
id bigint generated by default as identity, angle double not null,
x double not null, y double not null, primary key (id)
)
'''
int n = 20
def delta = 2*PI/n (0..<n).each { num ->
Complex c = ComplexUtils.polar2Complex(1, num*delta) sql.execute """
insert into coordinates(id,angle,x,y)
values(null, ${i*delta}, $c.real, $c.imaginary)
"""
}
sql.rows('select * from coordinates').each { row -> println "$row.id, $row.angle, $row.x, $row.y"
}
The script creates a table to hold x and y coordinates at 20 points along a circle. The ComplexUtils.polar2Complex method takes a radius (here using one for simplicity) and an angle (in radians) along the circle and generates a complex number, which is then stored in the database.
The Grapes system is simple and effective, but limited in practice. The additions work in a script, but for a larger system it’s more common to use a full-scale build tool, like Gradle, which is the subject of the next section.
5.6The Gradle build system
Gradle is proposed as a next-generation build solution. Gradle combines the flexibility of Groovy builds with a powerful domain-specific language (DSL) that configures a rich set of classes.
www.it-ebooks.info

118 |
CHAPTER 5 Build processes |
As with virtually all Groovy projects of any significant size, Gradle is written in both Java and Groovy. Gradle is essentially a DSL for builds.10 It defines a language of syntax and semantics that allows you to write a build file quickly and easily.
Gradle doesn’t come with an installer. Instead you just download a ZIP file, set the GRADLE_HOME environment variable to wherever you unzip it, and add the $GRADLE_ HOME/bin directory to your path, and you’re ready to go. In fact, you don’t even need to install Groovy first, because Gradle comes with its own version of Groovy.
How projects in the Groovy ecosystem include Groovy
One of the dirty little secrets of Groovy is that the major versions are not always binary compatible. Code compiled with one version doesn’t necessarily work with any other.
This means that projects in the Groovy ecosystem have a choice. They can either be compiled with different versions of Groovy and make the Groovy version number part of their own version, or they can bundle in a particular version of Groovy.
The Spock framework (discussed in chapter 6) takes the former approach. Spock versions are in the form 0.7-groovy-2.0, meaning Spock version 0.7 compiled with Groovy version 2.0.
The Grails and Gradle projects take the other approach. Grails 1.3.9, for example, includes a copy of Groovy 1.7.8, Grails 2.0.3 includes Groovy 1.8.6, and Grails 2.2.1 includes Groovy 2.0.8. To see the Groovy version included in your Gradle distribution, run the gradle –v command.
For Grails, the bundled Groovy version locks you into that version for the entire application. For Gradle, however, the bundled Groovy version is used only to execute the build script itself. You’re free to use any version of Groovy in your own projects, and Gradle will correctly build them.
When you run the gradle –v command, in addition to showing the Gradle and Groovy versions, Gradle also reports the included versions of Ant and Ivy, as well as the
JVM and OS.
Gradle builds range from extremely simple to quite powerful. I’ll start with the simplest possible example and build from there.
5.6.1Basic Gradle builds
Gradle is a plugin-based architecture. Most Gradle tutorials start by defining what a task is and showing how to call one. Rather than do that here, let me instead show you a minimal build file and go from there.
10Mandatory DSL jokes: “JavaScript is a DSL for finding browser bugs”; “Java is a DSL for generating stack traces”; “Maven is a DSL for downloading the internet.”
www.it-ebooks.info

The Gradle build system |
119 |
Here’s the smallest possible Gradle build for a Java project, in a file called build.gradle:
apply plugin:'java'
The apply syntax indicates that the build is using the Java plugin. When you run the build command using this file, Gradle executes tasks in several stages, as shown:
:compileJava UP-TO-DATE :processResources UP-TO-DATE :classes UP-TO-DATE
:jar
:assemble
:compileTestJava UP-TO-DATE :processTestResources UP-TO-DATE :testClasses UP-TO-DATE
:test
:check
:build
BUILD SUCCESSFUL
Each word after the colon is a Gradle task. Gradle constructs a Directed Acyclic Graph (DAG) out of the specified tasks, paying attention to their dependencies, and then executes them in order. This minimal project has no source code, so the compile tasks are up to date without running at all. In fact, the only task that does anything is the jar task, which creates a JAR file in the build/libs directory.
If you’re doing any testing your project will need to include the JUnit dependency. Consider a simple project that uses standard Maven structure, so that any Java classes are contained in src/main/java, and any tests are in src/test/java. The next listing shows a POJO called Greeting with a single String property called message.
Listing 5.14 A Greeting POJO to demonstrate a Gradle build
public class Greeting {
private String message = "Hello, World!";
public String getMessage() { return message;
}
public void setMessage(String message) { this.message = message;
}
}
The following listing is a JUnit test called GreetingTest, which checks the getter and setter.
Listing 5.15 A JUnit test for the Greeting POJO
import static org.junit.Assert.*; import org.junit.Test;
public class GreetingTests {
private Greeting greeting = new Greeting();
www.it-ebooks.info

120 |
CHAPTER 5 Build processes |
@Test
public void testGetGreeting() {
assertEquals("Hello, World!", greeting.getMessage());
}
@Test
public void testSetGreeting() { greeting.setMessage("What up?"); assertEquals("What up?", greeting.getMessage());
}
}
The next listing shows a Gradle build file with a JUnit dependency during the testing phase. It’s still a “Hello, World” example, but it does introduce some essential concepts.
Listing 5.16 A build.gradle file for the POJO application with testing
apply plugin:'java'
repositories { mavenCentral()
} |
|
|
|
dependencies { |
|
Maven notation |
|
|
|||
testCompile 'junit:junit:4.10' |
|
|
‘group:artifact:version’ |
|
|
|
|
} |
|
|
|
The terms repositories and dependencies are part of the Gradle DSL. Any required libraries are listed in the dependencies block. There are several legal forms for listing dependencies. The one used here is a string separated by colons. Using Maven syntax is not an accident, as shown in the repositories section. Many different types of repositories can be used, but here the standard Maven central repository is declared.
Executing the build this time runs the same series of tasks, but now any tests are executed and a JUnit report in HTML form is produced in the build/reports/tests directory.
That demonstrated that a Gradle build can be applied to a Java project with no Groovy dependencies. To show that the same process works on mixed Java/Groovy projects, I’ll add a Groovy test case, called GroovyGreetingTests, in the src/test/ groovy directory. The test case is shown in the next listing.
Listing 5.17 A Groovy test for the POJO, making this a mixed Java/Groovy project
import static org.junit.Assert.* import org.junit.Test
class GroovyGreetingTests {
Greeting greeting = new Greeting()
@Test
void testGetMessage(){
assert 'Hello, World!' == greeting.message
}
www.it-ebooks.info

The Gradle build system |
121 |
@Test
void testSetMessage() { greeting.message = 'Yo, dude'
assert 'Yo, dude' == greeting.message
}
}
The new build.gradle file requires a Groovy dependency. Prior to Gradle version 1.6 the name of the dependency was “groovy”. Now the preferred notation is to declare the Groovy dependency as a standard compile-time requirement. The complete build.gradle file is shown in the following listing.
Listing 5.18 A build.gradle file for a mixed Java/Groovy project
apply plugin:'groovy'
repositories { mavenCentral()
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.1.5' testCompile 'junit:junit:4.10'
}
The other change to the build file is that the Java plugin has been replaced by the Groovy plugin, which includes the Java tasks already. The new plugin adds a couple of tasks to the build, as shown here:
:compileJava :compileGroovy UP-TO-DATE
:processResources UP-TO-DATE :classes
:jar
:assemble
:compileTestJava
:compileTestGroovy :processTestResources UP-TO-DATE :testClasses
:test
:check
:build
BUILD SUCCESSFUL
Both the compileGroovy and compileTestGroovy tasks are new, but everything else proceeds normally. The classes are compiled, the tests run, and the HTML test report is produced.
That’s the basic structure of a Gradle build file when dealing with Java, Groovy, or mixed Java/Groovy projects. Similar files are shown throughout this book. To illustrate some interesting Gradle features I’ll now consider several use cases that often come up in practice.
www.it-ebooks.info