Groovy Programming

You do not need to be a groovy expert to complete your apps, but you’ll have to learn some groovy. My motivation for this lecture is to introduce you to the most commonly used syntax and operators in Groovy, so you can get started quickly. Another reason is that when I started using Grails, a lot of what I wrote seemed like magic, especially editing the configuration files. Sure, you can copy and paste a line and then edit it. you’ll probably get the app running, but it is not very satisfying. If an error should happen, you are not well prepared to fix it. So, I hope that this lecture can also demystify some of the groovy aspects that appear like magic.

Much of the material for the lecture comes from the first chapter of Programming Grails by Burt Beckwith and the Groovy User Guide page.

http://groovy-lang.org/documentation.html

A reason why I chose Groovy and Grails framework for your projects is because Groovy is a scripting language built on top of Java, so I thought that the language should be somewhat familiar to you, but that is not always true. You can almost always use Java syntax and commands, but to do that would lose the power of Groovy.

Some Mysteries of Groovy Unraveled

The groovy compiler, groovyc, makes byte code similar to what javac does, but its parser is LL(3), which implies it can look ahead three tokens instead of two tokens as in a LL(2) parser. This allows it to parse “===” and I believe to do away with many brackets that delineate function argument list, maps and arrays.

During bye code generation the groovy compiler adds methods and properties to your classes. But, it also adds a MetaClass to the MetaClassRegistry for the execution context. There is only one MetaClassRegistry for a context, and it associates the MetaClass to the class defined in your code.

Method invocation is the term for how a compiler setups the method calls in your code. The method invocation in groovy is that the MetaClass for your class is called first. This permits the objects of your class to appear to be more dynamic, meaning that properties and methods can be added at run time.

Groovy Console

You can run groovy code in your web app and test them with the Grails console. The Groovy Console is shipped with GGTS and IntelliJ IDEA. It allows you to run isolated groovy code. It is useful for developing algorithms or learning groovy.

http://groovy-lang.org/groovyconsole.html

Make a “Groovy Project” in IntelliJ and then  select Tools -> “Groovy Console” will open a groovy console.  You can open as many as you like.

https://www.jetbrains.com/help/idea/2016.3/launching-groovy-interactive-console.html

Preliminary Groovy

Groovy has some nice groovy features that simplify your code.

  • No need for semi colons.
  • No need for functions or methods to have  (…) to delineate arguments.
  • No need for the return statement. The value of the last line of code is the return value.

Groovy Reading Hint

If you see missing parentheses assume it is a method call and the arguments of the methods are the variables following the method name.

Optional Typing

Groovy is a dynamic language which means that objects do not have to be typed and can appear to change their type. Groovy enables this by using “def” keyword to define an object, such as

def person = new Person()

the compiler replaces the definition with

Object person = new Person()

In java, this would cause problems later in your code when you want to call a Person method on  a person object, you would have to cast person to the Person type

(Person)person.personName()

But in groovy you do not have to make the cast because the MetaClass for  the person object is called first, so the compiler knows the class of the object. Of course if you declare the object with “def” then the precompiler cannot warn you of potential syntax errors. I advise to type declare objects whenever you can.

The MetaClass also allows you to dynamically invoke methods or access properties, for example

String propertName = "presonName"
def name = person."$propertyName"

In the above example the personName property of the person class is assessed using a string variable.

Arrays and Maps

Declaring Collections

When you make an array in groovy, the compiler implements it as an ArrayList. The example below

List<String> names = ["Robert", "Nancy", "Bill"]

is implemented as

List<String> names = new ArrayList<String>();
names.add("Robert");
names.add("Nancy");
names.add("Bill");

Maps (key-value pairs) are implemented with a LinkedHashMap. You can make a Map using square bracket and colon notation.

name = ["first name": "Robert", "last name": "Pastel"]

In this case both the key and the value are Strings. Keys are always Strings, so if the key is a single word you can omit the quotation marks around the key.

name = [first: 'Robert', last: 'Pastel']

Note groovy does not care if you use single or double quotation marks to represent strings. Items in a Map can be accessed by the key, index or using dot notation.

assert name['first'] == 'Robert'
assert name[0] == 'Robert'
assert name[-1] == 'Pastel'
assert name.last == 'Pastel'

Groovy Reading Hint

Whenever you see square brackets think, “The object being represented is a Collection, either a List, Set or Map.” If it is a Map you’ll also see colons.

Using Collections

Lists and Maps has many new groovy operators. You can see examples in the documentation.

http://www.groovy-lang.org/groovy-dev-kit.html

Some of the more popular operators are ‘<<‘ and ‘+’ for adding to a collection. The star dot, ‘*.’ or ‘.each{…}’ for traversing the collection.

http://www.groovy-lang.org/operators.html

Plain Old Groovy Object (POGO)

Many classes are simple and are composed of only attributes with getter and setter methods and have empty constructor. These are called Plain Old Groovy Objects (POGO). For example the Person class.

class Person {

// class attributes
    private String firstName;
    private String lastName;

    // class setters and getters
    public String setFirstName(String name){this.firstName = name;}
    public String getFirstName(String name){return firstName;}
    public String setLastName(String name){this.lastName = name;}
    public String getLastName(String name){return lastName;}
}

In groovy you would just code the class attributes without the scoping qualification, i.e. “private”.

class Person{
   String firstName
   String lastName
}

The groovy compiler will make the class attributes private and write the setter and getter methods for you. If you needed to do something special in either of the setters and getters you would just overwrite the method.

