Tuesday, 14 October 2008

Beginning Groovy and Grails - Part1

Couple of Days back i started reading Beginning Groovy and Grails Christopher M. Judd,Joseph Faisal Nusairat,Jim Shingler.

I wanted to share few quotations found from this book from 1st 2 chapters.

First i downloded groovy and grails from this site.

1) Groovy is a relatively new dynamic language that can either be interpreted or compiled and is designed specifically for the Java platform. It has been influenced by languages such as Ruby, Python, Perl, and Smalltalk, as well as Java.

2) Groovy does not just have access to the existing Java API; its Groovy Development Kit (GDK) actually extends the Java API by adding new methods to the existing Java classes to make them more Groovy.

3) Groovy is a standard governed by the Java Community Process (JCP)1 as Java Specification Request (JSR) 241.2 It is hosted on Codehaus at http://groovy.codehaus.org.

4) Groovy by Example

The best way to grasp the power and elegance of Groovy is to compare it to Java using an example.


/*
* Java example for the purpose of comparing it to the equivilant
* Todos.groovy file.
*/


import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

public class Todo {
private String name;
private String note;

public Todo() {}

public Todo(String name, String note) {
this.name = name;
this.note = note;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getNote() {
return note;
}

public void setNote(String note) {
this.note = note;
}

public static void main(String[] args) {
List todos = new ArrayList();
todos.add(new Todo("1", "one"));
todos.add(new Todo("2", "two"));
todos.add(new Todo("3","three"));

for(Iterator iter = todos.iterator();iter.hasNext();) {
Todo todo = (Todo)iter.next();
System.out.println(todo.getName() + " " + todo.getNote());
}
}
}



Converting Java to Groovy


class Todo {

String name
String note

}

def todos = [
new Todo(name:"1", note:"one"),
new Todo(name:"2", note:"two"),
new Todo(name:"3", note:"three")
]

todos.each {
println "${it.name} ${it.note}"
}



As we understand from the above example

a) GroovyBeans are publicly scoped by default and automatically generate corresponding getters and setters in the bytecode.
b) Groovy has a concept of native properties, which means getters and setters do not need to be declared.
c) Notice how the ArrayList was replaced with []. Again, this is just syntactic sugar; Groovy really is instantiating an ArrayList. Similarly, we can create maps with the [:] syntax.

5) Some of the syntax sugar included in the Groovy language is making semicolons, parentheses,and data typing optional.Other interesting features to simplify code include implicit imports like the java.util.* package, common methods like println() applying to all objects including Java objects, and more flexible strings.

6) Groovy uses "duck typing," which means if it sounds like a duck and walks like a duck, it must be a duck.

7) Using Script Functions

Just like most scripting languages, Groovy scripts can be organized into blocks of reusable code. In scripts, these blocks are called functions. It creates a simple function to print a name and calls the function with two different names.

Example:


def printFullName(firstName, lastName) {
println "${firstName} ${lastName}"
}
printFullName('Luke', 'SkyWalker')
printFullName('Darth', 'Vader')


8) The Groovy compiler is a joint compiler. It can compile Groovy and Java code at the same time. The joint compiler first became available in Groovy 1.5 through a generous donation by JetBrains, the makers of IntelliJ IDEA. The joint compiler allows you to compile Groovy and Java files with a single compile statement.

Example:


class Name
{
String firstName
String toString() { return "Hello ${firstName}, Java calling Groovy" }
}



public class SayHello
{
public static void main( String args[] )
{
Name name = new Name();
name.setFirstName( args[0] );
System.out.println( name.toString() );
}
}


When we run this java program it calls the underlying Name groovy class.

9) Strings

Like most modern languages, Groovy has the concept of a string. In Groovy, a string can be defined three different ways: using double quotes, single quotes, or slashes (called "slashy strings").


def helloChris = "Hello, Chris"
println helloChris.class.name // java.lang.String

// Single quote
def helloJoseph = 'Hello, Joseph'
println helloJoseph.class.name // java.lang.String

// Slashy string
def helloJim = /Hello, Jim/
println helloJim.class.name // java.lang.String


10) If we define the string with single quotes. The result is a regular Java string, and the expression is not evaluated.


def name = "Jim"
def helloName = "Hello, ${name}"
println helloName // Hello, Jim
println helloName.class.name // org.codehaus.groovy.runtime.GStringImpl

def helloNoName = 'Hello, ${name}'
println helloNoName // Hello, ${name}
println helloNoName.class.name // java.lang.String

def helloSlashyName = /Hello, ${name}/
println helloSlashyName // Hello, Jim
println helloSlashyName.class.name // org.codehaus.groovy.runtime.GStringImpl


