Pages

Thursday, July 2, 2009

Groovy Impressions

Groovy is a superset of the Java programming language with dynamic language constructs. Here are my notes on Groovy.
1. Java is Groovy
Every Java sentence is a valid Groovy sentence but not the other way around. Which means you can use every Java library out there with Groovy classes. Infact Groovy classes in the end compile into Java code.
2. Loose Syntax
No need for a main method. No more a class should be defined in its own named file requirement. Following is a complete "Hello, World!" program for Groovy:
println "Hello, World!"
We don't need the System.out.... or the semicolon ending commands. Though we could have used them also.
3. Integrated Template Engine
It has a embeded templating engine which does all sort of things. And here is the "Hello, World" of templating :
world = "World"
println "Hello, ${world}!"
4. Constructers, Getters and Setters
Getters and Setters are automatically generated for properties of the class and there is a simple property initialization mechanism. And the example :
new Salutor(hello:true,who:"World")
5. Safe Navigation & Elvis Operators
With Java Often we may have to these null checks :
if(state != null &&
state.getTransitions() != null &&
state.getTransitions().size() > 0) {
states = state.getTransitions().values();
...
With groovy we can navigate with the '?' operator safely with out cluttered if checks :
states = state?.transitions?.values()
And the Elvis operator is used for assigning default values other than null :
name = user.name ?: "Anonymous"
As far as I know these will be available in Java 7.
6. Closures
The folowing closure (the thing between curly brackets) finds even integers inside the int array.
ints?.find {n -> n % 2 == 0}
Closures are passable function block. You can also check out the commons-collections api to see how similar code could be written in Java.
7. Meta Programming
e = new Euro()
prop="value";
op="plus";
e."${prop}"= 5;
e."${prop}"=e."${prop}"."${op}"(1)
println e
The above example succesfully computes to 6.
8. Build DSL's
Using the MetaClass api you can create simple inline DSL's. Here is a example whit euros:
package tr.mca.dsl;
import static tr.mca.dsl.MoneyDomain.*;

println "1 euro + 2 euro :" + money {
1.euro + 2.euro
}
Here whit in the money block we create "new Euro(3)" but we are doing it in a more brain friendly way.
There is two ways I know to achive that:
a. DelegatingMetaClass
DelegatingMetaClass helps us to intercept the method and property accesses. Here is the extended version I crated for money example :
public class MoneyDelegatingMetaClass extends DelegatingMetaClass {

MoneyDelegatingMetaClass(Class delegate) {
super(delegate);
}

public Object getProperty(Object obj, String property) {
if (isDynamicProperty(property)) {
return new Euro(obj);
}
return super.getProperty(obj, property);
}

private boolean isDynamicProperty(String property) {
return "euro".equals(property) || "€".equals(property)
}

}
We are able to intercept the "euro" property access and upon access we create the Euro object. Here is the code that activates this interceptor for a given code block :
class MoneyDomain {

static Object money(Closure closure) {
def orgMetaClass = InvokerHelper.metaRegistry.getMetaClass(Integer.class)
MoneyDelegatingMetaClass myMetaClass = new MoneyDelegatingMetaClass(Integer.class)
InvokerHelper.metaRegistry.setMetaClass(Integer.class, myMetaClass)
try {
return closure.call()
} finally {
InvokerHelper.metaRegistry.setMetaClass(Integer.class, orgMetaClass)
}
}

}
InvokerHelper.metaRegistry.setMetaClass call lets us register and unregister when we are done.
b. ProxyMetaClass
Another way of doing is using the ProxyMetaClass api. We again wrote a similar interceptor :
class MoneyDomainInterceptor implements PropertyAccessInterceptor {

public Object beforeGet(Object obj, String property) {
if ("euro".equals(property)) {
return new Euro(obj);
} else {
return obj.getProperties().get(property);
}
}

public void beforeSet(Object obj, String property, Object newValue) {
}
}
This time we implemented the PropertyAccessInterceptor. And here is how we gonna use it :
class MoneyDomain {

def static proxy = ProxyMetaClass.getInstance(Integer.class);
static {
proxy.interceptor = new MoneyDomainInterceptor();
}

static void moneyProxy(closure) {
proxy.use(closure);
}
}
}
And thats my short journey of the Groovy language.

No comments:

Post a Comment