From Event to Action: Accelerate Your Decision Making with Real-Time Automation
Groovy unleashed
1. Welcome To… Groovy!
– The Catalyst Language for Programmers
Presentation By
-Isuru Samaraweera
2. Agenda
• Introduction to Groovy
• Key Features
• Closures
• Operator Overloading
• Array Slicing and looping
• Collections
• Dynamic Methods/Mixins and Properties
• Regular Expressions
• File IO
• Database Operations
3. What is Groovy?
• Java-like scripting language for the JVM
• Dynamic Language
• Inspired by Ruby,Python,SmallTalk and Perl
• Open Source language
– Apache2.0 license
– dev@groovy.apache.org
– users@groovy.apache.org
• Seamless integration with Java
– Follow the mantra…Java is Groovy,Groovy is Java
• Web Application Development
– Groovelets,GSP,Grapplet
• Sole alternative dynamic language for the JVM fully supporting frameworks like Spring, Hibernate
– Grails
– Coding by Convention
• Mobile Application Support
• Official web site http://www.groovy-lang.org/
4. Installation and Configuration
• Prerequisites
– JDK1.4 or higher installed and system path should point to %JAVA_HOME%/bin
• Download Groovy distribution from http://www.groovy-lang.org/download.html
• Unzip the groovy archive
– Set the GROOVY_HOME environment variables.
– Add %GROOVY_HOME%bin to your system path
– Try opening groovyConsole.bat
• Eclipse Plug-in
– https://github.com/groovy/groovy-eclipse/wiki
• IntelliJ Idea Plug-in-Community edition
– http://www.jetbrains.net
6. Java Vs. Groovy No of line Comparison
• Java Code
for (String item : new String [] {"Rod", "Carlos", "Chris"})
{
if (item.length() <= 4)
{
System.out.println(item);
}
}
• Groovy Code
["Rod", "Carlos", "Chris"].findAll{it.size() <= 4}.each{println it}
7. /*A Typical Groovy Class*/
class Customer
{
// properties
Integer id
String name
Date dob
// sample code
static void main(args)
{
def customer = new Customer(id:1, name:"Gromit", dob:new Date())
println("Hello ${customer.getName()}")
customer.setName(“James”)
println("Hello ${customer.getName()}")
}
}
Java Vs. Groovy No of line Comparison
8. Closures
• A block of code that can access variables in the scope where it is declared or
outside
• Higher order functions
• A closure will have a default parameter named it if you do not define one
def x = { println it }
• And here's how you call it (two options):
x('Hello, world!')
x.call('Hello, world')
9. Closure Arguments(Typed or Untyped)
• Untyped Arguments
def isList = { i -> i instanceof List }
if (isList([]))
{
println "This is a List“
}
• Typed Arguments
def prefix = {
String s ->
while (s.length() < 17)
{
s = "0$s"
}
s // return keyword is not required
}
def id = prefix "1234" // parentheses are not required
10. Closures as arguments and Recursion
• Closures can be passed as arguments
• Consider the each() method on java.util.Map:
System.properties.each { println it.key }
• Recursion
• lambda is annonymous
def fac =
{
int i -> i == 1 ? 1 : i * call(i - 1)
}
println fac(10)
11. Currying
• Currying is a programming technique that transforms a function into
another while fixing one or more input values
def multiply = { x, y -> return x * y } // closure
def triple = multiply.curry(3)
// triple = { y -> return 3 * y }
def quadruple = multiply.curry(4)
// quadruple = { y -> return 4 * y }
def p = triple.call(4) // explicit call
def q = quadruple(5) // implicit call
println "p: ${p}" // p is 12
println "q: ${q}" // q is 20
12. Currying contd..
def lSubtract = { x, y -> return x - y }
def rSubtract = { y, x -> return x - y }
def dec = rSubtract.curry(1)
// dec = { x -> return x - 1 }
def cent = lSubtract.curry(100)
// cent = { y -> return 100 - y }
def p = dec.call(5) // explicit call
def q = cent(25) // implicit call
println "p: ${p}" // p is 4
println "q: ${q}" // q is 75
13. Variable Arguments
int sum(int... someInts)
{
//ellipsis notation
def total = 0
for (int i = 0; i < someInts.size(); i++)
total += someInts[i]
return total
}
assert sum(1) == 1
assert sum(1, 2) == 3
14. Operator Overloading ! - 1
it does it by following a naming convention for methods.
Operation Method
a+b a.Plus(b)
a-b a.minus(b)
a*b a.multiply(b)
a**b a.power(b)
a/b a.div(b)
a % b a.mod(b)
a | b a.or(b)
a & b a.and(b)
15. Operator Overloading ! - 2
a ^ b a.xor(b)
a++ or ++a a.next()
a-- or --a a.previous()
a[b] a.getAt(b)
a[b] = c a.putAt(b, c)
a << b a.leftShift(b)
a >> b a.rightShift(b)
switch(a) { case(b) : } b.isCase(a)
~a a.bitwiseNegate()
-a a.negative()
+a a.positive()
16. Operator Overloading ! - 3
text = "Programing" - "ing" + "er"
assert "Programer" == text
list = [1,2,3]
list += [4,5,6]
assert [1,2,3,4,5,6] == list
list << 7 // list.leftShift(7) -> list.add(7)
assert [1,2,3,4,5,6,7] == list
s = "A" * 5
assert s == "AAAAA“
s = "ABCDE"
assert "BC" == s[1..2]
s.getAt([1..2]); ranged operation
assert "C" == s[2] // s.getAt(2) -> s.charAt(2)
17. Looping
• General for loop and while loop
• Classical for loop
def x = 0
for ( i in 0..9 ) //RANGE
{ x += i }
assert x == 45 // iterate over a list
• Iterate over a list
x = 0
for ( i in [0, 1, 2, 3, 4] ) //LIST
{ x += i }
assert x == 10
19. Elvis Operator
• Elvis Operator alternative to ternary operator
//traditional ternary operator
String name = “Sam";
String displayName = name != null ? name : "Unknown";
//elvis operator
String name = “Sam"
String displayName = name ? name : "Unknown"
//eliminate DRY
String name = “Sam"
String displayName = name ?: "Unknown"
20. Agenda
• Introduction to Groovy
• Key Features
• Closures
• Operator Overloading
• Array Slicing and looping
• Collections
• Dynamic Methods and Properties
• Regular Expressions
• File IO
• Database Operations
• Unified Field and Programming Languages
22. Lists
• Lists have been implemented in Groovy as ArrayLists which store elements of type Object.
• Create a list def myList = [1,2,3.6,-9.01,“hello”,“a string”, new Date()]
• Create an empty list myList = [ ]
• Size of a list myList.size()
• Accessing an element of list myList.get( 1 ) or myList[ 1 ] are same.
• Add elements to a list myList << 0 << -1 << ‘hello’
• Add a list to a list myList << [1,2] << someOtherList
• New ways of adding elements to a list myList += 3; myList += [3,5]
• Flattening a list of lists
[ 1, [2,3,[4,5],6], 7, [8,9] ].flatten() == [1, 2, 3, 4, 5, 6, 7, 8, 9]
• Nulls are inserted if required.
list = ['a', 'b', 'z', 'e', 'u', 'v', 'g']
list[8] = 'x'
list == ['a', 'b', 'z', 'e', 'u', 'v', 'g', null, 'x']
23. Lists contd..
• Closures as a way to do common updates
myList = myList.collect { it * 2 }
• Closures as a way of operations
[1, 2, 3].find{ it > 1 } == 2
[1, 2, 3].findAll{ it > 1 } == [2, 3]
Similar keywords are every and any.
• To add all elements in a list [1,2,3,4,5,6].sum() == 21
• Other operations available on a list :
– Find max. and min. elements
– Use –(minus) sign to remove elements from a list.
– Stack operations (push, pop) can be done on a list.
– Count method gives the number of elements equal to the one passed in method call.
– Sort method will sort a list in ascending order.
Reverse will reverse a list.
24. Range
• Ranges allow you to create a list of sequential values.
• Ranges defined with the .. notation are inclusive, that is they contain both values.
• def myRange = 5..8 This will make a range 5,6,7,8
• A range can be in both orders, increasing, as well as decreasing.
• They are accessed same as Lists.
example: myRange += 4..-3 makes myRange as 5,6,7,8,4,3,2,1,0,-1,-2,-3
• Even characters can be added to a range. myRange += ‘a’..’d’
• And same strings with different last characters can be added myRange += ‘AAB’..’AAD’.
• They find their usage in loops. Example for(count in start..end)
• They can be used in switch statements too. Example
switch(value){
case 1..10: --------;
case 11..25: -------;
default: -------;}
• They can be used to create Lists
[ 1, *3..5, 7, *9..<12 ] == [1,3,4,5,7,9,10,11]
25. Maps
• Maps have been implemented in Groovy as LinkedhashMap which store elements of type
key:value. By default, Groovy takes key as a String.
• Example: def myMap = [name:“Alan", likes:“bread", id:1234]
• Empty map is defined as myMap = [ : ]
• Values in a map are accessed using key, as usually.
• Maps also act like beans so you can use the property notation to get/set items inside the
Map provided that the keys are Strings which are valid Groovy identifiers. Ex:
def map = [name:"Gromit", likes:"cheese", id:1234]
assert map.name == "Gromit"
assert map.id == 1234
• Similar operations as that on Lists can be performed on Maps too.
26. Expandos (The Dynamic Object)
• An Expando is like a Map in Groovy or an object in Javascript that do not have to have their
properties in advance.
• It allows you to create dynamic objects by making use of Groovy's closure mechanisms.
• An Expando is different from a map in that you can provide synthetic methods that you can
call on the object.
• Example:
def player = new Expando()
player.name = "Dierk"
player.greeting = { "Hello, my name is $name" }
println player.greeting()
player.name = "Jochen"
println player.greeting()
Note: The closure has access to the properties assigned to the Expando, even though these
values may change over time.
27. Agenda
• Introduction to Groovy
• Key Features
• Closures
• Operator Overloading
• Array Slicing and looping
• Collections
• Dynamic Methods/Mixins and Properties
• Regular Expressions
• File IO
• Database Operations
• Unified Field and Programming Languages
28. Groovy Way of Handling…
– Dynamic Methods and Properties
– Regular Expressions
– File I/O
– Database Connectivity
29. Dynamic Method Invocation
• You can invoke a method even if you don't know the method name until it is
invoked:
class Dog
{ def bark() { println "woof!" }
def sit() { println "(sitting)" }
def jump() { println "boing!" }
}
def doAction( animal, action ){
animal."$action"() //action name is passed at invocation
}
def rex = new Dog()
doAction( rex, "bark" ) //prints 'woof!‘
doAction( rex, "jump" ) //prints 'boing!'
30. Dynamic Methods/mixins
george = new Wombat()
george.mixin("say") { something-> println something }
george.say("Hello, world!")
george = new Wombat().mixin(FighterType)
william = new Wombat()
georage.getFighter() // returns
william.getFighter()//error
31. Dynamic Properties
• You can also override property access using the getProperty and setProperty
property access hooks, Dynamically
class Expandable
{
def storage = [:] //Empty MAP
def getProperty(String name) { storage[name] } //AUTO RETURN
void setProperty(String name, value) { storage[name] = value }
}
def e = new Expandable()
e.foo = "bar"
println e.foo //OUTPUT: bar
32. Regular Expressions
• Groovy supports regular expressions natively using the ~"pattern" expression,
• Which compiles a Java Pattern object from the given pattern string.
• Groovy also supports the =~ (create Matcher) and ==~ (matches regex) operators.
• Packages that are used in Groovy for RegEx
– import java.util.regex.Matcher
– import java.util.regex.Pattern
• Regular expression support is imported from Java.
def pattern = ~/foo/
assert pattern instanceof Pattern
assert pattern.matcher("foo").matches()
def matcher = "cheesecheese" =~ /cheese/
assert matcher instanceof Matcher
answer = matcher.replaceAll("edam")
def cheese = ("cheesecheese" =~ /cheese/).replaceFirst("nice") assert
cheese == "nicecheese"
33. Works with standard Java Reader/Writer , InputStream/OutputStream ,File and URL classes
Message Passing … Using Closures
new File("foo.txt").eachLine { line -> println(line) }
Don’t Bother about Resource Closing Mechanism Groovy Methods will handle it.
def fields = ["a":"1", "b":"2", "c":"3"]
new File("Foo.txt").withWriter { out -> fields.each() { key, value ->
out.writeLine("${key}=${value}") }
}
- No Reader / Writer Object Handling
Handle the resource for you via a closure - which will automatically close down any resource
if an exception occurs
- No Data Piping (Stream Management)
- No Exception Handling
The eachLine() method ensures that the file resource is correctly closed. Similarly if an
exception occurs while reading, the resource will be closed too.
File Input / Output
34. Executing External Processes
Groovy provides a simple way to execute command line processes.
def process = "ls -l".execute()
process.in.eachLine { line -> println line }
====================
Process p = "cmd /c dir".execute()
println "${p.text}“
====================
def initialSize = 4096
def outStream = new ByteArrayOutputStream(initialSize) //STREAMS
def errStream = new ByteArrayOutputStream(initialSize)
def proc = "ls.exe".execute()
proc.consumeProcessOutput(outStream, errStream)
proc.waitFor() println 'out:n' + outStream println 'err:n' + errStream
35. SQL can be more Groovy - 1
• You can perform queries and SQL statements, passing in variables easily with
proper handling of statements, connections and exception handling.
import groovy.sql.Sql
def foo = 'cake‘
def database = Sql.newInstance( "jdbc:mysql://localhost:3306/mydb",
"user",
"pswd",
"com.mysql.jdbc.Driver")
database.eachRow("select * from FOOD where type=${foo}“)
{ println "Smith likes ${it.name}" }
Thanks to closures.
36. SQL can be more Groovy - 2
• You can perform queries and SQL statements, passing in variables easily with
proper handling of statements, connections and exception handling.
import groovy.sql.Sql
def foo = 'cheese‘
def database = Sql.newInstance( "jdbc:mysql://localhost:3306/mydb",
"user",
"pswd",
"com.mysql.jdbc.Driver")
def answer = 0
sql.eachRow("select count(*) from FOOD where type=${foo}")
{ row -> answer = row[0] }
Println (“Our menu has $answer dishes to choose from!)
Thanks to closures.
37. SQL can be more Groovy - 3
• You can perform queries and SQL statements, passing in variables easily with
proper handling of statements, connections and exception handling.
import groovy.sql.Sql
def foo = 'cheese‘
def database = Sql.newInstance( "jdbc:mysql://localhost:3306/mydb",
"user",
"pswd",
"com.mysql.jdbc.Driver")
def food = database.dataSet('FOOD')
def cheese = food.findAll { it.type == 'cheese' }
cheese.each { println “${it.name} will be delicious" }
Thanks to closures.
38. Why to Thank Closures ?
A typical JDBC Program should have these Steps
1. Loading a database driver
2. Creating a oracle JDBC Connection
3. Creating a JDBC Statement object
4. Executing a SQL statement with the Statement object, and returning a jdbc resultSet.
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//or any other driver
} catch(Exception x){
System.out.println( "Unable to load the driver class!" );
}
try {
Connection con = DriverManager.getConnection(url, userid, password);
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
String createString="create table Employees(“+"Employee_ID INTEGER,”+"Name VARCHAR(30))";
try {
stmt = con.createStatement();
stmt.executeUpdate(createString);
stmt.close();
con.close();
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
39. Reduced code noise in Groovy
-Simple code is beautiful code
Groovy Will Handle all those common tasks for you,
- including Exception Handling, Connection - ResultSet Closing, etc..
import groovy.sql.Sql
class GroovySqlExample1
{
static void main(args)
{
database = Sql.newInstance("jdbc:mysql://localhost:3306/words",
"words", "words", "org.gjt.mm.mysql.Driver")
database.eachRow("select * from word")
{ row | println row.word_id + " " + row.spelling } //CLOSURE
wid = 999
spelling = "Nefarious"
pospeech = "Adjective"
database.execute("insert into word (word_id, spelling, part_of_speech)
values (${wid}, ${spelling}, ${pospeech})")
val = database.execute("select * from word where word_id = ?", [5])
//Negetive Indexing
sql.eachRow("select * from word")
{ grs | println "-1 = " + grs.getAt(-1) //prints part_of_speech
println "2 = " + grs.getAt(2) //prints part_of_speech }
}
}