www.flickr.com
|
Thursday, May 10, 2007
JavaOne 2007 Day 3 - My groovy redux
I still remember the first time I was exposed to groovy. James Strachan stood on stage (I think it was 2003 or 2004) and with his very smooth and soothing voice dazzled everyone in the room with this new language that allowed you to get more done with less. In the period since that time groovy has had its ups and downs but lately it really seems to be coming of age since there's finally a release (1.0 was released in January of this year), there's the grails project, and the popularity of ruby and rails has at least raised the awareness of dynamic scripting languages to new levels. For java developers that haven't made the venture outside the confines of Java it appears now is as good a time as any to put a new weapon to your arsenal. Groovy is certainly a natural choice for many java developers that don't wish to learn a new API with ruby though there's quite a bit of the groovy API that extends java that appears to be at least partially inspired by ruby.
Today I attended Rod Cope's "Advanced Groovy" talk. So while I'd never written a line of groovy until today (I copied Rod's numerous examples for today's post) I felt up to the task of attending an "advanced" talk based on the level of most talks at JavaOne. It turned out I was right, as Rod spewed out code example after code example I felt quite at home with a few minor syntax differences that I will say are less "beautiful" than ruby but that's probably because I'm used to ruby now. But you could take any ruby developer, give them groovy and they would have no problems working with it based on the examples I saw in today's talk.
Let's look at some of the advanced features from Rod's examples:
Safe navigation - Allows safe traversal without getting NPEs and avoid doing null checks. When you call the property with "?" if anything in the chain is null the result is null.
Expando - a dynamic etch-a-sketch object that you can add methods and properties to on the fly
Template engines - A closure as template engine
He also mentioned the existence of a GStringTemplateEngine. groovy.text.GStringTemplateEngine
Default parameters - just like ruby it supports default param values in method signatures
Single object iteration/identity. You can iterate over any object whether a collection or not. If it's not a collection you'll get back the object itself once in the block.
With identity it's a way to have an implicit object set in the block. I'm not really clear on why this is such a big win at the moment.
Currying - This is the process of using functions to manufacture other functions.
First a groovy example:
Now let's see the same thing in ruby for folks that have never heard of currying before. The following code isn't mine it's taken from the the ruby quiz site.
Dynamic language extensions - mixins. Of all the things that were shown the implementation of mixins made me cringe because you have to create a new class and then pollute your implementation code that uses the mixin with the "use" method. The ruby way is seamless and much more elegant to me but the groovy way is arguably a little safer because it's so explicit and you'd always know that you're dealing with mixed in implementation. Still, I don't like it :-)
Method aliasing
After these simple examples Rod broke into a couple more complex examples that really showed the power of groovy and to me rivals DHH's video that made RoR so attractive to so many people.
Demo of xml-rpc
First start up a server
Then create and run the client code
Going back to the server let's add a new method to our service:
Back to client, let's call it:
No reboots were needed in the above example code which is impressive
Next up was the ActiveX demo using http://danadler.com/jacob (Java API to COM)
This opens excel on your machine
Creates a new workbook in your opened excel instance
Selects the first sheet in the workbook
He then proceeded to add data to the sheet programmatically, create charts and add formulas (this code isn't complete as I wasn't able to keep up with this section)
After that he demonstrated the SwingBuilder and updated the excel spreadsheet via that UI
The above code shows the swing GUI and when you click the button the chart is updated both in excel and in the button that you've just clicked. The speed was fast with no noticeable slowness.
A couple final examples that were thrown in at the end
It's great to see groovy finally coming into its own. Performance isn't bad and will only get better with optimization and for java devs that want to get into scripting or a ruby dev that needs to work in java and can't use jruby groovy's a really comfortable choice for all but the most religious ruby zealots :-)
Today I attended Rod Cope's "Advanced Groovy" talk. So while I'd never written a line of groovy until today (I copied Rod's numerous examples for today's post) I felt up to the task of attending an "advanced" talk based on the level of most talks at JavaOne. It turned out I was right, as Rod spewed out code example after code example I felt quite at home with a few minor syntax differences that I will say are less "beautiful" than ruby but that's probably because I'm used to ruby now. But you could take any ruby developer, give them groovy and they would have no problems working with it based on the examples I saw in today's talk.
Let's look at some of the advanced features from Rod's examples:
Safe navigation - Allows safe traversal without getting NPEs and avoid doing null checks. When you call the property with "?" if anything in the chain is null the result is null.
people = ['rod' : ['age' : 36, 'height' : "5'9"]]
people.rod.age
-> 36
people?.joe?.age
-> null
Expando - a dynamic etch-a-sketch object that you can add methods and properties to on the fly
import groovy.util.Expando
rod = new Expando(name: 'Rod', age: 36)
rod.drinkWater = {num -> num.times { println "yummy" }}
print rod.age
-> 36
rod.drinkwater(2)
-> yummy
-> yummy
Template engines - A closure as template engine
t = {p -> "${p.name} is ${p.age()}" }
rod = new Person(name: 'Rod', age: 36)
println t(rod)
He also mentioned the existence of a GStringTemplateEngine. groovy.text.GStringTemplateEngine
Default parameters - just like ruby it supports default param values in method signatures
Single object iteration/identity. You can iterate over any object whether a collection or not. If it's not a collection you'll get back the object itself once in the block.
currentCustomer.employees['joe'].manager.secretary.each { it.bonus = 1000 }
With identity it's a way to have an implicit object set in the block. I'm not really clear on why this is such a big win at the moment.
currentCustomer.employees['joe'].manager.secretary.identity {
println "salary = $salary" } <- same as saying secretary.salary
Currying - This is the process of using functions to manufacture other functions.
First a groovy example:
c1 = {a, b -> a + b}
c2 = c1.curry("Hi ") result = c2 = {b -> "Hi " + b}
Now let's see the same thing in ruby for folks that have never heard of currying before. The following code isn't mine it's taken from the the ruby quiz site.
require "curry"
scale = lambda { |size, object| object * size }
puts "3 scaleded to a size of 10 is #{scale[10, 3]}." # 30
puts
# curry some functions
double = scale.curry(2)
triple = scale.curry(3)
halve = scale.curry(0.5)
puts "4 doubled is #{double[4]}." # 8
puts "1 tripled is #{triple[1]}." # 3
puts "Half of 10 is #{halve[10]}." # 5.0
Dynamic language extensions - mixins. Of all the things that were shown the implementation of mixins made me cringe because you have to create a new class and then pollute your implementation code that uses the mixin with the "use" method. The ruby way is seamless and much more elegant to me but the groovy way is arguably a little safer because it's so explicit and you'd always know that you're dealing with mixed in implementation. Still, I don't like it :-)
class PropertiesHelper
{
public static List getProperyNames(Object bean)
{
def methodNames = bean.class.methods.name.findAll { it.startsWith('get') }
def goodNames = methodNames - ['getMetaClass', 'getClass', 'getProperty']
def propertyNames = goodNames.sort().collect {
// "getName" -> "n" + "ame" -> "name"
it[3].toLowerCase() + it[4..-1]
}
return propertyNames
}
}
rod = new Person(firstName: 'Rod', lastName: 'Cope')
use(PropertiesHelper) {
for (prop in rod.propertyNames) {
println "${prop} = ${rod[prop]}"
}
}
-> firstName = Rod
-> lastName = Cope
Method aliasing
def p = System.out.&println
p('hi')
def doSomething(method) { method('dog') }
doSomething(p)
-> dog
After these simple examples Rod broke into a couple more complex examples that really showed the power of groovy and to me rivals DHH's video that made RoR so attractive to so many people.
Demo of xml-rpc
First start up a server
import groovy.net.xmlrpc.*
server = new XMLRPCServer()
server.testme = {name -> "$name is cool"}
server.startServer(new ServerSocket(9047))
go
Then create and run the client code
import groovy.net.xmlrpc.*
server = new XMLRPCServerProxy('http://localhost:9047)
println server.testme("Groovy")
go
Groovy is cool
Going back to the server let's add a new method to our service:
server.multiply = {it * 7}
go
Back to client, let's call it:
println server.multiply(3)
go
21
No reboots were needed in the above example code which is impressive
Next up was the ActiveX demo using http://danadler.com/jacob (Java API to COM)
import org.codehaus.groovy.scriptom.ActiveXProxy
excel = new ActiveXProxy("Excel.Application")
excel.visible = true
go
This opens excel on your machine
book = excel.workbooks.add()
go
Creates a new workbook in your opened excel instance
sheet = book.activesheet
go
Selects the first sheet in the workbook
He then proceeded to add data to the sheet programmatically, create charts and add formulas (this code isn't complete as I wasn't able to keep up with this section)
a1 = sheet.range('a1'); a2 = sheet.range('a2')
co = sheet.chartobjects.add(50,50,400,200)
go
After that he demonstrated the SwingBuilder and updated the excel spreadsheet via that UI
swing = new groovy.swing.SwingBuilder()
mybutton = swing.button(text: 'click me')
mybutton.actionPerformed = {
a1.value = new Random().nextFloat() * 500
chart.export('graphname.gif)
mybutton.icon = new javax.swing.ImageIcon('graphname.gif')
}
frame = swing.Frame(title: "The frame")
frame.show()
The above code shows the swing GUI and when you click the button the chart is updated both in excel and in the button that you've just clicked. The speed was fast with no noticeable slowness.
A couple final examples that were thrown in at the end
"cmd /c dir".execute().text -> execute a system process
Thread.start { any code } -> firing off a thread, this is just like ruby
It's great to see groovy finally coming into its own. Performance isn't bad and will only get better with optimization and for java devs that want to get into scripting or a ruby dev that needs to work in java and can't use jruby groovy's a really comfortable choice for all but the most religious ruby zealots :-)
Post a Comment