Chapter 2. The Groovy essentials


This chapter covers

  • Introducing Groovy
  • Differences between Java and Groovy
  • Groovy’s dynamic features

Grails is a great framework that removes much of the drudgery from the development of web applications. You have already seen how easy it is to get a usable application up and running from scratch. A large part of that productivity gain comes from using Groovy as the main language for Grails development.

This chapter aims to be a primer for Java developers, covering basics that will be useful for following the rest of the book. The pace is fast, but you don’t have to understand everything in one go. In fact, we encourage you to refer back to this chapter as your experience grows and you need to dig a bit deeper into Groovy. If you’re already familiar with the language, you may still want to browse through the chapter—we talk about some subtleties and pitfalls that you may not be aware of.

We begin by covering the many small differences between Groovy and Java, most of which amount to simple variations in the syntax. We then highlight the Java features that are missing from Groovy (there are only a few), before moving on to closures and the dynamic nature of the language. Even after a quick read through, you’ll know enough to follow the examples in the book and write your own code. Beyond that, there is enough information in this chapter for you to become a competent Groovy (and Grails!) developer.

2.1. An introduction

We could go straight into explaining how Groovy and Java differ, but there is nothing like getting your hands dirty to get a real feel for a language. With that in mind, we’ll introduce you to a couple of Grails commands that allow you to experiment with Groovy easily and safely. We’ll follow that up by explaining a few minor but nonetheless important differences between the two languages that will enable you to follow the rest of the examples in the chapter.

2.1.1. Let’s play with Groovy!

You have Grails installed, and now you want to try out this outrageously named programming language called Groovy with a minimum of fuss. What can you do? Well, you saw in the first chapter how you can use the create-app command to create a Grails project. There are also two commands that provide interactive environments for running Groovy code. They can be used to interactively play with your Grails application.


Grails and Groovy versions

This book targets Grails version 1.1, which comes with its own copy of Groovy 1.6, so that’s the version of Groovy that this chapter is based on. Most of the information is also applicable to Groovy 1.5, but some code may not work with that version.


The first command is shell. This starts an interactive shell or command prompt in which you can type Groovy expressions and see the results. Figure 2.1 shows an example session. As you can see, to exit the shell, simply type quit on its own.

Figure 2.1. An example session with the Grails shell, started with the shell command

The shell is great for evaluating expressions and checking the results of method calls, and it’s even powerful enough that you can define new classes from within it. But it isn’t possible to edit code that you have already written, so it’s somewhat limited.

The Grails console, started with the console command, is a Swing application that makes it easy to write simple scripts and run them—it even gives you syntax highlighting! The console consists of two panes: the upper one contains your Groovy code, and the one below shows the output from running the script. The console’s biggest advantage over the shell is that you can change a script and immediately run it with those changes. You can also save the script and load it back in at a later date. Figure 2.2 shows the console application in action.

Figure 2.2. The Grails console in action


Note

You can only start the shell and console commands from within a Grails project. It’s also worth pointing out that the two commands use the standard Groovy shell and console, respectively, which explains the references to “Groovy Shell” and “GroovyConsole” in the interfaces. However, Grails adds some magic that allows you to interact with your Grails project in ways that you can’t with the standard Groovy shell and console.


The script in figure 2.2 highlights a few of the differences between Groovy and Java that we’re about to cover, but first we should explain what scripts are.

What’s This Script Business, Then?

In order to run Java code directly, you must create a class and define a static main() method. This doesn’t sound particularly onerous, but it’s a surprisingly effective disincentive to writing simple applications. To remove this hurdle, Groovy supports scripts: collections of statements in text files that are executed in order. You can think of them as the body of a main() method, but without the class and method definitions. As you can see in figure 2.2, you can even include class definitions.

Try this simple script in the Grails console:

println "Hello world!"

Either use the Script > Run menu item or the Ctrl-R keyboard shortcut to execute the script. And that’s it! You have now written and executed a simple Groovy script.

Now that you know how to use the console, you’re ready to test the examples as we go. Let’s take a look at some of the basic language features that you need to be aware of.

2.1.2. Some basic differences from Java

With a few exceptions, valid Java code is also valid Groovy. But writing idiomatic Groovy means taking advantage of some of its extra features. We start with some familiar Java concepts that vary slightly in Groovy.

Fewer Imports

As you know, all classes in the java.lang package are automatically imported by Java. Groovy extends this behavior to include the following packages:

  • java.io
  • java.math
  • java.net
  • java.util
  • groovy.lang
  • groovy.util

This is convenient when writing scripts because you often end up using classes from these core packages extensively, and it gets pretty tedious running a script only to find that you missed one of those imports.

Assertions

Many of the examples in this chapter make use of the assert keyword:

assert 1 == 1
assert 'c' != 'z'

All assert does is throw a java.lang.AssertionError if the corresponding expression evaluates to false (according to Groovy Truth, which we look at next). You should be familiar with assert from Java, but be aware that although it has similar semantics to the Java version, it can’t be switched on and off via the -ea argument to the JVM.

The Truth ...

You might expect “Groovy Truth” to hold the answer to life, the universe, and everything. Sadly, you’ll have to find that elsewhere. Its actual meaning is far more prosaic and relates to what Groovy views as true or false.

In Java, conditions only work with Boolean values, which often makes for verbose code:

if (mySet == null || mySet.isEmpty()) {
...
}

Groovy helps to reduce this verbosity and improve readability by coercing other objects to Booleans. For example, a null reference and an empty collection will both evaluate to false, so the equivalent Groovy code would look like this:

if (!mySet) {
...
}

Table 2.1 lists the coercions used by Groovy Truth. Note that the null object reference coercion applies to all the object types listed, so both a null map and an empty map will evaluate to false.

Table 2.1. Groovy Truth evaluations

Type

Evaluates to false

Boolean

false, Boolean.FALSE

Object reference

null

Number

0

String, GString

Zero-length string

Collection

Empty Collection

Map

Empty Map

Iterator

hasNext() returns false

Enumeration

hasMoreElements() returns false

java.util.regex.Matcher

find() returns false

Be careful when using Groovy Truth—are you checking the behavior you really want? Ask yourself whether you should be checking for null or for some other value instead. For example, if you know you’re testing a collection and you want to treat a null reference the same as an empty collection, using Groovy Truth is appropriate. However, if you want to treat an empty collection and null differently, make the check explicit, with code like obj == null. This makes the intent clear to anyone reading your code.

Public is the Default Scope

As you know, Java has four scopes: private, protected, public, and the default (package) scope. The designers of Groovy decided that the last of these is redundant, so it only supports the other three. This, in turn, led to the decision to make public the default scope, because it’s the most commonly used. If a class, field, or method has no explicit scope declared, it’s automatically public rather than Java’s default package scope.

