I suspect that to complete your apps will not require you to become a groovy expert, 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 the line above and then edit it, and you’ll get the app running, but it is not very satisfying. If an error should happen, you are not well prepared to fix it. So, This lecture could also demystify some of the groovy aspects that appear like magic.
Much of this material of the lecture comes from the first chapter of Programming Grails by Burt Beckwith and the Groovy User Guide page.
http://groovy.codehaus.org/User+Guid
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 it 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 a LL(3), which implies 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.
http://groovy.codehaus.org/Groovy+Backstage
During bye code generation the groovy compiler adds methods and properties to your class. But, it also adds a MetaClass and 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 for objects of your class to appear to be more dynamic, meaning that properties and methods can be added at run time.
http://groovy.codehaus.org/Groovy+Method+Invokation
Groovy Console
You can run groovy code in your web app and test them with Grails console. The Groovy Console is shipped with GGTS and allows you to run isolated groovy code. It is useful for developing algorithms or learning groovy.
Console
Make a “Groovy Project” then use right click project on the project -> “run as” -> “Groovy Console” opens a groovy console. You can open as many as you like. It is a simple script editor with a console output screen. It does have an AST (Abstract Syntax Tree) browser which shows you the Java code of your script and allows you to view the code generate during the different phase of compilation.
Preliminary Groovy
Groovy has some nice groovy features that simplify your code.
- No need for semi colons
- No need for function or method (…)
- No need for return. The value of the last line of code is the return value.
Groovy Reading Hint
If you see missing parentheses or brackets assume it is a method call and the arguments of the methods are variable following the command 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 simply by whenever you define an object using “def” 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 person. 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 associated with the person object will called first and knows the class. 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 propertise, for example
String propertName = "presonName" def name =person."$propertyName"
Arrays and Maps
Declaring Collections
When you make array in groovy, the compiler implements it as an ArrayList.
List<String> names = ["Robert", "Nancy", "Bill"]
is implemented
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 at the “For those new to both Java and Groovy.”
http://groovy.codehaus.org/JN1015-Collections
http://groovy.codehaus.org/JN1025-Arrays
http://groovy.codehaus.org/JN1035-Maps
Some of the more popular operators are ‘<<‘ and ‘+’ for adding to a collection. The star dot, ‘*.’ or ‘.each{…}’ for traversing the collection.
Plain Old Groovy Object (POGO)
Many classes are simple and basically are composed of only attributes with getter and setter methods and have empty constructor. These are called 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.
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 some 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 use of private, final and overloading the getter and setters.
Constructors
Groovy like Java makes the empty constructor, but groovy also makes a constructor which accepts a map of the attributes and values. For a Person instance can be made.
def me = new Person([firstName: "Robert", lastName: "Pastel"])
The above can be shorter.
def me = new Person(firstName: "Robert", lastName: "Pastel")
The map constructor is implemented by the MettaClass by calling the default constructor and then calling the setter methods for each key.
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 is that segment of code that are defined before they are invoked and have scope at the time that they are defined.
http://groovy.codehaus.org/Closures+-+Formal+Definition
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.
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' } }
Appears above that calling the 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 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 the variable, but in groovy it is only a string representation.
String fullname = "$person.fistName $person.lastName"
The types of strings are called GStrings.
http://groovy.codehaus.org/Strings+and+GString
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://groovy.codehaus.org/Operators
Null-Safe
Very frequently you need to check that an object is not null before call a method. In groovy this is easy with the “?.” navigation safe operator.
String name = person?.firstName
Groovy will check that person is not null before calling the getFirstName method.
Elivis
Frequently you set defaults after you assume the object has been set. Using groovy truth and the Elvis operator, “?:” you and do this easily.
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.
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 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.