Loading...

Monday, November 30, 2009

Groovy Goodness: Use a Category and Get a Return Value

With the use() method in Groovy we execute a closure in the scope of a Category or list of Categories. The last statement of the closure is the return value for the use() method. So we can get a result from the use() method and use it in our program.

class StringCategory {
    static String groovy(String self) {
        self + ' Yeah man.'
    }
}

def returnedValue = use(StringCategory) {
    def s = 'A simple String.'
    s.groovy()
}

assert 'A simple String. Yeah man.' == returnedValue

Sunday, November 29, 2009

Groovy Goodness: A Bit of metaClass DSL

When we add behaviour to classes with the metaClass property we can use a simple DSL. We pass a closure to the metaClass method where we group the definitions for the new behaviour. If we add multiple methods with the same name we must use <<, otherwise we can just set a closure to the method name. To add a static method we use 'static' and define the methods.

String.metaClass {
    or << { String s -> delegate.plus(' or ').plus(s) }
    or << { List l -> delegate.findAll("(${l.join('|')})") }
    and { String s -> delegate.plus(' and ').plus(s) }
    'static' {
        groovy { 'Yeah man!' }
    }
}

assert 'Groovy or Java?' == ("Groovy" | "Java?")
assert ['o', 'o', 'y'] == ("Groovy" | ['o', 'y'])
assert 'Groovy and Java!' == ("Groovy" & "Java!")

assert 'Yeah man!' == String.groovy()

Saturday, November 28, 2009

Groovy Goodness: Closure Arguments

If we define a closure in Groovy we can define our own arguments or rely on the default it for a single argument closure. The it argument is available if we don't define any named arguments ourselves. We can also create a closure and define it to have no arguments even not the it argument.

// Closure with default 'it' argument.
def defaultIt = { it - 1 }
assert 'Groovy String with .' == defaultIt('Groovy String with 1.')
assert 41 == defaultIt(42)

// Closure with named argument.
def namedArg = { value -> value * 2 }
assert 'Groovy Groovy ' == namedArg('Groovy ')
assert 84 == namedArg(42)

// Closure with multiple named arguments.
def moreArgs = { a, b -> a + b }
assert 'Groovy Java' == moreArgs('Groovy ', 'Java')
assert 44 == moreArgs(42, 2)

// Closure without arguments, even no 'it'.
def noArgs = {-> 'Groovy closure without arguments' }
assert 'Groovy closure without arguments' == noArgs()

Friday, November 27, 2009

Groovy Goodness: Intercept Methods with Interceptors

We can intercept method invocations in Groovy in several ways. One way is to write an implementation for the Interceptor interface. Next we create a ProxyMetaClass for the class we want the methods to be intercepted for and assign the interceptor to the ProxyMetaClass. With the use() method we can run our methods and the interceptor is used for each method invocation.

class HelloInterceptor implements Interceptor {
    boolean invokeMethod = true

    boolean doInvoke() {
        invokeMethod
    }
    
    Object beforeInvoke(Object obj, String name, Object[] args) {
        // We don't want the shout() method to be executed.
        if (name == 'shout') {
            invokeMethod = false
        }
    }
    
    Object afterInvoke(Object obj, String name, Object[] args, Object result) {
        if (name == 'shout') {
            invokeMethod = true
            // Set an alternate result for the shout() method.
            result = "sssshhh... You don't have to shout."
        }
        result
    }
}

class Hello {
    String say() { "Hello Groovy" }
    String shout() { "HELLO GROOVY" }
}

// Create ProxyMetaClass and assign interceptor.
def proxy = ProxyMetaClass.getInstance(Hello)
def interceptor = new HelloInterceptor()
proxy.interceptor = interceptor

// Invoke Hello methods in use block so methods are intercepted.
proxy.use {
    def h = new Hello()
    assert 'Hello Groovy' == h.say()
    assert "sssshhh... You don't have to shout." == h.shout()
}

Thursday, November 26, 2009

Groovy Goodness: Compiled Groovy Script is a Java Class

A Groovy script has no class declaration or main() method, but if we compile the script class to Java bytecode, it has. This means we can write a Groovy script, compile the source and use the resulting class in Java.

// File: Sample.groovy
package com.mrhaki.blog

println 'Hello from Groovy'

Next we can compile this script and use Java to invoke the class. We must make sure we add the Groovy library to the classpath, but that is all.

$ groovyc Sample.groovy
$ java -cp .:$GROOVY_HOME/embeddable/groovy-all-1.6.5.jar com.mrhaki.blog.Sample
Hello from Groovy

Wednesday, November 25, 2009

Groovy Goodness: Simple Evaluation of Groovy Expressions in Java

We can run Groovy code from Java code in several ways. A very simple and easy way is to use the Eval class. The Eval class has five methods to execute simple Groovy expressions with zero to three arguments. All methods are static and the Groovy expression must be a String.

package com.mrhaki.blog;

import java.util.*;
import groovy.util.Eval;
import junit.framework.*;
import static junit.framework.Assert.*;

public class EvalGroovyTest extends TestCase {
    public static void main(String[] args) {        
        assertEquals(
            "Invoke Eval.me() without arguments",
            "Hello from Groovy", 
            Eval.me("def language = 'Groovy'; \"Hello from $language\";").toString()
        );
        
        final Map values = new HashMap();
        values.put("name", "mrhaki");
        values.put("lang", "Groovy");
        String expression = "\"Hello $params.name from $params.lang\"";
        assertEquals(
            "Invoke Eval.me() with 2 arguments: first is name of object used by expression, second is object self",
            "Hello mrhaki from Groovy",
            Eval.me("params", values, expression).toString()
        );
            
        assertTrue(
            "Invoke Eval.x() where the passed arguments name is x in the expression",
            (Boolean) Eval.x("mrhaki", "x.any { it =~ 'a' }")
        );
        
        assertTrue(
            "Invoke Eval.xy() where the passed arguments name is x and y in the expression",
            (Boolean) Eval.xy("mrhaki", "h", "x.any { it =~ y }")
        );
        
        expression = "x.\"$z\"() * y";  // Unreadable expression to return x with the method z applied y times.
        assertEquals(
            "Invoke Eval.xyz() where the passed arguments name is x, y and z in the expression",
            "GROOVYGROOVY", 
            Eval.xyz("groovy", 2, "toUpperCase", expression).toString()
        );
    }
}

Tuesday, November 24, 2009

Me on Github

Today I created my Github account and started uploading the sources for the Groovy Goodness posts. I will add more sources in the next couple of days/weeks.

I am also thinking about creating a "Groovy Goodness sample viewer". With this viewer we can look at the sample and run it immediatelly in the GroovyConsole or shell.

Groovy Goodness: Setting a Closure's Delegate

Closures are reusable code blocks in Groovy. The code of the closure is executed against the delegate of the closure. By default the owner of the closure is the same as the delegate, but we can change this. We can define which object is the delegate for a closure, so we can change the object the closure is executed for.

// Simple class.
class Post {
    int count
    def info() { "This is Groovy Goodness post #$count!" }
}

// Script variable and method.
count = 0
def info() {
    "Count value is $count."
}

// Closure to increment a count variable and invoke a info() method.
def printInfo = { 
    count++
    info() 
}

assert "Count value is 1." == printInfo() // Delegate is by default set to owner, so the script in this case.

printInfo.resolveStrategy = Closure.DELEGATE_FIRST  // Change closure resolver so first the delegate is used.
printInfo.delegate = new Post(count: 100)  // Set delegate to Post object.
assert "This is Groovy Goodness post #101!" == printInfo()

Monday, November 23, 2009

Groovy Goodness: Create Dynamic Methods

In Groovy we can write classes and write an implementation for methods we don't even know exist. We must implement the method methodMissing() which is invoked when other methods cannot be found. Because methodMissing() is invoked each time another method cannot be found, it can be expensive, but we can use the metaClass property to cache the new method. Next time the cached version is used.

class LanguageList {
    def list = ['Java', 'Groovy', 'Scala']

    // Set metaClass property to ExpandoMetaClass instance, so we 
    // can add dynamic methods.
    LanguageList() {
        def mc = new ExpandoMetaClass(LanguageList, false, true)
        mc.initialize()
        this.metaClass = mc
    }
    