Checked Exceptions Don’t Have to be Caught

Error-handling is nearly the same in Groovy as it is in Java. Syntactically, exceptions are treated identically using try...catch...finally blocks. The difference is that you don’t have to catch checked exceptions in Groovy. This means that checked exceptions are, for all intents and purposes, the same as runtime exceptions.

On the whole, this results in less boilerplate code, because you only catch the exceptions you know what to do with. But there are occasions when it’s important not to forget that you’re dealing with checked exceptions. For example, Spring’s default transaction behavior only works with runtime exceptions (as you’ll see in chapter 14). If that doesn’t mean anything to you at the moment, don’t worry—just remember that checked exceptions are still checked exceptions, even if you don’t have to catch them!

That wasn’t so bad, was it? We now have the foundations to move on to the more substantial differences, all of which are geared toward making your life easier.

2.1.3. Some new operators

You’re undoubtedly familiar with operators such as these: + - . and so on. Groovy supports all of the same operators as Java, but it also introduces a few new ones that will make your life easier and your code easier to read.

?. (Null-Safe Object Navigation)

Have you ever been annoyed at having to check whether a reference is null before calling a method on it? The Groovy developers have, so they added a null-safe dot (.) operator to the language.

Consider this common idiom from Java, which checks whether an object or one of its properties is null:

if (obj != null && obj.value != null) {
...
}

In Groovy, you can write this as

if (obj?.value != null) {
...
}

In this example, the field value is only accessed if obj isn’t null. Otherwise the entire expression, obj?.value, evaluates to null—no more NullPointerException! You can chain the operator too, and in fact you should. Otherwise, you’ll see that dreaded exception. So do this:

user.company?.address?.state?.name

rather than this:

user.company?.address.state.name

Once you use ?. in a chain, you should use it in the rest of the chain too.

?: (Elvis!)

Both Java and Groovy have what is known as the ternary operator, which is a concise form of the if...then...else structure:

<condition> ? <expr1> : <expr2>

So, if the condition is true, expr1 is evaluated; otherwise you get expr2.

Here is an example of a common idiom using this operator:

String name = (person.getName() != null) ? person.getName() : "<unknown>"

In words, if the person’s name is set, we use that. Otherwise we use a default value.

This is so commonly used (and verbose) that Groovy introduces a shorthand form:

String name = person.getName() ?: "<unknown>"

This is the Elvis operator, and it returns the value of the left expression if it evaluates to true (according to Groovy Truth), but the value of the right expression otherwise.

Why “Elvis”? Rotate the operator 90° clockwise and you’ll see!

*. (The Spread-Dot Operator)

No operator is better disguised by its name than “spread-dot.” What does it do? Surprisingly, something useful: it calls a method on every item in a collection, and it creates a new list containing the results of those methods.

For example, imagine you have a list of objects that all have a getName() method; the following code will create a new list containing the names of the original items:

List names = people*.getName()

The resulting list has the same order as the original, so in the preceding example the names will be in the same order as the people. The operator can also be used on other types of collections, but the result is always a list and its items are always in the iteration order of the original collection.

We could also use property notation, which is described in a later section:

List names = people*.name

This is probably the most common use of the operator you’ll see in both examples and real code.

<=> (Comparisons with a Spaceship)

Java has plenty of operators for comparing two values, so why should we want another one? If you have ever implemented the Comparable.compareTo() or Comparator. compare() methods, you’ll know why.

Here is a naive implementation of a comparator for integers:

public int compare(int i1, int i2) {
if (i1 == i2) return 0;
else if (i1 < i2) return -1;
else return 1;
}

You can reduce this to a one-liner for numbers, but it’s not so easy for other types. So what would the method look like if we had an operator with identical behavior to the compare() method? Let’s see:

public int compare(int i1, int i2) {
return i1 <=> i2;
}

That’s the Groovy “spaceship” operator, which can be used on any types that implement Comparable. It’s particularly useful for custom comparators and, in combination with some other features of Groovy that we’ll see later, for sorting lists. It returns a negative number if the left side is less than the right side, zero if the operands are equal, and a positive number otherwise. There are no guarantees as to the absolute value of nonzero results—only the sign is significant.

== (Equals())

When you use == in Groovy, the generated code uses the equals() method. It’s also null-safe, which means that it will work if either or both of the operands are null.

The following example demonstrates the behavior using assertions and strings:

String str = null
assert str == null
assert str != "test"

str = "test"
assert str != null
assert str == "test"

str += " string"
assert str == "test string"

This example doesn’t tell the whole story, and there is an exception to this rule: if the object on the left side implements java.lang.Comparable, then == uses the compareTo() method rather than equals(). In this case, the result is true if the compareTo() method returns 0, or false otherwise.

In case you’re wondering why Groovy does this, remember that 0.3 and 0.30 are not equivalent according to the BigDecimal.equals() method, whereas they are with the compareTo() method. Again, the principle of least surprise suggests that the expression 0.3 == 0.30 should evaluate to true, which is exactly what happens in Groovy.

Lastly, how do you get the Java behavior for ==? Use the is() method:

BigDecimal x = 0.234
BigDecimal y = x

assert y.is(x)
assert !y.is(0.234)
assert y == 0.234

As you can see, it will only return true if two objects are the same instance.

Although these operators may be unfamiliar now, it won’t be long before you’re confidently using them in your own code. So with that gentle introduction out of the way, it’s time to look at the Groovy type system.

2.2. Exploring types

As with most things in Groovy, if you start from the assumption that its type system is the same as Java’s, you won’t go far wrong. Nonetheless, there are some key differences between the two languages when it comes to types and their handling, which you need to know to unlock the full potential of the language.

2.2.1. Looking at basic types

All the types you expect from Java are there in both primitive and object form: boolean, int, double, String, and so on. This makes both the transition to the language and integration with Java relatively easy. But the type systems aren’t identical. Take primitive types: even if you declare a variable as a primitive, you can still treat it as an object by calling methods on it. This is most obvious in the handling of numbers.

Numbers

Not only can primitive variables be treated as objects, but this behavior also extends to numeric literals. So 1 is an instance of Integer and 546L is an instance of Long. Here is how you can call a method on an integer literal:

assert (-12345).abs() == 12345

A subtle but notable feature in Groovy is that floating-point arithmetic is based on BigDecimal rather than double or float. At first this may seem strange, but Groovy aims for the principle of least surprise, and one of the most surprising things in Java is that 0.1D * 3 is 0.300...04 rather than 0.3 exactly. Because Groovy isn’t targeted at high-performance floating-point calculations, it prefers to use BigDecimal so that 0.1 * 3 is 0.3.

You may be worried about having to use the BigDecimal API, but fear not! Groovy helpfully makes the normal arithmetic operators work transparently with the class. Here’s a quick example:

assert 0.25 instanceof BigDecimal
assert 0.1 * 3 == 0.3
assert 1.1 + 0.1 == 1.2
assert 1 / 0.25 == 4

Anyone who has tried to perform BigDecimal division in Java will truly appreciate the simplicity in Groovy.

Groovy Strings

You have seen that Java string literals also work in Groovy, but there are some significant differences.

To begin with, Groovy has no character literal like Java. Single quotes ('') delimit string, not character, literals. So what is the difference between single quotes and double quotes? The latter allow you to embed Groovy expressions in the string. This means that rather than manually concatenating strings as in Java, you can use code like this:

String name = "Ben"
String greeting = "Good morning, ${name}"
assert greeting == 'Good morning, Ben'

String output = "The result of 2 + 2 is: ${2 + 2}"
assert output == "The result of 2 + 2 is: 4"

Anything inside the ${} will be evaluated, converted to a string via the toString() method, and inserted into that position. If your string contains dollar symbols, you can either use the single-quote form or escape them using a backslash ("$"). This type of string is known as a GString.

Both forms of string literal have corresponding multiline versions. These allow you to easily create string literals that include line breaks. If you have ever tried to build these strings in Java, you’ll understand how big a deal this is. Take, for example, a simple method that returns the body of an email given a person’s name. In Groovy, the code would be as follows:

String getEmailBody(String name) {
return """Dear ${name},

Thank you for your recent inquiry. One of our team members
will process it shortly and get back to you. Some time in
the next decade. Probably.

Warmest and best regards,

Customer Services
"""
}

See how we have embedded the name variable inside the string? Simple and elegant. One word of warning, though: any whitespace that appears between the triple quotes will be included in the string. Make sure that each line starts in column one of the file unless you want the text indented in the resulting string.

You can also use the slash (/) character to delimit string literals, although this approach doesn’t have a multiline version. You may find this option a bit strange, but you’ll see later that it comes into its own with regular expressions.

That’s it for string literals, but you must be asking yourself how you can declare a char literal. There are two options: either assign a single-character string to a char variable, or use the as keyword. Here are examples of both:

char ch = 'D'
assert ch instanceof Character

String str = "Good morning Ben"
str = str.replace(' ' as char, '+' as char)
assert str == "Good+morning+Ben"

Although we use single quotes for our character literals in the preceding example, you can use double quotes. It comes down to user preference, but there is an advantage to our method—the preceding example is almost valid Java. Remove the two as char elements and you have pure Java code! The other advantage of using single quotes for character literals and double quotes for string literals is that plain Java developers will be more comfortable with the code—a benefit not to be sneezed at.

Speaking of Java developers, that as keyword will be new to them. What does it do?

Your Flexible Friend: As

In Java, you can cast an object to a type as long as the object is actually an instance of that type. Groovy supports the Java cast, but as you’ll find out, it’s redundant in a dynamically typed language. Something that would be useful is a means of easily converting between types.

Imagine you have the string "12345". It looks like a number, but as far as Java and Groovy are concerned, it’s a string. To convert it to a number in Java, you have to use Integer.parseInt() or a similar method. That’s all well and good, but what if you want to convert an array to a list? For that you can use Arrays.asList(). You can similarly perform other conversions in Java, but you have to find the appropriate method—something that’s not always trivial.

Like a knight in shining armor, Groovy comes to the rescue with its as operator. This allows you to perform conversions like string to number or array to list using a consistent syntax. As an added bonus, your code will tend to be easier to read because as is implemented as an operator. Here are some examples of its syntax:

assert 543667 as String == "543667"

assert 1234.compareTo("34749397" as int) < 0

Groovy supports several conversions by default, a subset of which are listed in table 2.2. You may not understand all of them at this stage, but we’ll come across many of them later in the book.

Table 2.2. Conversions supported by as

Source type

Target type

Description

String

Number (int, double, Long, BigDecimal, and so on)

Parses a string as if it were a number

List

Array

Converts a list to an array; for example, myList as String[] (Groovy doesn’t support Java’s array literals)

List or array

Set

Converts a List or array to a Set

Anything

boolean

Uses Groovy Truth to convert a value to either true or false

Collection

List

Creates a list that’s a copy of the original collection; the items in the list are in the iteration order of the original collection

String

List

Treats a string as a sequence of characters and turns it into a list

You can also add custom conversions to a class by implementing the asType(Class) method. This is how Grails adds its own conversions, such as those involving the XML and JSON converters described in chapter 11 on REST.

That’s pretty much it, as far as the basic types go. Hopefully you’ll find GStrings and type coercion as useful as we do. Certainly they’re more elegant alternatives to string concatenation and casting. Yet these improvements are minor compared to Groovy’s collection and map support.

2.2.2. Syntax sugar for lists, maps, and ranges

Lists, maps, and ranges are so common that some other languages have them built into their type systems. Yet Java only has limited support for them—it’s almost as if they were tacked on as an afterthought. Groovy goes some way toward rectifying this situation by effectively treating them as first class citizens at the language level.

List and Map Literals

If you have ever tried to build up a list or map of reference data in Java, you know how painful the experience is. You first have to create an instance of the collection, and then add each item explicitly. Groovy makes life much easier in this respect, with its list and map literals. A list literal is a comma-separated sequence of items between square brackets, and a map literal is the same, but each “item” is a key and value separated by a colon. Listing 2.1 compares the Groovy and Java syntaxes for creating lists and maps, while at the same time showing the list and map literals in action.

Listing 2.1. Initializing lists and maps in Groovy

These literals are instances of java.util.List and java.util.Map, so they have all the methods and properties you would expect. For example,

assert 3 == [ 5, 6, 7 ].size()

uses List’s standard size() method to determine the number of elements in the list literal.

Array-Style Notation for Lists and Maps

Java has a rather clunky syntax for accessing items in lists and maps because it relies on methods. Groovy improves the situation dramatically by extending Java’s array notation to both lists and maps. This is best understood by example—listing 2.2 demonstrates getting and setting values with both types.

Listing 2.2. Accessing list and map elements

As you can see, Groovy makes using lists and maps pleasant and intuitive. Worthy of particular note is the ability to index lists (and arrays!) from the end rather than the beginning, as demonstrated by (a value of -1 refers to the last item). Listing 2.2 also shows the left-shift operator in action . This is the standard way of appending items to a list in Groovy (or anything else that implements Collection).

A New Type: Range

Somewhat related to lists is Groovy’s range type. In fact, all range objects implement the java.util.List interface. A full account of the capabilities of this type is outside the scope of this book, but you’ll need to recognize integer range literals and understand some of their uses. You can find out more on the Groovy website: http://groovy.codehaus.org/Collections.