11) Multiline Strings

Groovy supports strings that span multiple lines. A multiline string is defined by using three double quotes or three single quotes.String interpolation with multiline strings works in the same way as it does
with regular strings: multiline strings created with double quotes evaluate expressions, and single-quoted strings don’t.


def name = "Jim"
def multiLineQuote = """
Hello, ${name}
This is a multiline string with double quotes
"
""
println multiLineQuote
println multiLineQuote.class.name
def multiLineSingleQuote = '''
Hello, ${name}
This is a multiline string with single quotes
'
''
println multiLineSingleQuote
println multiLineSingleQuote.class.name


12) Methods

Defining aMethod the Java Way


public String hello(String name) {
return "Hello, " + name;
}

Defining aMethod Using the Groovy Idiom
def hello(name) {
"Hello, ${name}"
}


The Groovy way of defining is method is a bit more compact. It takes advantage of a couple of Groovy’s optional features:

• The return type and the return statement are not included in the body of the method. Groovy always returns the results of the last expression—in this case, the GString "Hello, . . . ".

• The access modifier public is not defined. By default, unless you specify otherwise,Groovy defaults all classes, properties, and methods to public access.

13) Closures

A Groovy closure is a block of reusable code within curly braces {}, which can be assigned to a property or a variable, or passed as a parameter to a method. The code within the curly braces is executed when the closure is invoked. In this form, the closure functions just like a Java method. The difference between methods and closures is that a closure is an object, and a method isn’t.


def name = "Chris"
def printClosure = { println "Hello, ${name}" }
printClosure()
name = "Joseph"
printClosure()


14) And just as with methods, parameters can be passed to closures as well.


def printClosure = {name -> println "Hello, ${name}" }
printClosure("Chris")
printClosure("Joseph")
printClosure "Jim"


The third invocation of printClosure does not include parentheses.This is not a typo. This is another one of the optional parts of Groovy. The fact that there is a parameter after the closure name helps Groovy infer that you want the closure invoked.

15) Multiple parameters can be passed as well


def printClosure = {name1, name2, name3 -> println "Hello, ${name1}, ${name2}, ${name3}" }

printClosure "Chris", "Joseph", "and Jim"


16) An advanced usage of closures is to bind the closure to values at the time it is defined.


def startTimer() {
def initialDate = new java.util.Date()
return { println "${initialDate} - ${new java.util.Date()} : Elapsed time ${System.currentTimeMillis() - initialDate.time}" }
}

def timer = startTimer()
//Simulate some work
sleep 30000
timer()
// Simulate some more work
sleep 30000
timer()

//Reset the timer
println "Reset the Timer"
timer = startTimer()
timer()
sleep 30000
timer()


17) A closure is an object. You can pass closures around just like any other objects.


def list = ["Chris", "Joseph", "Jim"]
def sayHello = { println it }
list.each(sayHello)


18) A Groovy list is an ordered collection of objects, just as in Java. It is an implementation of the java.util.List interface. In the course of building Grails applications, it is common to see lists returned from the controllers and services.


def emptyList = []
println emptyList.class.name // java.util.ArrayList
println emptyList.size // 0

def list = ["Chris"] // List with one item in it
// Add items to the list
list.add "Joseph" // Notice the optional () missing
list << "Jim" // Notice the overloaded left-shift operator
println list.size // 3

// Iterate over the list
list.each { println it } // Chris Joseph Jim

// Access items in the list
println list[1] // Joseph // Indexed access
list[0] = "Christopher"
println list.get(0) // Christopher

list.set(0, "Chris") // Set the 0 item to Chris
println list.get(0) // Chris

list.remove 2
list-= "Joseph" // Overloaded - operator
list.each { println it } // Chris

list.add "Joseph"
list+="Jim" // Overloaded + operator
list.each { println it } // Chris Joseph Jim
println list[-1] // Jim


19) Ranges

A range is a list of sequential values. Logically, you can think of it as 1 through 10 or a through z. As a matter of fact, the declaration of a range is exactly that: 1..10, or 'a'..'z'. A range is a list of any objects that implements java.lang.Comparable. The objects have next() and previous() methods to facilitate navigating through the range. This means that with a bit of work, it is possible to use your own Groovy objects within a range.


def numRange = 0..9
println numRange.size() // 10
numRange.each {print it} // 0123456789
println ""
println numRange.contains(5) // true

def alphaRange = 'a'..'z'
println alphaRange.size() // 26
println alphaRange[1] // b

def exclusiveRange = 1..<10
println exclusiveRange.size() // 9
exclusiveRange.each {print it} // 123456789
println ""
println exclusiveRange.contains(10) // false

def reverseRange = 9..0
reverseRange.each {print it} // 9876543210


20) Sets

A Groovy set is an unordered collection of objects, with no duplicates, just as in Java. It is an implementation of java.util.Set.By default, unless you specify otherwise, a Groovy set is a java.util.HashSet.If you need a set other than a HashSet, you can create any type of set by instantiating it; for example, def aTreeSet = new TreeSet(). In general, we encourage you just to think of it as a regular set.


def emptySet = [] as Set
println emptySet.class.name // java.util.HashSet
println emptySet.size() // 0

def list = ["Chris", "Chris" ]
def set = ["Chris", "Chris" ] as Set
println "List Size: ${list.size()} Set Size: ${set.size()}" // List Size: 2 Set Size: 1
set.add "Joseph"
set << "Jim"
println set.size() // 3
println set // ["Chris", "Jim", "Joseph"]

// Iterate over the set
set.each { println it }

set.remove 2
set-= "Joseph" // Overloaded - operator
set.each { println it } // Chris
set+= "Joseph"
set+= "Jim"
set.each { println it } // Chris Joseph Jim

// Convert a set to a list
list = set as List
println list.class.name // java.util.ArrayList
println set.asList().class.name // java.util.ArrayList
println set.toList().class.name // java.util.ArrayList


21) Maps

A Groovy map is an unordered collection of key/value pairs, where the key is unique,just as in Java. It is an implementation of java.util.Map.20 By default, unless you specify otherwise, a Groovy map is a java.util.LinkedHashMap.If you are familiar with LinkedHashMap maps, you know that they are ordered by insert. If you need a map other than a LinkedHashMap, you can create any type of map by instantiating it; for example, def aTreeMap = new TreeMap(). In general, we encourage you just to think of it as a regular map.


def emptyMap = [:]
// map.class returns null, use getClass()
println emptyMap.getClass().name //java.util.LinkedHashMap
println emptyMap.size() // 0

def todos = ['a':'Write the map section', 'b':'Write the set section']
println todos.size() // 2
println todos["a"] // Write the map section
println todos."a" // Write the map section
println todos.a // Write the map section
println todos.getAt("b") // Write the set section
println todos.get("b") // Write the set section
println todos.get("c", "unknown") // unknown, Notice "c" wasn't defined
// and now it is
println todos // ["a":"Write the map section", "b":"Write the set section",
// "c":"unknown"]

todos.d = "Write the ranges section"
println todos.d // Write the ranges section
todos.put('e', 'Write the strings section')
println todos.e // Write the strings section
todos.putAt 'f', 'Write the closure section' // Notice () are optional
println todos.f // Write the closure section
todos[null] = 'Nothing Set' // Using null as a key
println todos[null] // Nothing set

// Print each key/value pair on a separate line
// Note: it is an implicit iterator
todos.each { println "Key: ${it.key}, Value: ${it.value}" }
// Print each key/value pair on a separate line with index
todos.eachWithIndex { it, i -> println "${i} Key: ${it.key}, Value: ${it.value}" }
// Print the value set
todos.values().each { println it }


Author Information

Christopher Judd is the president and primary consultant for Judd Solutions, LLC, an international speaker, an open source evangelist, the Central Ohio Java Users Group leader, and the coauthor of Enterprise Java Development on a Budget (Apress, 2003). He has spent 12 years architecting and developing software for Fortune 500 companies in various industries, including insurance, retail, government, manufacturing, and transportation. His current focus is consulting, mentoring, and training with Java, Java EE, Java Platform, Micro Edition (Java ME), mobile technologies, and related technologies.

Joseph Faisal Nusairat is a software developer who has been working full time in the Columbus, Ohio, area since 1998, primarily focused on Java development. His career has taken him into a variety of Fortune 500 industries, including military applications, data centers, banking, internet security, pharmaceuticals, and insurance. Throughout this experience, he has worked on all varieties of application development, from design and architecture to development. Joseph, like most Java developers, is particularly fond of open source projects and tries to use as much open source software as possible when working with clients. Joseph is a graduate of Ohio University with dual degrees in computer science and microbiology and a minor in chemistry. While at Ohio University, Joseph also dabbled in student politics and was a research assistant in the virology labs. Currently, Joseph works as a senior partner at Integrallis Software (http://www.integrallis.com). In his off-hours, he enjoys watching bodybuilding competitions and Broadway musicals, specifically anything with Lauren Molina.

Jim Shingler is a senior consulting IT architect for a major midwestern insurance and financial services company. The focus of his career has been using leading-edge technology to develop IT solutions for the insurance, financial services, and manufacturing industries. He has 11 years of large-scale Java experience and significant experience in distributed and relational technologies.

No comments: