GROOVY
A better Java
would be
Groovy
!=
Java Replacement

Relies on Java

Is slower than Java

Great for Prototypes and Scripting

Strives as an Embedded Language

Ideal for Domain Specific Languages
What is Groovy?

builds upon the strengths of Java but has
additional power features inspired by languages
like Python, Ruby and Smalltalk

increases developer productivity by reducing
scaffolding code when developing web, GUI,
database or console applications

seamlessly integrates with all existing Java
classes and libraries

compiles straight to Java bytecode so you can
use it anywhere you can use Java
As described at http://groovy.codehaus.org/
Why all of this noise?
import java.io.*;
public class HelloWorld
{
public static void main(String[] args) throws Exception
{
String fileName = "/home/wes/test.txt";
BufferedReader br = new BufferedReader(new FileReader(fileName));
try
{
String line = null;
while((line=br.readLine()) != null)
{
System.out.println(line);
}
}
finally
{
br.close();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Shouldn't it be Simpler?
new File('/home/wes/test.txt').eachLine { println it }1

Eliminates the boilerplate code associated with Java

Provides convenient shortcuts and expressive syntax

Leverages extensive collection of Java libraries

Closures provides elegant, reusable solutions
Groovy's Strengths are Simple but Powerful
Closures are
Anonymous Functions
// define a closure
def myCalc = { numForCalc1,numForCalc2 -> numForCalc1 * numForCalc2 }
// define a method with closure as parameter
def doMyCalc(num1, num2, calculateClosure)
{
calculateClosure(num1,num2)
}
// these are all the same
println myCalc(10,20)
println doMyCalc(10,20,myCalc)
println doMyCalc(10,20,{ a, b -> a * b })
println doMyCalc(10,20) { a, b -> a * b }
// or we could provide alternate implementation of the calculation
println doMyCalc(10,20) { a, b -> a - b }
println doMyCalc(10,20) { a, b -> a + b }
println doMyCalc(10,20) { a, b -> b - a }
println doMyCalc(10,20) { a, b -> a ^ b }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
What's Missing? Optional?

Return Statements

last value in a method is an implicit return value

Parameter and Return Types

duck typing is supported

types are checked/enforced when present

Classes

still available for organization purposes

not required as an entry point

Compilation

groovyc can be used to compile groovy to class files

groovy executable provides dynamic runtime
Java from Groovy
public class Contact
{
private String name, email, phone;
public String getName() { return name; }
public void setName(String name){ this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email){ this.email = email; }
public String getPhone() { return phone; }
public void setPhone(String phone) { this.phone = phone; }
}
Contact contact = new Contact(name: 'Wes',
email: 'wes@mail.com',
Phone : '123-123-1234');
println "Contact ${contact.name} at ${contact.email} or ${contact.phone}"
1
2
3
4
5
Contact.java
useContact.groovy
Groovy from Java
import groovy.lang.*;
public class GroovyEmbedded
{
static String formatContact(Contact contact, String format)
{
Binding binding = new Binding();
binding.setVariable("c", contact);
GroovyShell shell = new GroovyShell(binding);
return shell.evaluate("c.identity { "" + format + "" }").toString();
}
public static void main(String[] args) throws Exception
{
Contact contact = new Contact();
contact.setName("Wes");
contact.setPhone("123-123-1234");
contact.setEmail("wes@mail.com");
String format1 = "Name: ${name}, Email: ${email}, Phone: ${phone}";
String format2 = "${name} - p: ${phone} e: ${email}";
System.out.println("Format #1: " + formatContact(contact,format1));
System.out.println("Format #2: " + formatContact(contact,format2));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Metaprogramming

Add behavior dynamically at runtime

Change existing behavior at runtime

Handle missing behavior gracefully

Invoke behavior dynamically
What if the rules only applied when we wanted?
MetaClass
def testString1 = "This is a test string."
def testString2 = "This is ALSO a TEST string."
println "Test #1a: ${testString1}" // This is a test string.
println "Test #2a: ${testString2}" // This is ALSO a TEST string.
try
{
testString1.doTestThing()
}
catch(Exception ex)
{
println "Error: ${ex.class.name}" // groovy.lang.MissingMethodException
}
println "Implement doTestThing at the class level"
String.metaClass.doTestThing = { delegate - " test" }
println "Test #1b: ${testString1.doTestThing()}" // This is a string.
println "Test #2b: ${testString2.doTestThing()}" // This is ALSO a TEST string.
println "Implement doTestThing at the instance level"
testString2.metaClass.doTestThing = { delegate - ~"(?i) test" }
println "Test #1c: ${testString1.doTestThing()}" // This is a string.
println "Test #2c: ${testString2.doTestThing()}" // This is ALSO a string.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Intercepting Method Calls
void methodMissing(String methodName, args)

Allows implementation to be provided when method not present
Object getProperty(String propertyName)

Allows interception of get methods when Groovy's object.property syntax used
void setProperty(String propertyName, Object newValue)

Allows interception of set methods when Groovy's object.property syntax used
Object invokeMethod(String methodName, args)

Same as methodMissing when methodMissing not present

Allows interception of all methods when GroovyInterceptable is implemented
Method Missing
class LikesItAll
{
def likesSports() { println "I play and watch lots of sports!" }
def likesMovies() { println "I see movies all the time!" }
def everythingElse = { println "I really like ${it} too!" }
def methodMissing(String name, args)
{
if(name =~ /^likes/)
everythingElse(name-"likes")
else
println "What?"
}
}
LikesItAll dude = new LikesItAll()
dude.likesMovies()
dude.likesBooks()
dude.likesSports()
dude.dislikesSomething()
dude.likesCars()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Results:
I see movies all the time!
I really like Books too!
I play and watch lots of sports!
What?
I really like Cars too!
GroovyInterceptable
class Bank implements GroovyInterceptable
{
def balance=0
def deposit(amt) { balance += amt }
def withdraw(amt) { balance -= amt }
def invokeMethod(String name, args)
{
def metaMethod = metaClass.getMetaMethod(name, args)
if(metaMethod)
{
metaClass.print "Performing ${name} of $${args[0]}"
return metaMethod.invoke(this, args)
}
metaClass.println "This bank does not support ${name}ing"
}
}
Bank bank = new Bank()
bank.deposit 100
bank.withdraw 20
bank.borrow 30
println "Balance is: $${bank.balance}"
Results:
Performing deposit of $100
Performing withdraw of $20
This bank does not support borrowing
Balance is: $80
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
WITHWITH
GROOVY
POWERPOWER COMESCOMES
GROOVY
RESPONSIBILITYRESPONSIBILITY
Gotcha! Polymorphism Differences
public class Poly
{
void test() { System.out.println("No params"); }
void test(Object test) { System.out.println("Object1"); }
}
public class PolyExt extends Poly
{
void test(Object test) { System.out.println("Object2"); }
void test(String test) { System.out.println("String"); }
public static void main(String[] args)
{
String a = "test";
Object b = a;
Poly poly = new PolyExt();
poly.test();
poly.test(a);
((PolyExt)poly).test(a);
poly.test(b);
((PolyExt)poly).test(b);
}
}
GROOVY
No params
String
String
String
String
JAVA
No params
Object2
String
Object2
Object2
Gotcha! GString's Lazy Evaluation
name = 'Bob'
howToContact = new StringBuffer("1231231234")
contactInfo = "${-> new Date()} - ${-> name} at ${howToContact}n"
contactList = contactInfo
println contactList
Thread.sleep 30000 // 30 seconds
howToContact.append " & 2342342345"
println contactList
Thread.sleep 30000 // 30 seconds
name = "Sue"
howToContact = howToContact.reverse()
contactList += contactInfo
println contactList
Results:
Fri Nov 05 19:12:56 MDT 2010 - Bob at 1231231234
Fri Nov 05 19:13:26 MDT 2010 - Bob at 1231231234 & 2342342345
Fri Nov 05 19:13:56 MDT 2010 - Sue at 5432432432 & 4321321321
Fri Nov 05 19:13:56 MDT 2010 - Sue at 5432432432 & 4321321321
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Further
GROOVY
Reading
Language: http://groovy.codehaus.org/
Web Dev: http://www.grails.org/
Embeded: http://soapui.org/userguide/functional/groovystep.html
DSL: http://www.slideshare.net/glaforge/practical-groovy-dsl
wes-williams.blogspot.com

Groovy Basics

  • 1.
  • 2.
    Groovy != Java Replacement  Relies onJava  Is slower than Java  Great for Prototypes and Scripting  Strives as an Embedded Language  Ideal for Domain Specific Languages
  • 3.
    What is Groovy?  buildsupon the strengths of Java but has additional power features inspired by languages like Python, Ruby and Smalltalk  increases developer productivity by reducing scaffolding code when developing web, GUI, database or console applications  seamlessly integrates with all existing Java classes and libraries  compiles straight to Java bytecode so you can use it anywhere you can use Java As described at http://groovy.codehaus.org/
  • 4.
    Why all ofthis noise? import java.io.*; public class HelloWorld { public static void main(String[] args) throws Exception { String fileName = "/home/wes/test.txt"; BufferedReader br = new BufferedReader(new FileReader(fileName)); try { String line = null; while((line=br.readLine()) != null) { System.out.println(line); } } finally { br.close(); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  • 5.
    Shouldn't it beSimpler? new File('/home/wes/test.txt').eachLine { println it }1  Eliminates the boilerplate code associated with Java  Provides convenient shortcuts and expressive syntax  Leverages extensive collection of Java libraries  Closures provides elegant, reusable solutions Groovy's Strengths are Simple but Powerful
  • 6.
    Closures are Anonymous Functions //define a closure def myCalc = { numForCalc1,numForCalc2 -> numForCalc1 * numForCalc2 } // define a method with closure as parameter def doMyCalc(num1, num2, calculateClosure) { calculateClosure(num1,num2) } // these are all the same println myCalc(10,20) println doMyCalc(10,20,myCalc) println doMyCalc(10,20,{ a, b -> a * b }) println doMyCalc(10,20) { a, b -> a * b } // or we could provide alternate implementation of the calculation println doMyCalc(10,20) { a, b -> a - b } println doMyCalc(10,20) { a, b -> a + b } println doMyCalc(10,20) { a, b -> b - a } println doMyCalc(10,20) { a, b -> a ^ b } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  • 7.
    What's Missing? Optional?  ReturnStatements  last value in a method is an implicit return value  Parameter and Return Types  duck typing is supported  types are checked/enforced when present  Classes  still available for organization purposes  not required as an entry point  Compilation  groovyc can be used to compile groovy to class files  groovy executable provides dynamic runtime
  • 8.
    Java from Groovy publicclass Contact { private String name, email, phone; public String getName() { return name; } public void setName(String name){ this.name = name; } public String getEmail() { return email; } public void setEmail(String email){ this.email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } } Contact contact = new Contact(name: 'Wes', email: 'wes@mail.com', Phone : '123-123-1234'); println "Contact ${contact.name} at ${contact.email} or ${contact.phone}" 1 2 3 4 5 Contact.java useContact.groovy
  • 9.
    Groovy from Java importgroovy.lang.*; public class GroovyEmbedded { static String formatContact(Contact contact, String format) { Binding binding = new Binding(); binding.setVariable("c", contact); GroovyShell shell = new GroovyShell(binding); return shell.evaluate("c.identity { "" + format + "" }").toString(); } public static void main(String[] args) throws Exception { Contact contact = new Contact(); contact.setName("Wes"); contact.setPhone("123-123-1234"); contact.setEmail("wes@mail.com"); String format1 = "Name: ${name}, Email: ${email}, Phone: ${phone}"; String format2 = "${name} - p: ${phone} e: ${email}"; System.out.println("Format #1: " + formatContact(contact,format1)); System.out.println("Format #2: " + formatContact(contact,format2)); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
  • 10.
    Metaprogramming  Add behavior dynamicallyat runtime  Change existing behavior at runtime  Handle missing behavior gracefully  Invoke behavior dynamically What if the rules only applied when we wanted?
  • 11.
    MetaClass def testString1 ="This is a test string." def testString2 = "This is ALSO a TEST string." println "Test #1a: ${testString1}" // This is a test string. println "Test #2a: ${testString2}" // This is ALSO a TEST string. try { testString1.doTestThing() } catch(Exception ex) { println "Error: ${ex.class.name}" // groovy.lang.MissingMethodException } println "Implement doTestThing at the class level" String.metaClass.doTestThing = { delegate - " test" } println "Test #1b: ${testString1.doTestThing()}" // This is a string. println "Test #2b: ${testString2.doTestThing()}" // This is ALSO a TEST string. println "Implement doTestThing at the instance level" testString2.metaClass.doTestThing = { delegate - ~"(?i) test" } println "Test #1c: ${testString1.doTestThing()}" // This is a string. println "Test #2c: ${testString2.doTestThing()}" // This is ALSO a string. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  • 12.
    Intercepting Method Calls voidmethodMissing(String methodName, args)  Allows implementation to be provided when method not present Object getProperty(String propertyName)  Allows interception of get methods when Groovy's object.property syntax used void setProperty(String propertyName, Object newValue)  Allows interception of set methods when Groovy's object.property syntax used Object invokeMethod(String methodName, args)  Same as methodMissing when methodMissing not present  Allows interception of all methods when GroovyInterceptable is implemented
  • 13.
    Method Missing class LikesItAll { deflikesSports() { println "I play and watch lots of sports!" } def likesMovies() { println "I see movies all the time!" } def everythingElse = { println "I really like ${it} too!" } def methodMissing(String name, args) { if(name =~ /^likes/) everythingElse(name-"likes") else println "What?" } } LikesItAll dude = new LikesItAll() dude.likesMovies() dude.likesBooks() dude.likesSports() dude.dislikesSomething() dude.likesCars() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Results: I see movies all the time! I really like Books too! I play and watch lots of sports! What? I really like Cars too!
  • 14.
    GroovyInterceptable class Bank implementsGroovyInterceptable { def balance=0 def deposit(amt) { balance += amt } def withdraw(amt) { balance -= amt } def invokeMethod(String name, args) { def metaMethod = metaClass.getMetaMethod(name, args) if(metaMethod) { metaClass.print "Performing ${name} of $${args[0]}" return metaMethod.invoke(this, args) } metaClass.println "This bank does not support ${name}ing" } } Bank bank = new Bank() bank.deposit 100 bank.withdraw 20 bank.borrow 30 println "Balance is: $${bank.balance}" Results: Performing deposit of $100 Performing withdraw of $20 This bank does not support borrowing Balance is: $80 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
  • 15.
  • 16.
    Gotcha! Polymorphism Differences publicclass Poly { void test() { System.out.println("No params"); } void test(Object test) { System.out.println("Object1"); } } public class PolyExt extends Poly { void test(Object test) { System.out.println("Object2"); } void test(String test) { System.out.println("String"); } public static void main(String[] args) { String a = "test"; Object b = a; Poly poly = new PolyExt(); poly.test(); poly.test(a); ((PolyExt)poly).test(a); poly.test(b); ((PolyExt)poly).test(b); } } GROOVY No params String String String String JAVA No params Object2 String Object2 Object2
  • 17.
    Gotcha! GString's LazyEvaluation name = 'Bob' howToContact = new StringBuffer("1231231234") contactInfo = "${-> new Date()} - ${-> name} at ${howToContact}n" contactList = contactInfo println contactList Thread.sleep 30000 // 30 seconds howToContact.append " & 2342342345" println contactList Thread.sleep 30000 // 30 seconds name = "Sue" howToContact = howToContact.reverse() contactList += contactInfo println contactList Results: Fri Nov 05 19:12:56 MDT 2010 - Bob at 1231231234 Fri Nov 05 19:13:26 MDT 2010 - Bob at 1231231234 & 2342342345 Fri Nov 05 19:13:56 MDT 2010 - Sue at 5432432432 & 4321321321 Fri Nov 05 19:13:56 MDT 2010 - Sue at 5432432432 & 4321321321 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  • 18.
    Further GROOVY Reading Language: http://groovy.codehaus.org/ Web Dev:http://www.grails.org/ Embeded: http://soapui.org/userguide/functional/groovystep.html DSL: http://www.slideshare.net/glaforge/practical-groovy-dsl wes-williams.blogspot.com