In essence, a range is the combination of a lower and an upper bound, which in the case of an integer range represents all numbers between the two bounds. The lower bound is always inclusive, but you can specify ranges with either an inclusive or exclusive upper bound.

Listing 2.3 shows code that iterates over a list of strings, printing each item in the list to the console, and then printing a subset of the items.

Listing 2.3. Ranges

The listing demonstrates the two most common uses for ranges: as something to iterate over , and as an argument to the array accessor .

You may not be familiar with the for loop shown at , but don’t worry. The code is simply iterating over the integers from 0 to 4 inclusive (there are 5 items in the list), and assigning the current integer to the variable i. In this case, the exclusive upper bound notation is being used: lower..<upper. Also note that you can use variables and expressions as range bounds.

shows how you can get a slice of a list, or in Java terms a sublist. Here we used the inclusive upper bound notation to extract items 2 through 4 from the list of fruit. Note that any changes to the original list will be reflected in the slice. If you were to change the third fruit from “lemon” to “lime”, the second item of the slice would also be “lime”.

If all that hasn’t got you excited, then either you’re coming from a language that already has rich support for collections and maps, or nothing will! Those of you coming from Java will wonder how you managed without these features.

And so we end our coverage of the type system. Next we’ll look at some features that are difficult to pigeonhole.

2.3. Time-saving features

Before we move on to the most significant features of Groovy, let’s take a look at some of the quiet helpers. We start with the seemingly innocuous semicolons at the end of statements.

2.3.1. Who needs semicolons?

One of the most obvious differences between Java and Groovy is that the latter doesn’t require semicolons at the end of lines, or, to put it more accurately, at the end of statements. If you want to put more than one statement on a single line in Groovy, you must still separate them with semicolons, as in Java.

This flexibility comes at a cost. You must be careful how you break statements across multiple lines, because some code arrangements will cause compiler errors. Listing 2.4 shows some examples of invalid and valid line breaks.

Listing 2.4. Valid and invalid line breaks

You can get around these limitations by using a line continuation that effectively says “this line hasn’t ended yet.” You may be tempted to insert semicolons to achieve the same result, but that won’t work. For multiline statements, Groovy parses the end of lines before it ever sees the relevant statement terminator, so it will still throw an error.

At this stage, you’re probably wondering about the underlying rules that determine whether a given format is valid. If a single line is a valid statement, then Groovy treats it as such, and the next line should be the start of a new statement. Otherwise Groovy combines the first line with the following one and treats them as a single statement. In general, if you run into a compilation error because of this problem, use a line continuation.

And Who Needs Parentheses?

You’ll soon notice that method calls don’t seem to need parentheses. The classic example is the println() method provided by the Groovy JDK (which we’ll get to in section 2.4.3):

println "Hello, world!"

Method calls that take a closure as a single argument (see section 2.4.1) also usually lack parentheses due to the improved readability. However, you must use parentheses for zero-argument method calls or if the first argument is a list or map literal:

println()
println([1, 2, 3, 4])

There are probably other instances where parentheses are required by Groovy, so we recommend that you use them in most cases, leaving them out only in a small set of common cases (such as println() and with closures). Doing this also makes your code easier for Java developers to read.

You Don’t Need Return Statements Either?

It may seem strange, but the return statement is unnecessary in Groovy. If no return is present, a nonvoid method will return the result of the last expression evaluated.

For example, the following method returns the result of value + 1:

int addOne(int value) { value + 1 }

You may be wondering why this feature exists. Simple: conciseness. It’s particularly useful when inlining closures, which you’ll see later in section 2.4.1. But this doesn’t prevent you from using return if you wish, and sometimes including it is more readable for Java-attuned eyes.

Optional elements like these need to be discussed, but they’re hardly satisfying. You need something to really sink your teeth into, and we have just the thing.

2.3.2. Native regular expressions

Regular expression support was introduced into the core Java API with version 1.4. Groovy builds on this and provides support for regular expressions at the language level. It provides new literals, new operators for regular expression matching, and a nice syntax for extracting groups, all of which make working with regular expressions a more productive experience.

Literals

Let’s start with the new form of string literal that uses slashes (/). Why do we need or even want another type of string literal?

Regular expressions use the backslash () as an escape character; for example,  represents a word boundary. Unfortunately, Java’s string literals also use the backslash as an escape character, so regular expressions in Java can quickly enter backslash hell. As an example, take this regular expression that matches a backslash followed by any word character: "\\\w".

The slash-based strings introduced by Groovy are a solution to this problem. They don’t use the backslash as an escape character (except when you need a literal slash), making regular expressions much easier to write. With / as a delimiter, the previous expression becomes /\w/. We have halved the number of backslashes!

You should also be aware that these string literals are GStrings, so you can embed Groovy expressions. For example, /${name}: w+/.

If you prefer to deal explicitly with java.util.regex.Pattern instances, you can create them by prefixing any string literal with a ~:

assert ~"London" instanceof java.util.regex.Pattern
assert ~/w+/ instanceof java.util.regex.Pattern

This technique is useful if you want to reuse a pattern, but it’s not common.

Matching

Literal patterns aren’t the only language-level support Groovy provides for regular expressions. It also introduces two new operators for matching that should be familiar to Perl and Ruby developers.

The first of these is =~, which matches if the pattern on the right side can be found in the string on the left side. For example,

assert "Speaking plain English" =~ /plain/

will pass because the string we’re testing contains “plain”. On the other hand, we get different behavior with the ==~ operator:

assert !("Speaking plain English" ==~ /plain/)

This is because the test string doesn’t match the pattern exactly—only part of the test string matches, not the whole of it. Adding a couple of wildcards to the pattern results in an exact match:

assert "Speaking plain English" ==~ /.*plain.*/

Behind the scenes, there is a more fundamental difference between the two operators. The =~ operator returns an instance of java.util.regex.Matcher, whereas ==~ returns a Boolean.

So why can we use =~ directly in an assertion? Because Groovy automatically coerces Matcher to a Boolean when required. Under the hood, Groovy calls find() on the matcher and returns the result.

Groups

Some regular expressions include capturing groups and you can access them via array notation.

The example in listing 2.5 extracts all words that contain “ain”, printing out the prefix and suffix of each match. When run, you’ll see this printed to the console:

Found: 'rain' - prefix: 'r', suffix: ''
Found: 'Spain' - prefix: 'Sp', suffix: ''
Found: 'mainly' - prefix: 'm', suffix: 'ly'
Found: 'plain' - prefix: 'pl', suffix: ''
Listing 2.5. Regular expression capture groups

You can see how the slash-literals, match operator, and groups come together to make using regular expressions far more concise than in Java. The only tricky part is understanding the array notation .

In listing 2.5, the test string has four bits that match the pattern: “rain”, “Spain”, “mainly”, and “plain”. The first array index allows us to pick one of these, so an index value of 1 refers to the match “Spain”. The second index allows us to access specific groups within that match. An index value of 0 refers to the whole of the match (for example, “Spain”), but index values of 1 and upwards refer to the groups. So in our example, a second index value of 1 gets us the prefix, whereas 2 refers to the suffix .

That’s it for the regular expression support. We recommend that you take full advantage of it in your own code if you can, but remember that you can always fall back to using the Java classes and methods if you aren’t comfortable with the Groovy feature.

We only have one more minor feature left to discuss, but it’s an important one because almost all Groovy code uses it. OK, maybe that’s an exaggeration, but not much of one.

2.3.3. Property notation

The JavaBeans specification introduced the concept of an object property but left us with an unwieldy syntax: getter and setter methods. Groovy rectifies this problem by letting us use field access notation for JavaBeans properties.

Take the java.util.Date class. It has the methods long getTime() and void setTime(long milliseconds), which conform to the JavaBeans specification and represent a long property named time. In Groovy you can access this property as if it were a field:

Date now = new Date()
println "Current time in milliseconds: ${ now.time }"

now.time = 103467843L
assert now.time == 103467843L

Once you start using this syntax, you won’t look back. It’s far more natural than calling the methods, requires less typing, and is more readable. What more can we say?

Using properties is all well and good, but you still have to define those getter and setter methods, don’t you?

Defining Properties

Writing getter and setter methods is so laborious that IDEs will autogenerate the code for you. Even so, your class still ends up polluted with boilerplate methods that don’t contain any real logic. Thankfully, Groovy provides a shortcut.

If you declare a field without any scope, Groovy will automatically make the field private and generate the getter and setter methods behind the scenes. You can even override those methods if you wish. All of the fields in the following example are properties, except for the last one:

class MyProperties {
static String classVar

final String constant = "constant"
String name

public String publicField
private String privateField
}

That’s it—nothing could be easier. Note that for Boolean properties, Groovy will even generate an is...() method. And for non-Java programmers, the final qualifier means that the variable can’t be modified once it has been initialized (which can be done in a constructor or as part of the declaration, as in the example).

All that’s left now is a trick for instantiating and initializing beans.

Instantiating Beans

When you define a bean, it must have a default constructor, and Groovy uses that requirement to provide a shortcut for initializing instances of such classes. All you need is to provide a list of named arguments matching the properties you wish to set.

This example creates a new instance of java.text.SimpleDateFormat using this approach:

DateFormat format = new SimpleDateFormat(
lenient: false,
numberFormat: NumberFormat.getIntegerInstance(),
timeZone: TimeZone.getTimeZone("EST"))

The named arguments look like a map without the square brackets, in which the key is the name of a property on the class. In fact, behind the scenes, Groovy uses an instance of LinkedHashMap. You can even pass your own map instance to the constructor. This is a common idiom when creating domain classes from web request parameters, as you’ll see later in chapter 5.

Speaking of maps, Groovy allows you to get and set map entries using property notation. Here’s an example:

Map values = [ fred: 1, peter: 5, glen: 42 ]
assert values.fred == 1
values.peter = 10
assert values.peter == 10

This syntax is widespread, and it’s particularly useful when combined with duck typing, which you’ll see in the next section. You can effectively treat maps as objects!


Note

Groovy treats map keys as strings unless they are numeric or inside parentheses. In the previous example, fred is the string "fred", not a variable. The quotes are optional unless the key contains a space, a dash, or some other character that is invalid in Groovy identifiers. If fred were a variable and you wished to use its value as the map key, you would put it in parentheses: [ (fred): 1 ].


So, you’ve now heard a lot about what features Groovy provides over and above Java, but what about the other way round?

2.3.4. Anything in Java that’s not in Groovy?

As we have already stated, most Java code is also valid Groovy. A few constructs are missing though, so it’s important to be aware of them.

Character Literals

We showed in the previous section that single quotes are used as string delimiters, so Groovy has no character literal. But you can coerce single character strings to chars using the as keyword.

Java “for” Loop

Groovy has limited support for the standard Java for loop in that you can’t use the comma (,) operator. This works:

for (int i = 0; i < 10; i++) { ... }

But this doesn’t:

for (int i = 0, j = 0; i < 10; i++, j++) { ... }
Do...While

There is no do...while loop, but we doubt that anyone will mourn its passing. We have rarely, if ever, seen it in the wild, and you can always use while and for loops to get the same effect.

Inner and Anonymous Classes

You can’t declare inner or anonymous classes. Support for these is coming, but, on the whole, both closures and the ability to declare more than one class in a Groovy file mean that this is only a real issue with libraries and frameworks that heavily depend on them.

2.4. Expert Groovy

You should now be fairly confident in your ability to understand and write Groovy code. So far, most differences between Groovy and Java have fallen under the heading of “syntactic sugar.” We now move on to two important concepts that separate Groovy from Java on a more fundamental level: closures and Groovy’s dynamic nature.

2.4.1. Discovering closures

You’re probably familiar with the sort() method in java.util.Collections for sorting a list using a given comparator. This simple fragment of Java code will sort a list of strings, ignoring case, and print them to the console:

List<String> fruit = Arrays.asList(
"apple", "Orange", "Avocado",
"pear", "cherry");

Collections.sort(fruit, new Comparator<String>() {
public int compare(String str1, String str2) {
return str1.compareToIgnoreCase(str2);
}
});
System.out.println("Sorted fruit: " + fruit);

The result is this output:

Sorted fruit: apple, Avocado, cherry, Orange, pear

Notice how the comparator is a single method implementation? All we want to do is pass a two-argument function to the sort() method, but this isn’t possible in Java, so you need an interface to host the function and an object to implement it. Fortunately for us, the JDK provides the java.util.Comparator interface and anonymous classes. But what if you wrote an algorithm that traverses a tree and performs a function on each leaf node? You’d have to write an interface to host the function and pass an object that implements that interface to the algorithm.

This seems like more work than it should be, and even anonymous classes leave one aching for a more elegant alternative. As usual, Groovy offers a solution: closures. You can think of these as anonymous functions that can be assigned to variables, passed to methods, or even returned from methods. Or, you can think of them as single-method anonymous classes.

The syntax can be difficult at first, so we’ll introduce it by example. This code does the same thing as the Java code you just saw, but it uses a sort() method that compares items using a closure:

List fruit = [ "apple", "Orange", "Avocado", "pear", "cherry" ]

fruit.sort { String a, String b -> a.compareToIgnoreCase(b) }

println "Sorted fruit: ${fruit}"

You may be wondering where this strange sort() method comes from—don’t worry, Groovy adds it to List implementations via the Groovy JDK, which we introduce shortly, in section 2.4.3.

