
- •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
JSON support |
323 |
This is the same as the DTD, except that it says that price elements have two decimal places, and isbn attributes are composed of either 10 or 13 decimal digits. Tying the XML document to this schema can be done by modifying the root element as follows:
<library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.kousenit.com/books" xsi:schemaLocation="
http://www.kousenit.com/books books.xsd">
The rest of the library is the same as before. Here’s the code used to validate the XML document against the schema:
String file = "books.xml" String xsd = "books.xsd"
SchemaFactory factory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI)
Schema schema = factory.newSchema(new File(xsd)) Validator validator = schema.newValidator()
validator.validate(new StreamSource(new FileReader(file)))
This looks relatively simple, but here’s the interesting part: the mechanism used is Java. If I was to write this code in Java, it would look almost identical. Unlike the XmlSlurper used for DTD validation, Groovy doesn’t add anything special to do schema validation. So you fall back on the Java approach and write it in Groovy. Because Groovy didn’t add anything, these lines could be written in either language, depending on your needs. Still, Groovy normally does help, as most of the code in this appendix shows.
Whenever the issue of XML comes up these days, someone always asks about JSON support. I’ll address that issue in the next section.
B.9 JSON support
The trend in the industry has been away from XML and toward JavaScript Object Notation, known as JSON. If your client is written in JavaScript, JSON is a natural, because JSON objects are native to the language. Java doesn’t include a JSON parser, but several good libraries are available.
As of Groovy 1.8, Groovy includes a groovy.json package, which includes a JSON slurper and a JSON builder.
B.9.1 Slurping JSON
The groovy.json package includes a class called JsonSlurper. This class is not quite as versatile as the XmlSlurper class because it has fewer methods. It contains a parse method that takes a Reader as an argument, as well as a parseText method that takes
a String.
www.it-ebooks.info
324 |
APPENDIX B Groovy by feature |
A JSON object looks like a map inside curly braces. Parsing it results in a map in Groovy:
import groovy.json.JsonSlurper;
def slurper = new JsonSlurper()
def result = slurper.parseText('{"first":"Herman","last":"Munster"}') assert result.first == 'Herman'
assert result.last == 'Munster'
Instantiate the slurper and call its parseText method, and the result is a map that can be accessed in the usual way, as shown. Lists work as well:
result = slurper.parseText( '{"first":"Herman","last":"Munster","kids":["Eddie","Marilyn"]}')
assert result.kids == ['Eddie','Marilyn']
The two children wind up in an instance of ArrayList. You can also add numbers and even contained objects:
result = slurper.parseText( '{"first":"Herman","last":"Munster","address":{"street":"1313 Mockingbird
Lane","city":"New York","state":"NY"},"wife":"Lily", "age":34,"kids":["Eddie","Marilyn"]}')
result.with {
assert wife == 'Lily' assert age == 34
assert address.street == '1313 Mockingbird Lane' assert address.city == 'New York'
assert address.state == 'NY'
}
The age becomes an integer. The address object is also parsed into a map, whose properties are also available in the standard way. Here, by the way, I used the with method, which prepends whatever value it’s invoked on to the contained expressions. wife is short for result.wife, and so on.
If parsing is easy, building is also a simple operation, much like using MarkupBuilder.
B.9.2 Building JSON
I discussed builders earlier, and I use them throughout the book. In various chapters I use MarkupBuilder (shown in this chapter), SwingBuilder, and AntBuilder. Here I’ll illustrate the builder for generating JSON, called JsonBuilder.
The JsonBuilder class can be used with lists, maps, or methods. For example, here’s a trivial list:
import groovy.json.JsonBuilder;
def builder = new JsonBuilder() def result = builder 1,2,3 assert result == [1, 2, 3]
www.it-ebooks.info
JSON support |
325 |
This builder takes a list of numbers as an argument and builds a JSON object containing them. Here’s an example of using a map:
result = builder { first 'Fred'
last 'Flintstone'
}
assert builder.toString() == '{"first":"Fred","last":"Flintstone"}'
The result is a standard JSON object (contained in braces), whose properties are the strings provided in the builder.
In the builder syntax you can use parentheses to build a contained object, so let’s continue on with the example:
result = builder.people { person {
first 'Herman' last 'Munster'
address(street:'1313 Mockingbird Lane', city:'New York',state:'NY')
wife 'Lily' age 34
kids 'Eddie','Marilyn'
}
}
assert builder.toString() == '{"people":{"person":{"first":"Herman","last":"Munster",' + '"address":{"street":"1313 Mockingbird Lane",' + '"city":"New York","state":"NY"},"wife":"Lily","age":34,' + "kids":["Eddie","Marilyn"]}}}'
The generated JSON can get difficult to read, so the class adds a toPrettyString() method:
println builder.toPrettyString()
This results in nicely formatted output, as shown:
{
"people": { "person": {
"first": "Herman", "last": "Munster", "address": {
"street": "1313 Mockingbird Lane", "city": "New York",
"state": "NY"
},
"wife": "Lily", "age": 34, "kids": [
"Eddie",
www.it-ebooks.info
326 |
APPENDIX B Groovy by feature |
"Marilyn"
]
}
}
}
JSON data is therefore almost as easy to manage as XML, both when creating it and when managing it.
www.it-ebooks.info