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

102 |
CHAPTER 5 Build processes |
|
|
java(jar:"$jarDir/HelloAntBuilder.jar", fork:'true') { |
|
|
|
|
|
classpath { |
Execute |
|
path refid:'classpath' |
|
|
main |
|
|
path refid:'application' |
|
|
method |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
You execute this script with the groovy command. Inside the with block, all methods |
|
|
like mkdir, javac, and junit are passed to the builder instance. Formally this means |
|
|
that the delegate property for the with block is the AntBuilder instance. Because |
|
|
this is a Groovy script you could add any code you wish to do other processing. It’s |
|
|
notoriously awkward do arrange loops and conditionals inside XML files, for instance, |
|
|
but here that would be easy. |
|
|
For all of its simplicity, though, AntBuilder is still just Ant under the hood. Groovy |
|
|
wouldn’t be Groovy if there wasn’t a domain-specific language (DSL) alternative. The |
|
|
best of breed is Gradle, which is discussed later in this chapter. There’s another |
|
|
approach, however, which you may encounter in practice. For completeness the next |
|
|
subsection contains a brief discussion of Groovy Ant, known as Gant. |
|
5.3.4Custom build scripts with Gant
Although the future of build files in Groovy belongs to Gradle, Gant still occupies one special niche in the Groovy ecosystem. As of this writing, the latest version of the Grails framework (2.3)3 still implements its build scripts in Gant.4 If you need to create a custom build script for a Grails application, Gant is still useful. If you’re not planning to do that, you can comfortably skip this subsection.
GANT USE CASE Grails commands are implemented as Gant scripts, so if you need to customize a Grails command or create a new one, Gant is the tool of choice.
The Gant scripts in Grails are also an excellent choice of sample code. To keep this section simple I’ll review parts of an existing Grails Gant script, called Clean.groovy. The script can be found in the scripts directory under the root of the Grails distribution. As with all Grails Gant scripts, it’s invoked using the script name in lowercase, substituting dashes for camel case; so for the Clean script the command would be grails clean, and for the CreateDomainObject script the command is grails create-domain-object.
Here’s the Clean script in its entirety (minus the copyright statement):
includeTargets << grailsScript("_GrailsClean") setDefaultTarget("cleanAll")
3Grails is discussed in chapter 8 on databases and chapter 10 on web development. The home page for Grails is http://grails.org.
4Gant will continue to be included in Grails through at least version 2.3.
www.it-ebooks.info
Making Ant Groovy |
103 |
The grailsScript command loads a different Gant script, called _GrailsClean. By convention (and Grails is all about conventions), scripts that begin with an underscore are internal scripts that can’t be executed from the command line. The first line thus loads a series of tasks, and the second line makes the cleanAll task the default.
Turning now to the _GrailsClean script, let me highlight a couple of small sections from it:
includeTargets << grailsScript("_GrailsEvents")
target (cleanAll: "Cleans a Grails project") { clean()
cleanTestReports()
grailsConsole.updateStatus "Application cleaned."
}
target (clean: "Implementation of clean") { depends(cleanCompiledSources, cleanWarFile)
}
The resemblance to Ant is not accidental. Gant scripts contain targets, and targets can be invoked as though they were method calls. Here the target defined with the name cleanAll invokes two other tasks (clean and cleanTestReports) and then invokes the updateStatus method on the predefined grailsConsole object.
The clean task uses the depends method (again analogous to the same functionality in Ant) to make sure that the cleanCompiledSources and cleanWarFile tasks are invoked when the clean task is invoked. Here’s a snippet from the cleanCompiledSources task:
target (cleanCompiledSources: "Cleans compiled Java and Groovy sources") { def webInf = "${basedir}/web-app/WEB-INF" ant.delete(dir:"${webInf}/classes") ant.delete(file:webXmlFile.absolutePath, failonerror:false) ant.delete(dir:"${projectWorkDir}/gspcompile", failonerror:false)
The task goes on to delete many more items, delegating to an internal AntBuilder object in each case. The cleanWarFile task shows how you can mix in Groovy logic code inside a script:
target (cleanWarFile: "Cleans the deployable .war file") { if (buildConfig.grails.project.war.file) {
warName = buildConfig.grails.project.war.file
}
else {
def fileName = grailsAppName
def version = metadata.'app.version' if (version) {
fileName += "-$version"
}
warName = "${basedir}/${fileName}.war"
}
www.it-ebooks.info

104 |
CHAPTER 5 Build processes |
ant.delete(file:warName, failonerror:false)
}
This is straightforward Groovy code that simply defines some variables and sets their properties based on the current configuration, and then invokes the delete method on the ant object.
That’s enough Gant for this book.5
5.3.5Ant summary
That also concludes the discussion of Ant and Ant-based approaches, both in Java and Groovy. The “Lessons learned” sidebar shows the details.
Lessons learned (Ant)
1If you have an existing Ant build, you can add <groovyc> and <groovy> tasks to it.
2Gant is only used by Grails, and not for very much longer.
3AntBuilder is rare by itself but is built into and useful in Gradle
It’s time now to examine the other major build tool in the Java world: Maven.
Ant limitations
When it was released Ant was a major improvement over previous build processes. Still, it has major issues that complicate life, especially in larger builds. Here’s a brief list of complexities associated with using Ant. This is not intended to be a criticism of Ant, but rather to highlight the issues that lead to the next-generation tools.
Ant builds are based on XML, and XML is not a scripting language. Builds inevitably need to be customized and usually vary depending on whether the project is in development, test, or production mode. Ant allows you to set properties, but properties aren’t variables. It’s especially difficult to do complex branching logic in an XML file.
Ant says nothing about dependency management. It assumes you have all the required libraries available and that you can build a file set to hold them and use that as your classpath. The Ivy project (also from Apache) fills that gap, and the combination of Ant and Ivy is much more common now than Ant alone.
XML was designed to be processed by programs, not people. Reading a short XML file isn’t hard. Reading a long, involved one is, and even the trivial build file presented in this section is over 50 lines long when a few basic tasks are included.
5Additional information on Gant can be found at the Groovy website. There’s also a decent tutorial in the book Grails in Action (Manning, 2009), by Peter Ledbrook and Glen Smith. Finally, the Grails user guide has a section on creating Gant scripts specifically for Grails.
www.it-ebooks.info