In this example, we have not only declared a closure but also passed it as an argument to the sort() method. See how the closure looks like a method body without a name? The major difference is that the arguments are declared within the curly braces.

Before we move on, we should point out two things in the preceding example. The first is that the sort() method is called without parentheses. This is common when a method only has a single argument and that argument is a closure. The second point is that the closure uses an implicit return value to help keep the code compact.

The standard syntax for a closure is

{ <arguments> -> <body> }

where <arguments> is the list of typed or untyped parameters to the closure, and <body> is the equivalent of a regular method body. A zero-argument closure can be expressed with no argument declarations before the arrow: {-> ... }. There is also a special case that you need to be aware of, which is demonstrated by this example:

[ "apple", "pear", "cherry" ].each { println it }

When a closure definition has no ->, it’s created with a single implicit argument that you can access via the special variable it. So in the preceding example, each() calls the closure for each item in the list, passing the current item in as an argument. Therefore, it contains the current list item (the name of a fruit), and the code prints out each item in the list to the console.

You have seen closures declared at the point of use—as method arguments—but we also mentioned that you could assign them to variables and pass them around, sort of like a function pointer. Listing 2.6 modifies the previous Groovy sorting example so that you can see how a reference to a closure can be used.

Listing 2.6. Closure assigned to a variable

Passing a closure to a method via a reference looks just like a regular method call . We have also included an example of how you can call a closure directly, as if it were a method . This notation isn’t particularly surprising when you consider that closures are effectively anonymous functions. When you assign a closure to a variable, you bind it to a name, so it effectively becomes a named function.


What’s in a name?

The term closure has a specific meaning in computer science, and there have been various arguments in the past over whether Groovy’s closures should be named as such. The key point is that they aren’t simply blocks of code; they capture references to variables and methods outside of the closure definition. Try this simple example in the console:

def n = 14
def msg = "'n' is ${->n}"
println msg
n = 10
println msg

The second println will display the message with a value of 10 for n, because the closure embedded in the string captures the variable reference, not just its value. Anonymous classes can do something similar, but they can only access variables that are declared final.


We have now covered enough ground that you’ll be able to follow the many examples in this book where closures are used. But to become truly comfortable with them in the context of Grails, you need to know a few more things.

First, single-argument closures are unique: they can be called with or without an argument; for example, myClosure(1) or myClosure(). In the latter case, the closure is passed a value of null.

Second, there is a simple restriction on the special syntax used in the early examples of this section. Take the following example, which sums the items in a list. Don’t worry, you don’t have to understand how it works—we’re only interested in the syntax at the moment.

List list = [ 1, 3, 5, 6 ]
assert 15 == list.inject(0) { runningTotal, value -> runningTotal + value }

The closure is declared after the method’s closing parenthesis, and yet it is passed to the inject() method as the second argument. This is one of those syntactic tricks that Groovy provides to make code easier to read. That method call could equally be written like this,

list.inject(0, { runningTotal, value -> runningTotal + value })

but this form doesn’t work well with larger, multiline closures. So what is the restriction we mentioned? You can only use the former syntax if the closure is the last argument to the method, whereas the latter form will work irrespective of the argument position.

The final point is possibly the most important: closures aren’t methods! The way in which they’re used means that they often look like methods, but they’re still objects, whereas proper methods in Groovy compile to regular Java methods. In many cases, the distinction is unimportant, but you should understand that the standard rules for overriding methods don’t apply. For example, if you’re extending a class like this,

Class SuperClass {
Closure action = {
...
}
}

we recommend that you don’t declare an action property in your subclass. If you want polymorphic behavior, use methods. Inheritance isn’t the only area where using closures can cause problems. You may not be aware of or familiar with aspect-oriented programming (AOP), but it has been growing in popularity in the last few years. Many AOP libraries and tools work with methods, so if you start using closures everywhere, you’ll lose easy AOP integration.

Hopefully you’ll take these as words of caution rather than as a reason never to use closures. They’re powerful and will make it easier to formulate solutions to certain problems. But as with any new toy, there is a danger of using them to the exclusion of other techniques.

2.4.2. Programming dynamically

Dynamic languages sound exciting, don’t they? It’s built into their name: “dynamic.” But what do we mean by that term?

Throughout this chapter, we have assumed that you already know Java. In Java, all variables, properties, method arguments, and method returns must have declared types. This allows the compiler to perform type-checking, eliminating a potential source of bugs before the application is ever run.

Now imagine that we have a Person class with the properties givenName, family-Name, age, and country. In Java, we can easily sort a list of Person objects by one of these properties, like so:

public void sortPeopleByGivenName(List<Person> personList) {
Collections.sort(personList, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return p1.getFamilyName().compareTo(p2.getFamilyName());
}
});
}

But what if you don’t know which property to sort on until runtime? This might happen if a user can select which property to sort by in a user interface. Life suddenly becomes much trickier in Java. You either write a sort method like the preceding one for each of the properties and link them to the user interface somehow, or you use reflection in the comparator. The first option means duplication of the comparator code, which is both tedious and error prone. The second option would involve some pretty nasty code, so we’ll save you the pain of looking at it.

Instead, let’s look at how we would do it in Groovy using untyped variables and dynamic dispatch. As required, this method sorts a list of people by a given property:

def sortPeople(people, property) {
people.sort { p1, p2 -> p1."${property}" <=> p2."${property}" }
}

We’ve thrown you into the deep end with this example, but trust us—you’ll be swimming in no time! Let’s break the example down into bits, starting with the method signature. It looks like any other method signature, apart from the def keyword and the lack of types on the method arguments. The def keyword defines both untyped variables and methods, which means a variable declared using def can be assigned any value. You can even assign it a string on one line and then an integer on the next. When used on methods, it means that the method can return any type of value or be void. Effectively, def is like using java.lang.Object.

Untyped method and closure arguments don’t even need the def keyword. Leave out the type and they will be treated as untyped variables. Although Groovy is almost (if not quite) unique in dynamic languages by supporting declared types, most developers tend to quickly move to using untyped variables, arguments, and methods because the code is more concise and easier on the eye.

In the closure passed to the sort() method, you’ll see some strange notation involving a GString. The first thing to understand is that Groovy will accept strings as property and method names. To see what we mean, here is an example in which the two lines do exactly the same thing:

peopleList.sort()
peopleList."sort"()

The string notation can be particularly useful with Groovy builders, such as the XML markup builder we introduce in section 2.4.4, but in this case it’s the ability to specify a property or method at runtime that’s important. So if the property argument contains the string age, the closure body in our example sortPeople() method becomes

p1."age" <=> p2."age"

