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

122 |
CHAPTER 5 Build processes |
5.6.2Interesting configurations
Gradle builds are used throughout this book. I’ll bring up lots of different options when discussing specific examples in context, but here I can discuss a few interesting ideas.
CUSTOM SOURCE SETS
First, one of the running themes in this book is that separating Groovy source code from Java source code is rather artificial. What if you wanted to use the same source folder for both, as an Eclipse project might do? Here’s an easy customized project layout to do so:
sourceSets { main {
java { srcDirs = [] } groovy { srcDir 'src' }
}
test {
java { srcDirs = [] } groovy { srcDir 'src' }
}
}
Source sets are collections of source code in a Gradle build. Here, by assigning the srcDirs property of both the src/main/java and src/test/java folders to an empty list, the Java compiler won’t run at all. Instead, the Groovy compiler is used for all classes in the src directory, which will presumably hold both Java and Groovy classes.
COPYING JARS
Another useful tactic is to make a local copy of the dependent libraries. The following task does that:
task collectJars(type: Copy) { into "$buildDir/output/lib"
from configurations.testRuntime
}
The collectJars task is a kind of Copy task—one of the built-in task types in Gradle. Running collectJars copies the JAR files in the runtime classpath into the output/ lib folder in the build directory. Spock uses this task to make a complete distribution.
INPUTS AND OUTPUTS
Another neat capability of Gradle is that it can skip tasks that aren’t necessary. It does this by creating hashes of files and directories and checking whether or not they have changed. The following listing shows an example taken from the samples11 that come with Gradle.
11See the userguide/tasks/incrementalBuild/inputsAndOutputs directory in the download distribution. Gradle comes with a huge number of very simple samples like this one.
www.it-ebooks.info

The Gradle build system |
123 |
||||||
|
|
|
|
|
|
|
|
Listing 5.19 Inputs/outputs example from the incrementalBuilds Gradle sample |
|||||||
task transform { |
|
|
External properties for the |
||||
|
|||||||
ext.srcFile = file('mountains.xml') |
|
|
|
source and destination files |
|||
ext.destDir = new File(buildDir, 'generated') |
|
|
|
|
Time-stamped file |
||
inputs.file srcFile |
|
||||||
|
|||||||
outputs.dir destDir |
|
and directory |
|||||
doLast { |
|
|
|
|
|||
println "Transforming source file." |
|
|
|
Executed only if |
|||
destDir.mkdirs() |
|
|
|
||||
|
|
|
inputs or outputs |
||||
def mountains = new XmlParser().parse(srcFile) |
|
|
|
||||
|
|
|
have changed |
||||
mountains.mountain.each { mountain -> |
|
|
|
||||
|
|
|
|
def name = mountain.name[0].text()
def height = mountain.height[0].text()
def destFile = new File(destDir, "${name}.txt") destFile.text = "$name -> ${height}\n"
}
}
}
The srcFile and destDir properties of the script are assigned to the ext map, which puts them in the project but avoids any potential conflict with existing Project properties. The inputs and outputs properties can be assigned to either files or directories (in other words, the word file is interpreted as a java.io.File). If both properties are the same as during the previous run, the code inside the doLast block is skipped.
ANT INTEGRATION
One of the nice features of Gradle is that it includes an instance of groovy.ant.AntBuilder as part of the build. That means that anything that can be done with Ant can be handled inside a Gradle build. That has a couple of consequences. First, if you already have an Ant build file, you can invoke its tasks inside a Gradle build. You can even make the Gradle tasks dependent on the Ant tasks.
Consider this example, from the Gradle samples.12 The Ant build file is build.xml, and it contains a single task called hello:
<project>
<target name="hello"> <echo>Hello, from Ant</echo>
</target>
</project>
The Gradle build is in the file build.gradle:
ant.importBuild 'build.xml'
task intro(dependsOn: hello) << { println 'Hello, from Gradle'
}
12 See userguide/ant/dependsOnAntTarget in the distribution.
www.it-ebooks.info