    def methodMissing(String name, args) {
        // Intercept method that starts with find.
        if (name.startsWith("find")) {
            def result = list.find { it == name[4..-1] }
            // Add new method to class with metaClass.
            this.metaClass."$name" = {-> result + "[cache]" }
            result
        } else {
            throw new MissingMethodException(name, this.class, args)
        }
    }
}

def languages = new LanguageList()
assert 'Groovy' == languages.findGroovy()
assert 'Scala' == languages.findScala()
assert 'Java' == languages.findJava()
assert !languages.findRuby()

assert 'Groovy[cache]' == languages.findGroovy()
assert 'Scala[cache]' == languages.findScala()
assert 'Java[cache]' == languages.findJava()

Sunday, November 22, 2009

Groovy Goodness: Finding Files with FileNameFinder

The groovy.util package contains the FileNameFinder and FileNameByRegExFinder classes. We can use the FileNameFinder classe to search recursively for files in a directory with ANT fileset pattern conventions. With the FileNameByRegExFinder we use regular expressions to define the file patterns.

// Suppose we have a environment variable GROOVY_HOME pointing to the Groovy installation dir.
def groovyHome = System.getenv('GROOVY_HOME')

def txtFiles = new FileNameFinder().getFileNames(groovyHome, '**/*.txt' /* includes */, '**/*.doc **/*.pdf' /* excludes */)
assert new File(groovyHome, 'README.txt').absolutePath in txtFiles

def icoFiles = new FileNameByRegexFinder().getFileNames(groovyHome, /.*\.ico/)
assert new File(groovyHome, 'html/groovy-jdk/groovy.ico').absolutePath in icoFiles

Saturday, November 21, 2009

Gradle Goodness: Display Dependencies for a Gradle Build

We can see the dependencies defined in our project by using the -n or --dependencies argument. We get an overview of the dependencies for each configuration in our Gradle build.

// File: build.gradle
usePlugin 'java'

repositories { 
    mavenCentral() 
}

dependencies {
    compile 'org.springframework:spring-webmvc:2.5.6'
}
$ gradle -n
:reportTask

------------------------------------------------------------
Root Project
------------------------------------------------------------
archives - Configuration for the default artifacts.
compile - Classpath for compiling the sources.
|-----org.springframework:spring-webmvc:2.5.6:default
default - Configuration the default artifacts and its dependencies.
|-----org.springframework:spring-webmvc:2.5.6:default
      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |-----org.springframework:spring-web:2.5.6:master,runtime,compile
      |      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-context-support:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
runtime - Classpath for running the compiled sources.
|-----org.springframework:spring-webmvc:2.5.6:default
      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-context-support:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |-----org.springframework:spring-web:2.5.6:master,runtime,compile
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
testCompile - Classpath for compiling the test sources.
|-----org.springframework:spring-webmvc:2.5.6:default
testRuntime - Classpath for running the test sources.
|-----org.springframework:spring-webmvc:2.5.6:default
      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |-----org.springframework:spring-context-support:2.5.6:compile,runtime,master
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |-----org.springframework:spring-web:2.5.6:master,runtime,compile
      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-context:2.5.6:compile,runtime,master
      |      |      |-----org.springframework:spring-beans:2.5.6:master,compile,runtime
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----aopalliance:aopalliance:1.0:runtime,master,compile
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----org.springframework:spring-core:2.5.6:compile,runtime,master
      |      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime
      |      |-----commons-logging:commons-logging:1.1.1:master,compile,runtime

BUILD SUCCESSFUL

Total time: 7.359 secs

Another way is to add the plugin project-reports to our project. We now get the the task dependencyReport in our project. When we run $ gradle dependencyReport we get a text file build/reports/project/dependencies.txt with the same overview of the dependencies.

Groovy Goodness: Are You In? (Membership Operator)

Groovy brings some new operators and keywords to the table. One of them is the in keyword or the so-called membership operator. The operator can be called in a conditional context, for example we can use in to test for the existince of a member in a collection. We can write our own implementation by implementing the isCase() method of our class. Or the operator is called in an iterative context, for example in a for loop. Then the iterator() is called. We can write our own implementation for the iterator() to implement in when called in a iterative context.

// *** Conditional context
def list = ['Groovy', 'Java']
assert 'Groovy' in list
assert !('Scala' in list)

// Write our own in implementation.
class MyObject {
    String value
    boolean isCase(ch) { 
        value.contains(ch) 
    }
}
def myObj = new MyObject(value: 'Groovy')
assert 'oo' in myObj
assert !('oo' in myObj.value)  // isCase for String invokes equals.
assert 'Groovy' in myObj
assert 'Groovy' in myObj.value
assert !('a' in myObj)

// *** Iterative context
// Use in in a for loop.
def result = ''
for (lang in list ) {
    result += lang
}
assert 'GroovyJava' == result

class Counter {
    Integer maxValue
    private Integer counter = 0
    Iterator iterator() {
        [hasNext: { counter <= maxValue }, 
         next: { counter++ }] as Iterator
    }
}
def counter = new Counter(maxValue: 10)
result = '' 
for (c in counter) {
    result += c
}
assert result == '012345678910'

Friday, November 20, 2009

Create a Grails App in the Current Directory

The Grails create-app command accepts several arguments besides the application name. We can create the Grails directory structure in the current directory by using the --inplace argument. We can set the initial application version with the --appVersion argument. So to create a new Grails application with the name blog-app in the current directory with an initial application version of 1.0 we invoke the following command:

$ grails create-app --inplace --appVersion=1.0 blog-app

Groovy Goodness: Add Methods Dynamically to Classes with ExpandoMetaClass

We can add new behaviour, like methods, to classes in Groovy dynamically. So this means a method is not added to the class definition in the source code, but to the class definition while an application is already running. Groovy adds a metaClass property to all classes for this purpose. The type of this property is ExpandoMetaClass. We can assign methods (also static), properties, constructors to the metaClass property and the defined behaviour is added dynamically to the class definition. After we have added our behaviour we can create a new instance of the class and invoke the methods, constructors and access the properties just like we are used to do.

// We add the method rightShift to the List class. 
// The implementation is simply calling the remove method of List with
// the provided argument.
List.metaClass.rightShift {
    delegate.remove it
}

def list = ['one', 'two', 'three', 'four']
assert 4 == list.size()

list.rightShift 'two'
assert 3 == list.size()
assert ['one', 'three', 'four'] == list

// Operator overloading in action: rightShift is >>
list >> 'one'
assert 2 == list.size()
assert ['three', 'four'] == list


// We can also add behaviour to a specific instance instead of class.
// Notice we use the instance list instead of class List to assign 
// method groovy to metaClass property.
list.metaClass.groovy {
    delegate.collect { it + ' groovy' }
}

assert ['three groovy', 'four groovy'] == list.groovy()

def newList = ['a', 'b']
try {
    newList.groovy()  // groovy method was added to list instance not List class.
    assert false
} catch (e) {
    assert e instanceof MissingMethodException
}

Thursday, November 19, 2009

Gradle Goodness: Deploying Our Gradle Plugin to a Maven Repository

We have created a Gradle plugin, but now we want to share it with others. Suppose we have a central Maven repository within our company than we can use this repository to distribute our plugin among other developers. We don't need to change the code of our plugin, but we do need to move the code into a new project. We created the plugin in the buildSrc directory and that means it is only available for that project. We create a new directory and move the src directory from the buildSrc directory to the new project directory. Next we create a build.gradle file.

$ mkdir makedirs-plugin
$ cd makedirs-plugin
$ cp -R <old-dir>/buildSrc/src .
$ touch build.gradle

We open build.gradle in a text editor. Our plugin code is now nothing more or less than Groovy code, so we need the Groovy plugin for our project. The classes must be compiled into class files, but we have dependencies on the Gradle API for our plugin. When the files where in the buildSrc directory all was well, because Gradle would make sure the classpath was correct. But now we are a normal Groovy project, so we must define the location of the Gradle API class files ourselves. We add the lib directory of our Gradle installation directory to the groovy configuration to resolve the dependencies.

