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

Implementing JAX-RS with Groovy |
239 |
when:
def response = client.put(path: "people/${kirk.data.id}", contentType: ContentType.JSON, body: json)
then:
"$response.data.first $response.data.last" == 'James T. Kirk'
}
private List getAll() { client.get(path: 'people').data
}
void cleanupSpec() { server?.stop()
}
}
The JAX-RS annotations are easy enough to use. Building a URL-driven API with them isn’t difficult. The 2.0 version of the spec also includes a client-side API, but that’s not shown here.
Lessons learned (JAX-RS)
1JAX-RS 2.0 is part of the Java EE specification and, like most of the recent specs, is annotation-based.
2It’s very easy to build a hyperlink-driven database using JAX-RS.
3Hypermedia mechanisms do exist in JAX-RS, but they’re well hidden.
Instead, I want to illustrate the Groovy implementation of the same specifications, mostly to illustrate the code simplifications. After that I’ll deal with the issue of hypermedia.
9.3Implementing JAX-RS with Groovy
Groovy doesn’t change JAX-RS in any fundamental way, though as usual it simplifies the implementation classes. JAX-RS is already simplifying the implementation by providing its own kind of DSL, so the Groovy modifications are minimal.
The previous section used Groovy implementations but didn’t present them. Here I’ll show just enough to illustrate the Groovy features.
To begin, here’s the Person POGO. Note the @XmlRootElement annotation, used to control the serialization of the Person for the response. Normally that’s used for Java API for XML Binding (JAXB), but the presence of the Jackson JSON parser causes the serialization process to produce JSON objects instead:
@XmlRootElement
@EqualsAndHashCode class Person {
Long id String first String last
String toString() { "$first $last" }
}
www.it-ebooks.info

240 |
CHAPTER 9 RESTful web services |
Getters, setters, and constructors are all generated in the normal manner. The @EqualsAndHashCode AST transformation takes care of equals and hashCode method implementations. The @ToString annotation could also have been used, but the desired toString method is barely longer than that, so I just wrote it out.
Speaking of AST transformations, the @Singleton annotation is applied to the JdbcPersonDAO class when implemented in Groovy. That automatically implements and enforces the singleton property on the class by making the constructor private, adding a static instance variable, and so on. That class implements the same interface as before. Here’s the beginning of the class:
@Singleton
class JdbcPersonDAO implements PersonDAO { static Sql sql = Sql.newInstance(
url:'jdbc:h2:db', driver:'org.h2.Driver')
static {
sql.execute 'drop table if exists people'
...
}
...
}
GROOVY AND JAVA INTERFACES Java tools prefer Java interfaces. Most Java/ Groovy integration problems vanish if you use Java interfaces with Groovy implementations.
There’s one slight syntax variation required by the switch from Java to Groovy. The @Produces and @Consumes annotations take a list of media types that they support. In the Java implementation this is expressed as an array, using the braces notation:
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
In Groovy, braces indicate closures. Square brackets delimit a list, however, so the Groovy implementation just replaces the braces with brackets.
BRACES VS. BRACKETS Groovy uses curly braces for closures, so the literal notation to define a Java array should use square brackets for a java.util
.ArrayList instead.
The complete PersonResource implementation in Groovy is shown in the next listing.
Listing 9.6 A Groovy implementation of the PersonResource class
@Path('/people')
class PersonResource { @Context
private UriInfo uriInfo
PersonDAO dao = JdbcPersonDAO.instance
@GET
@Produces([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML])
www.it-ebooks.info

Implementing JAX-RS with Groovy |
241 |
List<Person> findAll() { dao.findAll();
}
@GET @Path("lastname/{like}") @Produces([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML]) List<Person> findByName(@PathParam("like") String like) {
dao.findByLastName(like);
}
@GET @Path("{id}")
@Produces([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML]) Response findById(@PathParam("id") long id) {
Response.ok(dao.findById(id))
.build()
}
@POST
@Consumes([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML]) @Produces([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML]) Response create(Person person) {
dao.create(person); UriBuilder builder =
UriBuilder.fromUri(uriInfo.requestUri).path("{id}") Response.created(builder.build(person.id))
.entity(person)
.build()
}
@PUT @Path("{id}")
@Consumes([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML]) @Produces([MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML]) Person update(Person person) {
dao.update(person) person
}
@DELETE @Path("{id}")
Response remove(@PathParam("id") long id) { dao.delete(id); Response.noContent().build()
}
}
Most discussions of JAX-RS end at this point, with a working, URL-driven database. True REST is more flexible than that, however. A RESTful service is supposed to act like the web, in that it presents a single URL to the client, which accesses it and receives additional links in return. This is known as HATEOAS, or simply hypermedia.
Lessons learned (JAX-RS with Groovy)
1Groovy doesn’t significantly change JAX-RS.
2The real Groovy simplifications are in the POGO and DAO classes. The resource implementation is essentially the same in both languages.
www.it-ebooks.info
242 |
CHAPTER 9 RESTful web services |
Hypermedia links are exposed to clients, which consume them. JAX-RS 1.x doesn’t include a client-side API. Version 2.0 does, and there’s a convenient project in the Groovy ecosystem known as HttpBuilder for performing HTTP requests. Both are the subjects of the next section.
9.4RESTful Clients
Accessing a RESTful web service involves creating an HTTP request of the proper type and adding any necessary information to the body. One of the biggest changes in JAX-RS when moving from version 1 to version 2 is the addition of a standard client API. The API includes Client and WebTarget classes, which are used as follows:
Client cl = ClientBuilder.newClient()
WebTarget target = cl.target('http://localhost:1234/people/3') def resp = target.request().get(Response.class)
A Client instance is created from a ClientBuilder, which in turn leads to a WebTarget. A GET request uses the get method, whose argument is the data type of the returned object. This example is taken from a hypermedia test, shown in the next section.
In Groovy, the Groovy JDK makes GET requests trivial. Groovy adds the toURL method to java.lang.String, which converts a String into an instance of java.net.URL. The Groovy JDK also adds the getText method to java.net.URL. Pulling information from the web can therefore be as simple as
String response = 'http://localhost:1234/people/3'.toURL().text
Making POST, PUT, and DELETE requests is done in Groovy the same way it’s done in Java, which isn’t fun. Instead, client access is best done through a library.
One of the most popular HTTP libraries is the open source Apache HTTP Client library (http://hc.apache.org/httpcomponents-client-ga/index.html), which is part of the Apache HttpComponents project.
Rather than show the details of that library I’d rather focus on the corresponding Groovy project, HttpBuilder. The HttpBuilder project (http://groovy.codehaus.org/ modules/http-builder/) follows the classic Groovy idiom: wrap a Java library and make it easier to use. While the documentation on the website isn’t bad, I recommend looking at the test cases in the source code for guidance on how to use the API.
Like most cool projects, the source code is hosted at GitHub at https:// github.com/jgritman/httpbuilder. The API includes a convenient class for REST applications called RESTClient, which I used in the tests in this chapter. The corresponding test class, RESTClientTests, shows how to access Twitter using all the standard HTTP verbs.
I used the RESTClient class in the PersonResourceSpec tests. The RESTClient class has a constructor that takes two arguments, the base URL and a content type:
RESTClient client = new RESTClient( 'http://localhost:1234/', ContentType.JSON)
www.it-ebooks.info