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

Build processes
This chapter covers
■Adding Groovy to Ant builds
■Using Maven with Groovy
■Groovy Grapes and @Grab
■The future: Gradle
Building source code is almost always a pain point in development organizations. An ideal build process is automated end-to-end, including compilation, running tests, generating reports, and producing any required artifacts. The process needs to be fast enough that it can be done frequently, especially given modern agile approaches, and yet flexible enough to adapt to the exigencies of individual teams.
In the Java world two primary approaches to automated builds have emerged over time. Both are open source projects from Apache. The first is Ant (http:// ant.apache.org), which uses a library of tasks configured in XML backed by Java classes. The other is Maven (http://maven.apache.org), which offers a rich array of options and promises to make the entire process simple, but uses a highly opinionated API that requires a degree of mastery to use effectively.
To start I want to address the goals of any build process, and then see how the various tools attempt to meet them.
93
www.it-ebooks.info

94 |
CHAPTER 5 Build processes |
5.1The build challenge
A software build combines several features that individually seem like they ought to be easy but in practice become complicated. To build your code you must
■Download any necessary dependencies.
■Compile the source code with the dependencies properly resolved, handling any cross-language issues that may arise.
■Run the unit, integration, and/or functional tests.
■Produce the desired artifacts, whatever they may be.
Optionally, other tasks might include checking code out of source code control, generating documentation, and even deploying the results into production.
The IDE build
Some companies still do their builds inside integrated development environments (IDEs). Although this is not in itself a bad thing, it often leads to long-term problems. Sooner or later such companies wind up with a special computer that no one is allowed to touch, even though the original owner left or transferred to another division long ago, because it’s the only system where the build still works.
Current thinking is that the source code control system should manage all aspects of a build, from the required scripts to the JAR dependencies. That way you can always be sure the build is correct and self-sufficient, which avoids the whole “at least it works on my machine” problem.
Java |
Ant |
Maven |
Groovy |
Gant |
Groovy |
GMaven |
|
Ant tasks |
Eclipse plugin |
|||
|
|
|||
Java + |
|
|
|
|
Groovy |
|
|
|
|
AntBuilder |
|
|
|
Groovy |
Grapes and |
Gradle |
|
@Grab |
|
|
|
Figure 5.1 Guide to technologies in this chapter. Java approaches are based on Ant or Maven. Groovy supplies Ant tasks for compilation and executing scripts. Gant is used by Grails but will eventually be replaced by Gradle. The AntBuilder class is useful and built into Gradle. There are two separate plugins available for Maven builds. Groovy Grapes make it easy to deliver code (normally scripts) to a client without compiling it first. Ultimately, though, the future belongs to Gradle.
www.it-ebooks.info

The Java approach, part 1: Ant |
95 |
In fact, the recent trend in development processes is toward continuous delivery, where a single command performs the whole sequence from build to deployment in one motion.1
There are two primary build tools in the Java world: Ant and Maven. Ant is older and is gradually being replaced, but it is still common in the industry and is the foundation of everything that came afterward. Maven is used extensively in the Java industry but tends to trigger strong feelings in developers.
A guide to the technologies covered in this chapter is shown in figure 5.1. I’ll start with the Apache Ant project in the next section.
5.2The Java approach, part 1: Ant
Apache Ant is a Java-based build tool, based on the older “make” technology but without many of its difficulties. The name Ant represents either “another neat tool” or a tool that lifts far more than its own weight, depending on whom you ask. Ant build files are written in XML, so they are inherently cross-platform, and because Java classes implement the XML tasks, a single API suffices for all operating systems.
That’s the good news. The (somewhat) bad news is that Ant is an extremely lowlevel API, so many build files consist of lots of twisty little tasks, all alike.2
Let me start with a “Hello, World” example in the next listing, based on a sample from the Ant tutorial provided by Apache at the Ant website.
Listing 5.1 build.xml: A simple Ant build file for a “Hello, World” Java application
<project name="HelloWorld" basedir="." default="main">
<property name="src.dir" value="src"/> <property name="build.dir" value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/> <property name="jar.dir" value="${build.dir}/jar"/> <property name="main-class" value="mjg.HelloWorld"/>
<target name="clean">
<delete dir="${build.dir}"/> </target>
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}" includeantruntime="false"/>
</target>
<target name="jar" depends="compile"> <mkdir dir="${jar.dir}"/>
<jar destfile="${jar.dir}/${ant.project.name}.jar"
1See Jez Humble and Dave Farley’s book Continuous Delivery (Addison Wesley, 2010) for details. (Available through its companion website, http://continuousdelivery.com/.)
2Yes, an Adventure (or Zork) reference. I just mean they’re small, they’re many, and they’re easy to get lost in.
www.it-ebooks.info

96 |
CHAPTER 5 Build processes |
basedir="${classes.dir}"> <manifest>
<attribute name="Main-Class" value="${main-class}"/> </manifest>
</jar>
</target>
<target name="run" depends="jar">
<java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/> </target>
<target name="clean-build" depends="clean,jar"/>
<target name="main" depends="clean,run"/>
</project>
By default, this file is called build.xml and resides in the root directory of the project. The root element of the project file is called <project>, which is given a name, a base directory, and the name of a default task to run if none is supplied on the command line.
At the top of the file a series of properties are set, including the locations of various directories. Note that one property can refer to another by using the ${...} syntax.
A series of <task> elements (clean, compile, jar, run, clean-compile, and main) are defined to represent individual actions during the build process. Some tasks depend on others, which is expressed using the depends attribute of the <task> element.
All the defined tasks ultimately delegate to a library of predefined Ant tasks. Here those tasks include file-based tasks like mkdir and delete, and Java-related tasks like javac, jar, and java.
Executing this build without arguments means typing ant at the command line, which will execute the default main task. Because main depends on clean and run it will execute those tasks first, which will execute their own individual dependencies, and so on. The result looks like the following listing.
Listing 5.2 Execution of the default task in the “Hello, World” Ant build
Buildfile: /.../build.xml clean:
[delete] Deleting directory /.../build compile:
[mkdir] Created dir: /.../build/classes
[javac] Compiling 1 source file to /.../build/classes
jar:
[mkdir] Created dir: /.../build/jar
[jar] Building jar: /.../build/jar/HelloWorld.jar
run:
[java] Hello, World! main:
BUILD SUCCESSFUL Total time: 1 second
www.it-ebooks.info