Next we define the location of our company Maven repository with the uploadArchives() method. A special repositories.mavenDeployer() method gives us the possibility to define the location. The uploadArchives task uses this location to deploy the JAR with all classes to the repository.

// File: build.gradle
usePlugin 'groovy'  // Need it to compile plugin classes.
usePlugin 'maven' // Need it to deploy to Maven repository.

// Project configuration is used for Maven deploy:
version = '1.0'
group = 'com.mrhaki.gradle.plugins'

uploadArchives {
    repositories.mavenDeployer {
        repository url: 'file:///shared/repos/m2/repository'
    }
}

dependencies {
    // Add all JAR files in the lib directory of theGradle installation directory
    // to the groovy configuration (is also used by compile configuration)
    groovy fileTree(dir: new File(gradle.gradleHomeDir, 'lib'), includes: ['*.jar'])
}

// Make sure all code is compiled, tested and checked before uploadArchives.
uploadArchives.dependsOn ':build'

We run the build to deploy the JAR file to the repository: $ gradle uploadArchives.

Okay we have deployed the plugin to the repository, it is time to use it in another project. We create a new directory and create the build.gradle file and open it in a text editor. We must use the usePlugin() method to enable the plugin, but the com.mrhaki.blog.gradle.MakeDirsPlugin class is not yet on the classpath. We need to define the build script dependency on the plugin with the buildscript() method. This will make sure any dependency needed by the build process itself can be resolved.

// File: build.gradle
buildscript {
    repositories {
        mavenRepo urls: 'file:///shared/repos/m2/repository'
    }
    dependencies {
        classpath 'com.mrhaki.gradle.plugins:makedirs-plugin:1.0'
    }
}

usePlugin com.mrhaki.blog.gradle.MakeDirsPlugin

Gradle Goodness: Use Our Local Maven Repo with Gradle

Usually when we work on a software component or library we package the files into a JAR file. If we use Maven we run the $ mvn install command to copy the JAR artifact into our local Maven repository, so we can use the component or library in other project on our local machine. We can do the same thing with Gradle, we run $ gradle install to copy the artifact into the local Maven repository. The only thing we need to do is use the Maven plugin in our project. Gradle knows the location of our Maven repository, because Gradle uses the Maven ANT tasks to implement the install task.

To use the local Maven repository in our Gradle projects for dependency resolution we must do something extra. The local Maven repository is not added to the repositories list of our project automatically, we must do this ourselves. In our build.gradle file we define a new Maven repository and point it to our local Maven repository. Now Gradle uses this repository to look for dependencies just like Maven does.

// File: build.gradle
usePlugin 'java'  // Java plugin to build our JAR artifact.
usePlugin 'maven'  // Maven plugin to install artifact in local Maven repo.

def localMavenRepo = 'file://' + new File(System.getProperty('user.home'), '.m2/repository').absolutePath
repositories {
    // Use local Maven repo location. We don't need this if we only want to install
    // an artifact, but we do need it if we want to use dependencies from the local
    // repository.
    mavenRepo urls: localMavenRepo
}

// Project configuration:
version = '1.0-SNAPSHOT'
group = 'com.mrhaki.gradle'

// The following line is not necessary. Default the install tasks depends on the
// jar task, but this means no tests and checks are executed when we use the
// install task. The following line makes the install tasks depend on the build task
// and now all tests and checks are done before install is executed.
install.dependsOn ':build'

To deploy our artifact to the Maven local repository we run the install command. If we use the -i argument to get extra information we see at the end where Gradle is installing the JAR file.

$ gradle install -i
...
Tasks to be executed: [task: ':compileJava', task: ':processResources', task: ':classes', task: ':jar', task: ':assemble', task: ':compileTestJava', task: ':processTestResources', task: ':testClasses', task: ':test', task: ':check', task: ':build', task: ':install']
...
[INFO] Installing .../build/libs/project-1.0-SNAPSHOT.jar to .../.m2/repository/com/mrhaki/gradle/project/1.0-SNAPSHOT/project-1.0-SNAPSHOT.jar

BUILD SUCCESSFUL

Total time: 2.625 secs

Groovy Goodness: Running a Unit Test

If we create a unit test class extending GroovyTestCase we can run the test with the groovy command. This is a very easy way to execute a test.

class SimpleTest extends GroovyTestCase {
    void testGroovy() {
        assertEquals 'Run with groovy', 10, 5 + 5
    }
}

We can run this test with the following command:

$ groovy SimpleTest.groovy
.
Time: 0.125

OK (1 test)

Start or Don't Start Web Browser When Running a Grails App in NetBeans

NetBeans opens a web browser with the index page of our Grails application if we run the application. If we don't want this behaviour or if we turned it off, but want to turn it on again, we right-click on the project in the Project window and select Properties. We click on the General Settings node and we check or uncheck Display Browser on Run.

We close the dialog window by clicking on the OK button. Next time when we run the Grails application the web browser will be shown or not depending on the choice we made in the dialog window.

Wednesday, November 18, 2009

Change Grails Environment in NetBeans

In NetBeans we can change the Grails environment to development, test or production for an application. We right-click on the Grails project in the Project window and select Properties. In the dialog window we select General Settings and on the right we see a combobox for Active Grails Environment. Here we can select an environment. If we defined our environment it is not shown in this list, so we can only select one of the three default environments.

We click on the OK button to activate our choice for the application.

Change Server Port for Grails App in NetBeans

We can change the port number for the server running our Grails application. We right-click on the project in the Project window and select Properties. We get a dialog window and select the General Settings node. We set the server port in the field Server Port. The default value is 8080, but we can change it to another value if we want.

We click on the OK button to close the dialog window. Next time we run our Grails application the server is started with the new server port.

Gradle Goodness: Creating a Gradle Plugin

A plugin for Gradle provides reusable build logic packaged as a unit. For example the Java plugin is already provided with Gradle and adds several tasks for working with Java code to a Gradle project. In this post we write our own plugin to add a custom task and a new method to a project. We create a new task mkdirs to create the source directories defined by plugins for a project. The code to create the directories is inspired by the Gradle Cookbook. The task itself looks for a property basePackageDir and apppends it to the source directory names. Finally we add the method makeDirs() to the Gradle project.

How do we achieve this? First we start with a new project and create a buildSrc directory. The buildSrc directory contains the plugin code. Gradle will automatically compile the classes and add it to the project's classpath. To create a new Gradle plugin we define a class that implements the Plugin interface. The interface only contains one method, use(), so that is simple. In the use() method we have access to the project object and plugins, so we can do a lot of things. For our sample we only have to create a new task and add it to the project:

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/MakeDirsPlugin.groovy
package com.mrhaki.gradle

import org.gradle.api.*
import org.gradle.api.plugins.*

class MakeDirsPlugin implements Plugin {

    void use(final Project project, ProjectPluginsContainer plugins) {
        // Closure to create a directory.
        def createDirs = {
            it.mkdirs()
        }

        // Create new task 'mkdirs' and add it to the project.
        project.task('mkdirs') << {
            if (plugins.hasPlugin('java')) {
                project.sourceSets.all.java.srcDirs*.each createDirs
                project.sourceSets.all.resources.srcDirs*.each createDirs
            }
            
            if (plugins.hasPlugin('groovy')) {
                project.sourceSets.all.groovy.srcDirs*.each createDirs
            }
            
            if (plugins.hasPlugin('scala')) {
                project.sourceSets.all.scala.srcDirs*.each createDirs
            }
            
            if (plugins.hasPlugin('war')) {
                createDirs project.webAppDir
            }
        }
        // Assign a description to the task.
        project.tasks.mkdirs.description = "Create source directories."
    }
    
}

And that is all we need to do (for now). We create a build.gradle file to use our plugin:

// File: build.gradle
usePlugin(com.mrhaki.gradle.MakeDirsPlugin)

When we ask Gradle for all available tasks we get our mkdirs task in the results:

$ gradle -t -q
--------------------------------------------------------------
Root Project
--------------------------------------------------------------
:mkdirs - Create source directories.

We can stop now, but we also wanted to use a basePackageDir property and add the method makeDirs() to our project from the plugin. To add properties and methods by a plugin Gradle supports conventions. We create a new convention object with properties and methods and assign it to the project plugins map. Now all properties and methods from the convention object can directly be invoked and accessed from the build script. So we start by creating a convention object, which is just a plain GroovyBean class:

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/MakeDirsPluginConvention.groovy
package com.mrhaki.gradle

import org.gradle.api.*

class MakeDirsPluginConvention {
    String basePackageDir = ''  // Property to hold base package directory name.
    Project project
    
    MakeDirsPluginConvention(Project project) {
        this.project = project 
    }
    
    // Method to create a new directory from the root of the project.
    // (Inspired by mkdir in Java plugin)
    File makeDirs(String dirName) {
        if (!dirName) {
            throw new InvalidUserDataException('You must specify a directory name')
        }
        if (!project) {
            throw new InvalidUserDataException('You must specify a project')
        }
        def newDir = project.file(dirName)
        newDir.mkdirs()
        newDir
    }
}

We change the code for the plugin to use the convention class:

// File: buildSrc/src/main/groovy/com/mrhaki/gradle/MakeDirsPlugin.groovy
package com.mrhaki.gradle

import org.gradle.api.*
import org.gradle.api.plugins.*

class MakeDirsPlugin implements Plugin {

    void use(final Project project, ProjectPluginsContainer plugins) {
        // Assign new convention object to project.
        // makedirs is a key for the plugins map. We can choose the name
        // ourselves here.
        project.convention.plugins.makedirs = new MakeDirsPluginConvention(project)
    
        // Closure to create a directory.
        def createDirs = {
            // Use basePackageDir property.
            def newDir = new File(it, project.convention.plugins.makedirs.basePackageDir)
            newDir.mkdirs()
        }

        // Create new task 'mkdirs' and add it to the project.
        project.task('mkdirs') << {
            if (plugins.hasPlugin('java')) {
                project.sourceSets.all.java.srcDirs*.each createDirs
                project.sourceSets.all.resources.srcDirs*.each createDirs
            }
            
            if (plugins.hasPlugin('groovy')) {
                project.sourceSets.all.groovy.srcDirs*.each createDirs
            }
            
            if (plugins.hasPlugin('scala')) {
                project.sourceSets.all.scala.srcDirs*.each createDirs
            }
            
            if (plugins.hasPlugin('war')) {
                createDirs project.webAppDir
            }
        }
        // Assign a description to the task.
        project.tasks.mkdirs.description = "Create source directories."
    }
    
}

We change our build script to show the usage of our plugin:

// File: build.gradle
usePlugin(com.mrhaki.gradle.MakeDirsPlugin)
usePlugin('war')  // Extra plugin so the task mkdirs from the plugin can do something.

basePackageDir = 'com/mrhaki'  // Property from plugin convention object.
makeDirs 'src/main/config' // Method from plugin convention object.

We run the build with $ gradle mkdirs and all source directories are created including src/main/config. For example we now have the directory src/main/java/com/mrhaki in our project.

Because we created our plugin in the buildSrc directory the plugin is only available for this project. In a next blog post we see how we can reuse our plugin in other projects. We will package the code into a JAR file and upload to a repository. Other projects can define a dependency for our plugin in the repository and use it in the build process.

Groovy Goodness: Testing for Expected Exceptions

If we create a unit test class and extend from GroovyTestCase we can use the very useful shoulFail() methods. The method provides a very concise way to define that a piece of code should throw an exception. We can specify the type of exception we expect to be thrown or leave it out.

class URLTest extends GroovyTestCase {
    void testNoProtocol() {
        // Test for exception.
        shouldFail {
            def url = new URL('')
        }

        // Test for exception and check resulting message.
        def msg = shouldFail {
            def url =  new URL('')
        }
        assert 'no protocol: ' == msg  // We can use the 'normal' assert.

        // Test for specific exception and resulting message.
        msg = shouldFail(MalformedURLException) {
            def url = new URL('')
        }
        assertEquals 'no protocol: ', msg  // We can use the JUnit assertEquals.
        
        // Test for exception higher up in the hierarchy.
        shouldFail(IOException) {
            def url = new URL('')
        }
    }
}

Tuesday, November 17, 2009

Gradle Goodness: Get Notified About Finished Build with Snarl

We can add a listener to the Gradle build process to get informed about certain events during the build process. We must implement the BuildListener interface and add it to a Gradle instance. One of the methods is the buildFinished() method. We write an implementation for this method to display the build result as a Snarl notification (Snarl is a Windows equivalent of Growl in OSX). The BuildAdapter class provides an empty implementation for the BuildListener interface and is a good starting point for our implementation.

We can add the code to our build.gradle file for a project. But we want to create the listener and use it for all our Gradle builds. We create the file init.gradle and place it in the ~/.gradle directory. Gradle will invoke this script always when we invoke a Gradle build, so every project we build with Gradle will use this code.

// File: ~/.gradle/init.gradle
class SnarlNotifyListener extends BuildAdapter {
    void buildFinished(BuildResult result) {
        if (result.failure) {
            snarlNotify 'Gradle build failure', result.failure.message, true
        } else {
            snarlNotify 'Gradle build finished', 'Build successful'
        }
    }

    void snarlNotify(title, message = 'No message', sticky = false) {
        def cmd = [
            '<Path to Snarl_CMD.exe>',  // Replace with your local path.
            'snShowMessage',
            sticky ? '0' : '10',  // If non-sticky display for 10 seconds.
            title,
            message,
            '<gradle_home>/docs/groovydoc/groovy.ico'  // Nice little icon, use local path.
        ]
        cmd.execute()
    }    
}

def listener = new SnarlNotifyListener()
gradle.addBuildListener listener

Now we can run a Gradle build and we get nice notifications when the build is finished:

Installing Grails Plugins in NetBeans

If we have a Grails project in NetBeans we can add plugins by right-clicking on the project in the Project window and selecting Grails Plugins....

NetBeans opens a dialog window with two tabs. The first tab, Installed, contains the plugins already installed in our application. The second tab, New plugins, shows all available plugins from the Grails plugin repository.

We can search in the list by typing the first characters of the name of the plugin. To install a plugin we must select the name and click on the Install button. If we have a plugin on our local file system we can use the Browse... button to locate the plugin and install it. In our sample we install the joda-time plugin:

After installation we return to the Installed tab and see the joda-time plugin is added to the list.

Now we can close the dialog window and return to our code. The Joda Time classes are now available in our code:

Gradle Goodness: Shortcut Notation for Dependencies

In a Gradle build script we define dependencies with the dependencies method. We can use a map notation or the short string notation. The string notation is the following format: group:name:version.

dependencies {
    compile group: 'commons-lang', name: 'commons-lang', version: '2.4'  // Map notation.
    compile(
        [group: 'commons-lang', name: 'commons-lang', version: '2.4'],
        [group: 'commons-io', name: 'commons-io', version: '1.4']
    )  // Multiple map notation.
    compile 'commons-lang:commons-lang:2.4', 'commons-io:commons-io:1.4'  // String notation.
}

Gradle Goodness: Setting Default Tasks

To run a task with Gradle we must specify the task name as an argument. If we don't specify a task name we get an error that Gradle cannot determine a task to execute. We can define the tasks that need to be executed when we don't specify a task name explicitly. In a Gradle build script we invoke the method defaultTasks and pass the name or names of the tasks as arguments to the method. These tasks are executed when we run Gradle without any task name. When we run $ gradle -t or $ gradle --tasks we can see which tasks are the default tasks.

// File: build.gradle
usePlugin 'java'

defaultTasks 'clean', 'build'  // Run tasks clean and build if no task is specified.
$ gradle --tasks | grep "Default Tasks"
Default Tasks: clean, build

Gradle Goodness: Using Properties for Multiple Environments or Profiles

A Gradle build script is a Groovy script, and this means we can use all classes available to Groovy in our Gradle build scripts. In this post we use the ConfigSlurper to read in properties for our project. The ConfigSlurper supports environments where we can define values for properties per environment. Suppose we have a dev, test and prod environment than we can define different values for the same property per environment. We can also override a default value in the environments section.

In our Gradle build script we look for a property env. We can pass a value for the env property to the build with the -P or --project-prop argument when we run Gradle. If the property is available we use the value to read in the properties for that environment. If the env property is not available we assume the default dev environment. Finally we assign the Config object (with all properties) returned by the ConfigSlurper to the project property config. In the Gradle build script we can access the properties with dotted notation: config.propName.

// File: build.gradle
loadConfiguration()

task printProps << {
    println "serverName:  $config.serverName"
    println "mail.server: $config.mail.server"
    println "mail.port:   $config.mail.port"
}

def loadConfiguration() {
    def environment = hasProperty('env') ? env : 'dev'
    setProperty 'environment', environment
    println "Environment is set to $environment"
    
    def configFile = file('config.groovy')
    def config = new ConfigSlurper(environment).parse(configFile.toURL())
    setProperty 'config', config
}
// File: config.groovy
mail {
    server = 'localhost'
    port = 25
}

environments {
    dev {
        serverName = 'http://localhost:9090'        
    }
    
    test {
        serverName = 'http://testserver'
        mail {
            server = 'mail.testserver'
        }
    }
    
    prod {
        serverName = 'http://www.mrhaki.com'
        mail {
            port = 552
            server = 'mail.host.com'
        }
    }
}

We run Gradle with different values for the env property to see the values of the properties:

$ gradle -q printProps
Environment is set to dev
serverName:  http://localhost:9090
mail.server: localhost
mail.port:   25

$ gradle -q -Penv=dev printProps
Environment is set to dev
serverName:  http://localhost:9090
mail.server: localhost
mail.port:   25

$ gradle -q -Penv=test printProps
Environment is set to test
serverName:  http://testserver
mail.server: mail.testserver
mail.port:   25

$ gradle -q -Penv=prod printProps
Environment is set to prod
serverName:  http://www.mrhaki.com
mail.server: mail.host.com
mail.port:   552

Groovy Goodness: Running Groovy Scripts in Java with GroovyClassLoader

With the GroovyClassLoader we can load Groovy scripts and run them in Java code. First we must create a new GroovyClassLoader and then parse a Groovy script. The script can be in a file, string or inputstream. Once the script is parsed we have a Class and we can make a new instance of this class. We cast the instance to a GroovyObject instance, so we can use the invokeMethod() method to invoke methods in our Groovy script.

package com.mrhaki.blog;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

import java.io.File;
import java.io.IOException;

public class GroovyRun {
    public static void main(final String[] args) throws IllegalAccessException, InstantiationException, IOException {
        // Create GroovyClassLoader.
        final GroovyClassLoader classLoader = new GroovyClassLoader();
        
        // Create a String with Groovy code.
        final StringBuilder groovyScript = new StringBuilder();
        groovyScript.append("class Sample {");
        groovyScript.append("  String sayIt(name) { \"Groovy says: Cool $name!\" }");
        groovyScript.append("}");
        
        // Load string as Groovy script class.
        Class groovy = classLoader.parseClass(groovyScript.toString());
        GroovyObject groovyObj = (GroovyObject) groovy.newInstance();
        String output = groovyObj.invokeMethod("sayIt", new Object[] { "mrhaki" });
        assert "Groovy says: Cool mrhaki!".equals(output);
        
        // Load Groovy script file.
        groovy = classLoader.parseClass(new File("SampleScript.groovy"));
        groovyObj = (GroovyObject) groovy.newInstance();
        output = groovyObj.invokeMethod("scriptSays", new Object[] { "mrhaki", new Integer(2) });
        assert "Hello mrhaki, from Groovy. Hello mrhaki, from Groovy".equals(output);
    }
}
// File: SampleScript.groovy
class SampleScript {
    String scriptSays(name, num) { 
        "Hello $name, from Groovy. " * num
    }
}

Monday, November 16, 2009

Create New Grails Files in NetBeans

To add a new file to our Grails application in NetBeans we simply select File | New (Ctrl+N in Windows) while we have a Grails application open. NetBeans opens a new dialog and if we select the Groovy node we get a list of Grails filetypes we can select. NetBeans provides templates for these types or uses the Grails commands to create a new file to get a good start. For most filetypes we only have to specify the name and package, but for more general filetypes we can also define the location in the Grails directory structure.

We can also right-click on a node in our Grails application in the Project window. NetBeans has a context-sentive pop-up menu and if we select New... we see the most relevant Grails types for that node at the top. So if we right-click on the Domain Classes node we get the Grails Domain Class... option at the top.

Create a Grails Project in NetBeans

To get started with Grails in NetBeans is easy once we have added the Groovy and Grails plugin. We select File | New Project and Groovy from the Categories. Now we select Grails Application and press the Next button:

On the next screen of the wizard we type the name of our Grails project and the location. And if we didn't define a Grails home directory for NetBeans yet we can do it by clicking on the Configure Grails... button.

If we clicked on the Configure Grails... button we get the following dialog to enter the directory of our Grails installation. We can also set the Grails installation directory if we go to Tools | Options | Miscellaneous | Groovy:

After we have set the Grails installation directory we close the dialog window and finish the New project wizard. NetBeans creates the new project and in our Project window we see the layout of our Grails application. We are now ready to add files to the project and start developing.

Running Grails Commands in NetBeans

NetBeans has some great support for developing Grails applications. We can run an arbitrary Grails command by right-clicking on the project and select Run Grails Command... from the pop-up menu. NetBeans opens a dialog where we can type in the command we want to use with parameters if needed.

To get quick access to this dialog we can assign our own shortcut key combination to the command. We go to Tools | Options | Keymap. In the Search field we type run grails and we get the Run Grails Command... in the Actions list. We click on the ... button to assign our own shortcut key combination (I choose Ctrl+Shift+G).

We close the Options window and now we can press our shorcut key combination and we can run Grails commands immediately.

Add Groovy and Grails Support to NetBeans

To enhance NetBeans with Groovy and Grails support we add the Groovy and Grails plugin to the IDE. We select Tools | Plugins and go to the Available Plugins tab. We type Grails in the Search field to look for the plugin. We select the plugin and press the Install button.

NetBeans downloads the plugin and installs it. After the installation we can restart the IDE to enable the plugin. As a last step we configure the plugin by specifying the Grails installation directory. We go to Tools | Options | Miscellaneous | Groovy and set the Grails home directory in Grails Home:

NetBeans is now setup to create Grails applications.

Gradle Goodness: Display Gradle Information in the Build

In a Gradle build script we can access properties from Gradle and the project itself. To access the Gradle object we use the gradle property. Properties of the Project instance can be accessed directly in our script. We can use this information to display an information message each time we run the build script. Let's make it look like something we also see when we run Grails:

// File: build.gradle
println """\
Welcome to Gradle $gradle.gradleVersion - http://www.gradle.org
Gradle home is set to: $gradle.gradleHomeDir
Gradle user directory is set to: $gradle.gradleUserHomeDir

Base directory: $projectDir
Running script ${relativePath(buildFile)}
"""

If we run the gradle we get to see the information:

$ gradle -t
Welcome to Gradle 0.8 - http://www.gradle.org
Gradle home is set to: D:\java\gradle\gradle-0.8
Gradle user directory is set to: C:\Documents and Settings\mrhaki\.gradle

Base directory is: D:\mrhaki\data\projects\mrhaki.com\blog\posts\samples\info
Running script build.gradle

:reportTask

---------------------------------------------------------
Root Project
---------------------------------------------------------
No tasks

BUILD SUCCESSFUL

Total time: 1.484 secs

Groovy Goodness: Source of Groovy GDK

Groovy adds a lot of useful methods to standard Java classes. The source of this code can be found in org.codehaus.groovy.runtime.DefaultGroovyMethods, org.codehaus.groovy.runtime.DefaultGroovyStaticMethods and org.codehaus.groovy.vmplugin.v5.PluginDefaultGroovyMethods. These are a nice read to see how the magic is happening.

Sunday, November 15, 2009

Groovy Goodness: Raising the Power of Numbers

The Groovy GDK adds the power() method to the Number class. The power() method has a shortcut operator: **.

assert 9 == 3**2
assert 27 == 3.power(3)
assert 16 == Math.pow(2, 4)  // Java way.

Saturday, November 14, 2009

Groovy Goodness: Run Code at a Specified Time

In Groovy we can use the method runAfter() to run a closure after a specified delay in milliseconds. This method is added by Groovy GDK to the Timer class.

// File: timer.groovy
def timer = new Timer()
def task = timer.runAfter(10000) {
    println "Actually executed at ${new Date()}."
}
println "Current date is ${new Date()}. Task is executed at ${new Date(task.scheduledExecutionTime())}."

If we run this script we get the following output (of course depending on the time the script is executed):

$ groovy timer.groovy
Current date is Thu Nov 12 6:51:41 CET 2009. Task is executed at Thu Nov 12 6:51:51 CET 2009.
Actually executed at Thu Nov 12 6:51:51 CET 2009.

As a bonus we add a runEvery() method to the Timer class with categories:

// File: newtimer.groovy
class GroovyTimerTask extends TimerTask {
    Closure closure
    void run() {
        closure()
    }
}

class TimerMethods {
    static TimerTask runEvery(Timer timer, long delay, long period, Closure codeToRun) {
        TimerTask task = new GroovyTimerTask(closure: codeToRun)
        timer.schedule task, delay, period
        task
    }
}

use (TimerMethods) {
    def timer = new Timer()
    def task = timer.runEvery(1000, 5000) {
        println "Task executed at ${new Date()}."
    }
    println "Current date is ${new Date()}."
}
$ groovy newtimer.groovy
Current date is Thu Nov 12 7:03:29 CET 2009.
Task executed at Thu Nov 12 7:03:30 CET 2009.
Task executed at Thu Nov 12 7:03:35 CET 2009.
Task executed at Thu Nov 12 7:03:40 CET 2009.
Task executed at Thu Nov 12 7:03:45 CET 2009.
Task executed at Thu Nov 12 7:03:50 CET 2009.
...

Friday, November 13, 2009

Groovy Goodness: Convert String to Boolean

Groovy adds the toBoolean() method to the String class. If the value of the string is true, 1 or y the result is true, otherwise it is false.

assert "y".toBoolean()
assert 'TRUE'.toBoolean()
assert '  trUe  '.toBoolean()
assert " y".toBoolean()
assert "1".toBoolean()

assert ! 'other'.toBoolean()
assert ! '0'.toBoolean()
assert ! 'no'.toBoolean()
assert ! '  FalSe'.toBoolean()

Thursday, November 12, 2009

Gradle Goodness: A Groovy Multi-project with Gradle

Gradle is a flexible build system that uses Groovy for build scripts. In this post we create a very simple application demonstrating a multi-project build. We create a Groovy web application with very simple domain, dataaccess, services and web projects. The sample is not to demonstrate Groovy but to show the multi-project build support in Gradle.

We start by creating a new application directory app and create two files settings.gradle and build.gradle:

$ mkdir app
$ cd app
$ touch settings.gradle
$ touch build.gradle

We open the file settings.gradle in a text editor. With the include method we define the subprojects for the application:

include 'domain', 'dataaccess', 'services', 'web'

Next we open build.gradle in the text editor. This build file is our main build file for the application. We can define all settings for the subprojects in this file:

subprojects {
    usePlugin 'groovy'
    version = '1.0.0-SNAPSHOT'
    group = 'com.mrhaki.blog'
    configurations.compile.transitive = true  // Make sure transitive project dependencies are resolved.
    
    repositories {
        mavenCentral()
    }
    
    dependencies {
        groovy 'org.codehaus.groovy:groovy:1.6.5'
    }
    
    task initProject(description: 'Initialize project') << { task ->
        task.project.sourceSets.all.groovy.srcDirs*.each { 
            println "Create $it"
            it.mkdirs() 
        }
    }
}

project(':dataaccess') {
    dependencies {
        compile project(':domain')
    }
}

project(':services') {
    dependencies {
        compile project(':dataaccess')
    }
}

project(':web') {
    usePlugin 'jetty'  // jetty plugin extends war plugin, so we get all war plugin functionality as well.
    
    dependencies {
        compile project(':services')  // Because configurations.compile.transitive = true we only have to specify services project, although we also reference dataaccess and domain projects.
    }
    
    // Add extra code to initProject task.
    initProject << { task ->
        def webInfDir = new File(task.project.webAppDir, '/WEB-INF')
        println "Create $webInfDir"
        webInfDir.mkdirs()
    }
}

The subprojects method accepts a closure and here we define common settings for all subprojects. The project method allows us to fine tune the definiton of a subproject. For each project we define project dependencies between the different projects for the compile configuration. This is a very powerful feature of Gradle, we define the project dependency and Gradle will make sure the dependent project is first build before the project that needs it. This even works if we invoke a build command from a subproject. For example if we run gradle build from the web project, all dependent projects are build first.

We also create a new task initProject for all subprojects. This task creates the Groovy source directories. In the web project we add an extra statement to the task to create the src/main/webapp/WEB-INF directory. This shows we can change a task definition in a specific subproject.

Okay it is time to let Gradle create our directories: $ gradle initProject. After the script is finished we have a new directory structure:

It is time to add some files to the different projects. As promised we keep it very, very simple. We define a domain class Language, a class in dataaccess to get a list of Language objects, a services class to filter out the Groovy language and a web component to get the name property for the Language object and a Groovlet to show it in the web browser. Finally we add a web.xml so we can execute the Groovlet.

// File: app/domain/src/main/groovy/com/mrhaki/blog/domain/Language.groovy
package com.mrhaki.blog.domain

class Language {
    String name
}
// File: app/dataaccess/src/main/groovy/com/mrhaki/blog/data/LanguageDao.groovy
package com.mrhaki.blog.data

import com.mrhaki.blog.domain.Language

class LanguageDao {
    List findAll() {
        [new Language(name: 'Java'), new Language(name: 'Groovy'), new Language(name: 'Scala')]
    }
}
// File: app/services/src/main/groovy/com/mrhaki/blog/service/LanguageService.groovy
package com.mrhaki.blog.service

import com.mrhaki.blog.domain.Language
import com.mrhaki.blog.data.LanguageDao

class LanguageService {
    def dao = new LanguageDao()
    
    Language findGroovy() {
       dao.findAll().find { it.name == 'Groovy' }
    }
}
// File: app/web/src/main/groovy/com/mrhaki/blog/web/LanguageHelper.groovy
package com.mrhaki.blog.web

import com.mrhaki.blog.service.LanguageService

class LanguageHelper {
    def service = new LanguageService()
    
    String getGroovyValue() {
        service.findGroovy()?.name ?: 'Groovy language not found'
    }
}
// File: app/web/src/main/webapp/language.groovy
import com.mrhaki.blog.web.LanguageHelper

def helper = new LanguageHelper()

html.html {
    head {
        title "Simple page"
    }
    body {
        h1 "Simple page"
        p "My favorite language is '$helper.groovyValue'."
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- File: app/web/src/main/webapp/WEB-INF/web.xml -->
<web-app>
    <servlet>
        <servlet-name>Groovy</servlet-name>
        <servlet-class>groovy.servlet.GroovyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Groovy</servlet-name>
        <url-pattern>*.groovy</url-pattern>
    </servlet-mapping>
</web-app>

We have created all the files and it is time to see the result. Thanks to the Jetty plugin we only have to invoke the jettyRun tasks and all files (and dependent projects) are compiled and processed:

$ cd web
$ gradle jettyRun
:domain:compileJava
:domain:compileGroovy
:domain:processResources
:domain:classes
:domain:jar
:domain:uploadDefaultInternal
:dataaccess:compileJava
:dataaccess:compileGroovy
:dataaccess:processResources
:dataaccess:classes
:dataaccess:jar
:dataaccess:uploadDefaultInternal
:services:compileJava
:services:compileGroovy
:services:processResources
:services:classes
:services:jar
:services:uploadDefaultInternal
:web:compileJava
:web:compileGroovy
:web:processResources
:web:classes
:web:jettyRun

We open a web browser and go to http://localhost:8080/web/language.groovy and get a simple web page with the results of all our labour:

This concludes this blog about the multi-project support of Gradle. What we need to remember is Gradle is great in resolving dependencies between projects. If one project dependents on another we don't have to worry about first compiling the dependent project, Gradle does this for us. We can define tasks for each project, but still fine tune a task for a specific project. Also we have a certain freedom about the project structure, as long as we define the needed projects in the settings.gradle all will be fine. Also we only need one build.gradle (but can be more per project if we want) to configure all projects.

Gradle Goodness: Execute Tasks with Abbreviations

Gradle supports task name abbreviation to execute tasks. This means we only have to type the portion of a task name that uniquely identifies the task within the project. So we don't have to type the complete name if we can use a shorter version. As a bonus Gradle also supports camel case to abbreviate a task name.

Suppose we have the following build file for our project:

// File: build.gradle
task helloWorld << { ant.echo 'Hello world.' }

The following statements will all invoke this task:

$ gradle helloWorld
$ gradle hello
$ gradle h
$ gradle hW

If the abbreviation is not unique for the project we get a warning from Gradle. For example if we have the tasks hello, helloTask and helloWorld and execute $ gradle h we get a failure message:

FAILURE: Could not determine which task to execute.

* What went wrong:
Task 'h' is ambigious in root project 'project'. Candidates are: 'hello', 'helloWorld', 'helloTask'.

* Try:
Run with -t to get a list of available tasks.

BUILD FAILED

Groovy Goodness: Passing Closures to Methods

Closures are blocks of code we can assign to variables and pass around like objects. We can use closures as method arguments, but we must make sure we use the correct syntax. Groovy has some variations we can use to pass a closure into a method. If for example the closure is the last argument for a method we can put the closure outside the argument list.

// Method with two arguments. Last argument is a closure.
def work(input, cl) {
    cl(input)
}

// Define a closure.
def assertJava = {
    it == 'Java'
}

work('Java', assertJava)

work 'Java', assertJava  // No parenthesis.

work('Groovy', {
    assert it == 'Groovy' 
})  // Anonymous closure as argument.

work('Groovy') {
    assert it == 'Groovy'
}  // Last argument is closure and can be outside parenthesis.

work('Groovy')
{
     assert it == 'Groovy'
}  // Opening bracket on new line. If we want a code block (e.g. static initializer) instead of closure we must use ; to separate code.


work 'Groovy', {
    assert it == 'Groovy'
}  // Pay attention, no parenthesis, so comma is needed again!


// Does not work:
//
// Comma between argument list needed:
// work 'Groovy' {
//     assert it == 'Groovy'
// }

Wednesday, November 11, 2009

Gradle Goodness: Changing the Project Name

By default the name of our Gradle project is the name of the directory the project is created in. We can check this by running the following command:

$ gradle -r | grep name
name: project

The first place we think of to change the project name is build.gradle, because that is also the file we can change for example the version property of our project:

name = 'newProjectName'

When we run gradle we get an error:

* What went wrong:
A problem occurred evaluating root project 'project'.
Cause: Cannot set the value of read-only property 'name' on root project 'project'.

So what can we do? We must create a file settings.gradle and set the property rootProject.name:

rootProject.name = 'newProjectName'

We can check the name of our project has changed by running the following command again:

$ gradle -r | grep name
name: newProjectName

Groovy Goodness: Building a GUI with SwingBuilder

Groovy has some very nice builders to quickly make for example XML. The SwingBuilder class makes it possible to use a builder syntax to make a GUI. We define the components we want to display, bindings, and event handlers. Groovy adds the TableLayout as a layout manger to define a simple table-like layout.

import groovy.swing.SwingBuilder  
import groovy.beans.Bindable  
import static javax.swing.JFrame.EXIT_ON_CLOSE  
import java.awt.*
 
@Bindable
class Address {  
    String street, number, city
    String toString() { "address[street=$street,number=$number,city=$city]" }
}
  
def address = new Address(street: 'Evergreen Terrace', number: '742', city: 'Springfield')
  
def swingBuilder = new SwingBuilder()
swingBuilder.edt {  // edt method makes sure UI is build on Event Dispatch Thread.
    lookAndFeel 'nimbus'  // Simple change in look and feel.
    frame(title: 'Address', size: [350, 230], 
            show: true, locationRelativeTo: null, 
            defaultCloseOperation: EXIT_ON_CLOSE) { 
        borderLayout(vgap: 5)
        
        panel(constraints: BorderLayout.CENTER, 
                border: compoundBorder([emptyBorder(10), titledBorder('Enter your address:')])) {
            tableLayout {
                tr {
                    td {
                        label 'Street:'  // text property is default, so it is implicit.
                    }
                    td {
                        textField address.street, id: 'streetField', columns: 20
                    }
                }
                tr {
                    td {
                        label 'Number:'
                    }
                    td {
                        textField id: 'numberField', columns: 5, text: address.number
                    }
                }
                tr {
                    td {
                        label 'City:'
                    }
                    td {
                        textField id: 'cityField', columns: 20, address.city
                    }
                }
            }
            
        }
        
        panel(constraints: BorderLayout.SOUTH) {
            button text: 'Save', actionPerformed: {
                println address
            }
        }
        
        // Binding of textfield's to address object.
        bean address, 
            street: bind { streetField.text }, 
            number: bind { numberField.text }, 
            city: bind { cityField.text }
    }  
}

When we run the script we get the following output:

If we change the input field and click on the Save button we get the following output:

address[street=Main St.,number=1,city=Hometown]

Tuesday, November 10, 2009

Groovy Goodness: Define Your Own Type Conversion

In Groovy we can override the method asType() to convert an object into another type. We can use the method asType() in our code to invoke the conversion, but we can even make it shorter an use as.

class Size {
    def x, y
    
    Object asType(Class clazz) {
        if (clazz == SquaredSize) {
            new SquaredSize(x: x**2, y: y**2)
        }
    }
}

class SquaredSize {
    def x, y
    
    String toString() { "x: $x, y: $y" }
}

def size = new Size(x: 10, y: 5)
def squared = size as SquaredSize  // Or size.asType(SquaredSize)

println squared  // Output: x: 100, y: 25

assert 100 == squared.x
assert 25 == squared.y

Monday, November 9, 2009

Groovy Goodness: withReader and withWriter

Normally when we are working with readers and writers in Java we must make sure we close the appropriate reader and writer. Groovy has several with...() methods for File, URL or streams and writers, where ... is the name of the reader or writer. We pass a closure to these methods and Groovy makes sure all readers and writers are closed correctly, even if exceptions are thrown in the closure.

def file = new File('sample.txt')

file.withWriter('UTF-8') {
    it.writeLine 'Adding this text to the file.'
}

def s 
file.withReader('UTF-8') {
    s = it.readLine()
}

assert 'Adding this text to the file.' == s

Sunday, November 8, 2009

Groovy Goodness: Using def to Define a Variable

Groovy has the def keyword to replace a type name when we declare a variable. Basically it means we don't really want to define the type ourselves or we want to change the type along the ride.

def myvar = 42
assert myvar instanceof Integer

myvar = 'I am a String'  // String assignment changes type.
assert myvar instanceof String

String s = 'I am String'
assert s instanceof String

s = new Integer(100)  // Surprise, surprise, value is converted to String!
assert s instanceof String

int i = 42
assert i instanceof Integer

try {
    i = 'test'  // Cannot assign String value to Integer.
} catch (e) {
    assert e instanceof org.codehaus.groovy.runtime.typehandling.GroovyCastException
}

Saturday, November 7, 2009

Gradle Goodness: Using Gradle for a Mixed Java and Groovy Project

Gradle is a build system to build software projects. Gradle supports convention over configuration, build-in takss and dependency support. We write a build script in Groovy (!) to define our Gradle build. This means we can use all available Groovy (and Java) stuff we want, like control structures, classes and methods. In this post we see how we can use Gradle to build a very simple mixed Java and Groovy project.

To get started we must first have installed Gradle on our computers. We can read the manual to see how to do that. To check Gradle is installed correctly and we can run build script we type $ gradle -v at our shell prompt and we must get a result with the versions of Java, Groovy, operating system, Ivy and more.

It is time to create our Groovy/Java project. We create a new directory mixed-project:

$ mkdir mixed-project
$ cd mixed-project
$ touch build.gradle

Gradle uses plugins to define taks and conventions for certain type of projects. The plugins are distributed with Gradle and not (yet) downloaded from the internet. One of the plugins is the Groovy plugin. This plugin is extended from the Java plugin, so if we use the Groovy plugin we also have all functionality of the Java plugin. And that is exactly what we need for our project. The plugin provides a set of tasks like compile, build, assemble, clean and a directory structure convention. The plugin assumes we save our source files in src/main/java and src/main/groovy for example. The structure is similar to Maven conventions. As a matter of fact Gradle also has a Maven plugin that add Maven tasks like build, install to our build. For now we just need the Groovy plugin, so we open the file build.gradle in a text editor and add the following line:

usePlugin 'groovy'

To see the lists of tasks we can now execute by just including this one line we return to our shell and type $ gradle -t and we get the following list of tasks:

------------------------------------------------------------
Root Project
------------------------------------------------------------
:assemble - Builds all Jar, War, Zip, and Tar archives.
   -> :jar
:build - Assembles and tests this project.
   -> :assemble, :check
:buildDependents - Assembles and tests this project and all projects that depend on it.
   -> :build
:buildNeeded - Assembles and tests this project and all projects it depends on.
   -> :build
:check - Runs all checks.
   -> :test
:classes - Assembles the main classes.
   -> :compileGroovy, :compileJava, :processResources
:clean - Deletes the build directory.
:compileGroovy - Compiles the main Groovy source.
   -> :compileJava
:compileJava - Compiles the main Java source.
:compileTestGroovy - Compiles the test Groovy source.
   -> :classes, :compileTestJava
:compileTestJava - Compiles the test Java source.
   -> :classes
:groovydoc - Generates the groovydoc for the source code.
:jar - Generates a jar archive with all the compiled classes.
   -> :classes
:javadoc - Generates the javadoc for the source code.
   -> :classes
:processResources - Processes the main resources.
:processTestResources - Processes the test resources.
:test - Runs the unit tests.
   -> :classes, :testClasses
:testClasses - Assembles the test classes.
   -> :compileTestGroovy, :compileTestJava, :processTestResources
rule - Pattern: build<ConfigurationName>: Builds the artifacts belonging to the configuration.
rule - Pattern: upload<ConfigurationName>Internal: Uploads the project artifacts of a configuration to the internal Gradle repository.
rule - Pattern: upload<ConfigurationName>: Uploads the project artifacts of a configuration to a public Gradle repository.

We don't have any code yet in our project so we don't have any task to run right now, but it is good to know all these tasks can be executed once we have our code. Okay, we have to create our directory structure according to the conventions to make it all work without to much configuration. We can do this all by hand but we can also use a trick described in the Gradle cookbook. We add a new task to our build.gradle file to create all necessary directories for us.

task initProject(description: 'Initialize project directory structure.') << {
    // Default package to be created in each src dir.
    def defaultPackage = 'com/mrhaki/blog'
    
    ['java', 'groovy', 'resources'].each {
        // convention.sourceSets contains the directory structure
        // for our Groovy project. So we use this struture
        // and make a directory for each node.
        convention.sourceSets.all."${it}".srcDirs*.each { dir ->
            def newDir = new File(dir, defaultPackage)
            logger.info "Creating directory $newDir"  // gradle -i shows this message.
            newDir.mkdirs()  // Create dir.
        }
    }
}

At the command prompt we type $ gradle initProject and the complete source directory struture is now created. Let's add some Java and Groovy source files to our project. We keep it very simple, because this post is about Gradle and not so much about Java and Groovy. We create a Java interface in src/main/java/com/mrhaki/blog/GreetingService.java:

package com.mrhaki.blog;

public interface GreetingService {
    String greet(final String name);
}

We provide a Java implementation for this interface in src/main/java/com/mrhaki/blog/JavaGreetingImpl.java:

package com.mrhaki.blog;

public class JavaGreetingImpl implements GreetingService {
    public String greet(final String name) {
        return "Hello " + (name != null ? name : "stranger") + ". Greeting from Java.";
    }
}

And a Groovy implementation in src/main/groovy/com/mrhaki/blog/GroovyGreetingImpl.groovy:

package com.mrhaki.blog

class GroovyGreetingImpl implements GreetingService {
    String greet(String name) {
        "Hello ${name ?: 'stranger'}. Greeting from Groovy"
    }
}

We have learned Gradle uses Groovy to define and execute the build script. But this bundled Groovy is not available for our project. We can choose which version of Groovy we want and don't have to rely on the version that is shipped with Gradle. We must define a dependency to the Groovy library version we want to use in our project in build.gradle. So we must add the following lines to the build.gradle file:

repositories {
    mavenCentral()  // Define Maven central repository to look for dependencies.
}

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.6.5'  // group:name:version is a nice shortcut notation for dependencies. 
}

In our shell we type $ gradle compileJava compileGroovy to compile the source files we just created. If we didn't make any typos we should see the message BUILD SUCCESSFUL at the command prompt. Let's add some test classes to our project to test our simple implementations. We create src/test/java/com/mrhaki/blog/JavaGreetingTest.java:

package com.mrhaki.blog;

import static org.junit.Assert.*;
import org.junit.Test;

public class JavaGreetingTest {
    final GreetingService service = new JavaGreetingImpl();

    @Test public void testGreet() {
        assertEquals("Hello mrhaki. Greeting from Java.", service.greet("mrhaki"));
    }
    
    @Test public void testGreetNull() {
        assertEquals("Hello stranger. Greeting from Java.", service.greet(null));
    }
}

And we create a Groovy test class in src/test/groovy/com/mrhaki/blog/GroovyGreetingTest.groovy:

package com.mrhaki.blog;

import static org.junit.Assert.*;
import org.junit.Test;

public class JavaGreetingTest {
    final GreetingService service = new JavaGreetingImpl();

    @Test public void testGreet() {
        assertEquals("Hello mrhaki. Greeting from Java.", service.greet("mrhaki"));
    }
    
    @Test public void testGreetNull() {
        assertEquals("Hello stranger. Greeting from Java.", service.greet(null));
    }
}

We add a dependency to build.gradle for JUnit:

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.6.5'  // group:name:version is a nice shortcut notation for dependencies. 
    testCompile 'junit:junit:4.7'
}

We return to the command prompt and type $ gradle test. Gradle compiles the code and runs the JUnit tests. The results of the test are stored in build/reports/tests. We can see the results in a web browser if we open index.html:

Let's leave the coding part for now. It it time to package our code. We can use $ gradle build to create a JAR file with the compiled classes from the src/main directories. But first we make a change to build.gradle to include a version number. If we run $ gradle -r we get an overview of all properties for our project. Among them is the version property. We can set a value for the version property in the build.gradle file. We also set the basename for the archive:

version = "1.0-${new Date().format('yyyyMMdd')"  // The script is all Groovy, so we make use of all methods and features.
archivesBaseName = 'greeting'

We return to the command prompt and type $ gradle build. Gradle runs and if all is successful we see in build/libs the file greeting-1.0-20091107.jar. Here is the complete build.gradle with all changes we made:

usePlugin 'groovy'

version = "1.0-${new Date().format('yyyyMMdd')}" // The script is all Groovy, so we make use of all methods and features.
archivesBaseName = 'greeting'

repositories {
    mavenCentral()  // Define Maven central repository to look for dependencies.
}

dependencies {
    groovy 'org.codehaus.groovy:groovy:1.6.5'  // group:name:version is a nice shortcut notation for dependencies. 
    testCompile 'junit:junit:4.7'
}

task initProject(description: 'Initialize project directory structure.') << {
    // Default package to be created in each src dir.
    def defaultPackage = 'com/mrhaki/blog'
    
    ['java', 'groovy', 'resources'].each {
        // convention.sourceSets contains the directory structure
        // for our Groovy project. So we use this struture
        // and make a directory for each node.
        convention.sourceSets.all."${it}".srcDirs.each { dirs ->
            dirs.each { dir ->
                def newDir = new File(dir, defaultPackage)
                logger.info "Creating directory $newDir"  // gradle -i shows this message.
                newDir.mkdirs()  // Create dir.
            }
        }
    }
}

We learned how we can start a new project from scratch and with little coding get a compiled and tested archive wth our code. In future blog posts we learn more about Gradle, for example the multi-project support.