so the method sorts on the age property. The exact same code can be used to sort on any of Person’s properties. In fact, you’ll notice that the method has no dependency at all on Person, which means that the method can sort any list of objects so long as they have the given property!

You have just seen how powerful a combination of untyped variables and dynamic dispatch can be. This pattern has a name.

Duck Typing

No discussion of a dynamic language is complete without a mention of duck typing. The term comes from the saying, “if it walks like a duck and talks like a duck, it’s probably a duck.” Applied to dynamic languages, it means that if an object has a particular property or method signature, then it doesn’t matter what type the object is, you can still call that method or access that property.

This is only possible in dynamic languages because properties and methods are resolved at runtime. This behavior also allows you to add methods and properties to classes without modifying the class itself. This is how Groovy itself extends some of the JDK classes—see section 2.4.3 on the Groovy JDK to see some of the extra methods and properties it provides.

So, whenever you see references to methods or properties that have no declaration, chances are that Grails has injected them into the class. Don’t worry, we’ll mention when this happens in our examples, and now you know where they’ll be coming from!

The Dangers

Remember, with great power comes great responsibility.

Uncle Ben, Spiderman, 2002

Using Groovy for the first time can often feel like a straitjacket has been removed. It gives you great freedom in your coding and makes it easier to express your ideas and designs in code. But with this power come pitfalls that you need to be aware of.

First, the compiler can’t pick up type violations or missing properties and methods, because these are all resolved at runtime. You’re likely to become quite familiar with MissingPropertyException and its relative MissingMethodException early on in your Groovy experience. You’ll be surprised how rarely they appear later on, but you should get into the habit of writing tests for your code at an early stage, and we cover this in chapter 7.

Second, Groovy applications are more difficult to debug, particularly with dynamically injected properties and methods. Using the “step into” feature of a debugger is likely to cause plenty of pain. Instead, make judicious use of breakpoints and the “run to cursor” feature.

Finally, overusing dynamic injection and even untyped variables can make it difficult to understand code. In both cases, it’s important to use descriptive names, and in the case of dynamic injection, you should document what methods and properties you are adding and what they do. Also consider using declared types for method and closure arguments: not only will people find it easier to use those methods, but IDEs can highlight potential type errors in the calling code.

Used judiciously, dynamically injected properties and methods can improve your productivity by enhancing classes in a non-invasive way. Probably the best example of this is the Groovy JDK, which is a set of enhancements to the core JDK classes.

2.4.3. The Groovy JDK

Have you ever bemoaned the lack of a method in the JDK or wondered why you have to use helper classes like java.util.Collections? Groovy tries to fill in any gaps it sees in the JDK and make code more uniformly object oriented than Java through the Groovy JDK, a set of enhancements to some of the more commonly used JDK classes. We can’t cover all the extra properties and methods because there are too many, but we’ll look at some of the more useful ones. For a full rundown, see the Groovy JDK reference online: http://groovy.codehaus.org/groovy-jdk/.

Probably the most useful additions relate to collections. Most of these also apply to arrays and strings, the latter of which are generally treated as lists of characters. There are also some nice enhancements to java.io.File. We round off with some miscellaneous improvements.

Collection/Array/String.Size()

In the interest of consistency, Groovy provides the size() method for both arrays and strings. Its behavior matches the length property for arrays, and the length() method on String. No longer do you have to remember which property or method to use for a particular type!

Collection/Array/String.Each(Closure)

You’ve already seen the each() method in action in some of the examples earlier in the chapter. It iterates over all elements of a collection, applying the given closure to each one in turn. Remember, a string is treated as a sequence of characters, so this code,

"Test".each { println it }

will print this to the console:

T
e
s
t
Collection/Array/String.Find(Closure)

Once you begin to use find() (and its sibling, findAll()), you’ll wonder how you ever managed to live without it. It does exactly what it says on the tin: finds an element within a sequence. More specifically, it returns the first element for which the given closure returns true. If there is no such element, the method returns null. The closure effectively acts as the criteria.

In this example, we retrieve the first object in a list for which the firstName property is “Glen”:

def glen = personList.find { it.firstName == "Glen" }

Whereas find() returns the first element that matches the criteria, findAll() will return all matching elements as a list. If there are no matching elements, it will return an empty list rather than null.

Collection/Array/String.Collect(Closure)

collect() is one of those methods that takes some getting used to but becomes invaluable once you do. In some other languages, it’s called the “map” function, and it iterates through the collection, applying the given closure to each element and adding the return value to a new list.

For example, say we have a list of strings and we want the lengths of those strings as a list. We can do that like so:

def names = [ "Glen", "Peter", "Alice", "Graham", "Fiona" ]
assert [ 4, 5, 5, 6, 5 ] == names.collect { it.size() }

Note that the new list has the same size and order as the original.

Collection/Array.Sort(Closure)

The sort() method sorts a collection using the given closure as a comparator. The closure can either take a single argument, in which case it should return a value that’s itself comparable, such as a string, or it can take two arguments (like the compareTo() method) and return an integer representing the relative order of the two values.

To demonstrate what this means in practice, we’ll sort a list of names based on their lengths using both approaches. First, here’s a single-argument closure:

def names = [ "Glen", "Peter", "Ann", "Graham", "Veronica" ]
def sortedNames = names.sort { it.size() }
assert [ "Ann", "Glen", "Peter", "Graham", "Veronica" ] == sortedNames

Next we use a two-argument closure:

def names = [ "Glen", "Peter", "Ann", "Graham", "Veronica" ]
def sortedNames = names.sort { name1, name2 ->
name1.size() <=> name2.size()
}

assert [ "Ann", "Glen", "Peter", "Graham", "Veronica" ] == sortedNames

The effect is the same in both cases, so the first form is preferable. More complicated comparisons may require the second form.

Collection/Array.Join(String)

The join() method creates a string by concatenating the elements of the collection together in order, using the given string as a separator. If the elements aren’t strings themselves, toString() is called before performing the concatenation.

One of the most common uses for this method is to convert a real list of strings to a comma-separated “list” like so:

def names = [ "Glen", "Peter", "Alice", "Fiona" ]
assert "Glen, Peter, Alice, Fiona" == names.join(", ")

The effect can be reversed by using the standard String.split(String) method of the JDK.

File.Text

The text property reads the given file and returns its content as a string.

File.Size()

File.size() returns the size of the file in bytes. It corresponds to the File.length() method.

File.Withwriter(Closure)

There are various with...() methods for streams and files, but we’ll only cover this one here. See the Groovy JDK reference for the others.

The File.withWriter() method conveniently creates a java.io.Writer from the file and passes it to the closure. Once the closure executes, the underlying output stream is closed automatically and safely (it doesn’t throw any exceptions). No more try...catch blocks just to write to a file!

Matcher.Count