class Person{
   String firstName
   String lastName
   String gender

   public setGender(String g){
      // check that gender is male or female
      …
     this.gender = g
   }
}

You can control the auto generation of setters and getters by using private or final and overloading the get and set methods.

This automation can sometimes cause problems. If you make methods in a groovy class with prefix “set” or “get” then groovy will add the field to the class. For example, suppose you code

class Person{
   String firstName
   String lastName

   def setMiddleName(){
       // do something, perhaps save in a hashmap.
   }
}

Groovy will make class like

class Person {

// class attributes
    private String firstName;
    private String lastName;
    private String middleName;

    // class setters and getters
    public String setFirstName(String name){this.firstName = name;}
    public String getFirstName(String name){return firstName;}
    public String setLastName(String name){this.lastName = name;}
    public String getLastName(String name){return lastName;}
   
   public void setMiddleName{
       // do something
   }
   public String getLastName(String name) {return middleName;}   
}

Frequently this is not a problem, but it might lead to unaccepted behavior. Especially, if Person is a domain object then GORM and Hibernate will not see the “middleName” field and give an error trying to setup the database.

Constructors

Groovy like Java makes the empty constructor, but groovy also makes a constructor which accepts a map of the attributes and values. A Person instance can be made as below.

def me = new Person([firstName: "Robert", lastName: "Pastel"])

The above can be shorter.

def me = new Person(firstName: "Robert", lastName: "Pastel")

Note that there is no need for both square brackets delinting the map. The map constructor is implemented by the MettaClass by first calling the default constructor and then calling the set methods for each key of the map.

Groovy Reading Hint

Whenever you see colons, ‘:’, even without the square brackets think map.

Closures

Defining and Calling

The term closure is probably new to you and will appear mysterious. The formal definition of closure is that it is a segment of code that is defined before it is invoked and has scope at the time that they are defined.

http://www.groovy-lang.org/closures.html

Think of them as functions, and generally you just use them like autonomous classes. Closures can be assigned to a variable so you can throw them around like any object.

def myClosure = {println "Hello World"}

You can later call the closure.

myClosure.call()
myClosure()

Closures can have parameters and use the arrow, ‘->’, to separate the argument list from the body.

def printFirstLastName = {first, last -> println first+" "+last}

and use it thus

printFristLastName("Robert", "Pastel")

Frequently closures have only one argument then the argument’s name is ‘it’.

def printWord{println it}

In a Closure this, owner and delegate

The “this”  in a closure refers to the instance of the enclosing class.

The “owner” refers to the enclosing object. It can be the same as “this” or reference an enclosing closure.

The “delegate” is by default “owner” but can be set.

http://www.groovy-lang.org/closures.html#closure-owner

Grails makes use of setting delegates of closures. Below is an example of a static closure for a Domain class.

   
class PersonName{
   String firstName
   String lastName
   static mapping = {
      version false
      table 'person'
   }
}

It might appear that calling the above “mapping” closure should fail because the methods version and table are not defined in the PersonName. But, Grails expects the closure ‘mapping’ and will assign the mapping closure a delegate which then redefines the scope of version and table.

Groovy Reading Hint

Whenever you see curly brackets think closure, function or method. Recall that the scope can be redefined.

Groovy Truth

Groovy will return true on more than a boolean object. It returns true for object that have value and false for null objects. Non empty arrays and maps return true, empty arrays and maps return false. This is very useful when checking if you can make a call.

def myCollection = makeMe(…)
if (myCollection) { // then do something}

Groovy Strings

Groovy uses the dollar sign, “$”, like many scripting languages, to represent the value of a variable. But in groovy it is only used as a string representation of the value.

String fullname = "$person.fistName $person.lastName"

These types of strings are called GStrings.

http://docs.groovy-lang.org/latest/html/documentation/index.html#all-strings

The complete syntax includes curly brackets ${expression}. So you can do.

def v1 = 2
def v2 = 3
println "$v1 plus $v2 is ${v1 + v2}"

Groovy Operators

Groovy adds lots of operator to make your code appear cleaner.

http://www.groovy-lang.org/operators.html

Null-Safe

Very frequently you need to check that an object is not null before calling a method. In groovy this is easy with the “?.” navigation safe operator.

String name = person?.firstName

Groovy will check that the person object is not null before calling the getFirstName method.

Elivis

While setting a value, you may want a defaults value if the object is null. This can be done by Using groovy truth and the Elvis operator, “?:”, for example:

String name = person.firstName ?: defaultName

Instead of

String name = preson.firstName ? person.firstName : defaultName

In Java you would write.

if(person != null ) preson.firstName ? person.firstName : defaultName;

Spread

The spread operator, “*.”, traverses a collection and invokes the action. For example

assert ["Bob", "Billy"]*.size() == [3, 5]

Spaceship

The spaceship operation, “<=>” is used in comparisons.

left <=> right

returns

  • -1 if left < right
  • 0 if left == right
  • 1 if left > right

as

The “as” operator is groovy’s type casting.

def animalType = ['cat', 'dog', 'bird'] as Set

Forces the array to be a type Set.

in

The “in” operator is a shorthand for contains

assert 1 in [1, 2, 3]

Review Groovy Read Hints

  • See {…} think closure
  • See [ ] think collection
  • See : think map
  • See $variable or ${expression} think GString
  • See “command variable” think function call, i.e. command(variable)
  • See the end of a method think return
  • See variable?.method think null checking
  • See variable?: default think Elvis, the shorten of the ternary operator

In no time you’ll be reading and writing groovy like you do Java.