I suspect that 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 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” then in IntelliJ select Tools -> “Groovy Consloe” -> opens 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 code 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 cast because the MetaClass for the person object is called first and 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. In 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 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 atributes 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.
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
Closures are 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 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 object of value 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.