The count property returns the number of matches found by the given Matcher. This is unrelated to the number of groups in the corresponding pattern.

Number.Abs()

Finally! You can now call the abs() method directly on numbers.

Number.Times(Closure)

The times() method calls the given closure n number of times, where n is the number the method is called on. Note that this only makes sense with integers. The closure is passed the current iteration number, which starts from 0.

We have only shown a fraction of the available properties and methods in the Groovy JDK, but these are some of the most common, and they’re used extensively throughout this book. As you become more experienced with Groovy, you should get into the habit of checking the Groovy JDK for any other useful properties or methods on the classes you’re working with. You never know what gems might be hidden in there!

There are two more features we’d like to introduce before wrapping up this chapter. They pop up all over the place in Grails, so it’s important to understand what they do and how they work. They also happen to make XML fun to work with!

2.4.4. Creating and parsing XML the easy way

The Java universe is full of XML: libraries for generating it, libraries for parsing it, and XML configuration files everywhere! Because Grails lives in that universe, it’s great news that Groovy makes both creating and parsing XML simple. Its support comes in the shape of a “markup builder” for generating XML and an “XML slurper” for parsing it.

Listing 2.7 demonstrates both features in a single example. It first writes this XML to a file using the markup builder:

<root>
<item qty="10">
<name>Orange</name>
<type>Fruit</type>
</item>
<item qty="6">
<name>Apple</name>
<type>Fruit</type>
</item>
<item qty="2">
<name>Chair</name>
<type>Furniture</type>
</item>
</root>

Then it parses that file using the slurper. Finally, it extracts different pieces of information from the XML and prints them to the console.

Listing 2.7. Playing with XML the Groovy way

Have you ever seen so little code for generating XML and extracting information from it? Let’s start with the code that creates the XML. All we’re doing is creating a new instance of MarkupBuilder and calling a method on it (root()). The builder doesn’t have a method called “root” itself, so rather than throw an exception, it treats the method as the start of a new XML element. As you can guess, the name of the XML element comes from the name of the method.


A story of two markup builders

Interestingly, MarkupBuilder isn’t the only builder you can use to create XML. Groovy also comes with StreamingMarkupBuilder. This is superficially similar to the builder we have been using, but its internals are different.

From the user’s perspective, the streaming builder has more features but it does no indenting at all (the XML is created as a single line). Check out the online Groovy documentation for more info.


Nested elements are then implemented via closures , where the closure is the last argument of the corresponding method. In listing 2.7, item(), name(), and type() are unknown methods, so they become XML elements. Attributes are declared as named arguments of the method, whereas simple text content is passed as an unnamed string argument. Those are the technical aspects, but you’ll get the general idea by looking at the example code.

It’s also worth noting that you can intermingle regular code with the markup, as we have done with the each loop. This allows for succinct code that can generate large quantities of XML. Once you get used to this form of markup, you’ll find XML itself verbose and annoying. You have been warned!

The next stage involves parsing the generated XML using the XmlSlurper class. When using this approach, you end up with an in-memory representation of the XML that you can navigate using property notation . When the slurper parses XML, it returns an object representing the root element of the document. In fact, it’s an instance of the GPathResult class, but that doesn’t matter. We’re more interested in how it behaves.

As you can see in listing 2.7, you access the elements of the XML by referring to properties of the same name. You navigate nested elements through multiple levels of property access, or multiple dots (.), if you will. So, to get hold of the name elements, we have to go through the item property:

def names = xml.item.name

This little example raises the question: what do the item and name properties return?

Based on listing 2.7, you could be forgiven for thinking that the properties return lists. That’s almost correct, because they do behave like lists in many ways, but they don’t implement the List interface. This is an important point to understand. You can call the size() and findAll() methods on the result, but you only get a real list if you call the special list() method.

One last thing: getting the values of attributes is simply a case of prepending the property name with an @ character.

That’s it for now—the whistle-stop tour of Groovy and XML is now complete. Although we have mainly included coverage because Grails uses both extensively, we think you’ll be inspired to start using Groovy XML processing in non-Grails projects too!

Hopefully, this discussion of Groovy and XML has highlighted how closures and dynamic methods can come together to provide novel, easy-to-use solutions for common problems. Even if you have found some of the concepts tough going, don’t worry about it. You don’t need an in-depth understanding at this stage, and you’ll see plenty more examples in the coming chapters that will help you understand the features better.

2.5. Summary and best practices

We have covered Groovy at a rather rapid pace, so let’s stop and take stock. From the early sections and examples in this chapter, you should be feeling pretty confident and hopefully excited about programming in Groovy. Even if you feel overwhelmed at this stage, don’t worry. This chapter includes more information than you need to get started. As you progress through the rest of the book, flip back here whenever you see something in an example you don’t quite understand.

At first, you’ll just need to recognize some of the syntax and constructs that are unique to Groovy. Later on, a firm grasp of the dynamic nature of Groovy will help your confidence level and help you avoid common pitfalls. We expect that you’ll soon enjoy Groovy’s expressivity and power. Just don’t blame us if you no longer want to program in plain Java!

Here are a few simple guidelines to smooth your way:

  • Use idiomatic Groovy. The syntax sugar in Groovy is there to make your life easier and your code clearer, so make use of it. You’ll also find it easier to follow example Groovy code if you are used to using the various idioms that differentiate Groovy from Java. After this chapter, all example Groovy code is idiomatic rather than Java-style.
  • Experiment. The Grails shell and console allow you to easily experiment with Groovy code. This is a great way to learn the language and find out just what you can do.
  • Use methods where appropriate. Although closures are powerful, don’t forget that methods are too. You may not be able to pass methods as arguments or treat them as objects, but they integrate well with Java, and the rules for inheritance are well understood.
  • Use explicit types in method signatures. It’s tempting to use untyped variables and arguments everywhere, but consider using explicit types for method arguments and return types. Not only do they document what the method expects and returns, but they can also be used by IDEs to detect incorrect usage. And if you call a method with incorrect types, the code will fail quickly with an error that makes it clear what went wrong. That said, when there is a clear benefit to a method supporting duck typing, or if a method can work with multiple types for a particular argument, it makes sense to use one or more untyped arguments. Just make sure that you clearly document in the javadoc what the method expects from untyped arguments.

Before we move on to the Grails fundamentals, remember that Groovy isn’t just a language for Grails. It can be used for a variety of purposes: writing scripts, scripting a Java application, rapid prototyping, and more! For a more comprehensive look at the language itself, check out Groovy in Action, by Dierk Koenig with Andrew Glover, Paul King, Guillaume Laforge, and Jon Skeet.

You have seen how quickly an application can be built from scratch. You should be able to understand and write Groovy without fear. It’s now time to introduce you to the fundamental concepts of a Grails application, starting with domain classes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset