Search

Dark theme | Light theme

October 31, 2009

Groovy Goodness: Access Strings with Subscript Operator

Groovy adds a lot of support to the String class. The getAt method is added and that means we can use the subscript operator ([]) to access parts of a String.

def s = 'Accessing Strings in Groovy is easy.'

assert 'A' == s[0]
assert 'A' == s.getAt(0)
assert 'Groovy' == s[21..26]  // We can use ranges.
assert 'easy.' == s[s.indexOf('ea')..-1]

// We can also use each method on a String.
s[21..26].each { println "$it-" } // Output: G-r-o-o-v-y-

October 30, 2009

Groovy Goodness: Invoke Methods Dynamically

In Groovy we can invoke a method with a name assigned to a variable. We use the GString notation to invoke the method with the variable name. We can pass parameters to the method just like when we use the method name directly.

def s = "Groovy is so much fun"
def methods = ['Upper', 'Lower']
def result = methods.collect { s."to${it}Case"() }
assert 'GROOVY IS SO MUCH FUN' == result[0]
assert 'groovy is so much fun' == result[1]

// We can pass parameters just like a normal method invocation.
def method = 'count'
def param = 'o'
assert 3 == s."$method"(param)  // s.count('o').

October 29, 2009

Groovy Goodness: Getting a Submap from a Map

To get only a subset of a map we can use the subMap() method. We provide a list of keys as parameter to define which elements from the map we want returned.

def map = [name: 'mrhaki', country: 'The Netherlands', blog: true, languages: ['Groovy', 'Java']]

def keys = ['name', 'blog']
assert [name: 'mrhaki', blog: true] == map.subMap(keys)

def booleanKeys = map.findAll { it.value instanceof Boolean }.collect { it.key } 
assert [blog: true] == map.subMap(booleanKeys)

def words = ['a': 'Apple', 'j': 'Java', 'g': 'Groovy', 'c': 'Cool']
def range = 'c'..'h'  // Range is also a list and can be used here.
def rangeWords = words.subMap(range).findAll{ it.value }
// words.subMap(range) returns [c:Cool, d:null, e:null, f:null, g:Groovy, h:null]
// so we use the findAll method to filter out all null values.
assert ['c': 'Cool', 'g': 'Groovy'] == rangeWords

October 28, 2009

Groovy Goodness: Immutable Collections

Groovy adds the method asImmutable() to the Collection interface. With this method we can convert a list or map to an immutable one. We can read data from the immutable list or map, but we cannot add, change or remove elements from the list or map. This is a good way to insure our list or map is read only in for example a threading and concurrency context.

def list = ['Groovy', 'Java', 'JRuby'].asImmutable()
assert 'Groovy' == list[0]
try {
    list << 'Scala'  // Cannot add item.
} catch (e) {
    assert e instanceof UnsupportedOperationException
}
try {
    list.remove 'Java'  // Cannot remove item.
} catch (e) {
    assert e instanceof UnsupportedOperationException
}

def map = [name: 'mrhaki', country: 'The Netherlands', blog: true].asImmutable()
assert map.blog
try {
    map.blog = false  // Cannot change item.
} catch (e) {
    assert e instanceof UnsupportedOperationException
}

October 27, 2009

Groovy Goodness: Getting and Setting Properties

In Groovy we can set values for properties with a simple assignment using the = operator. Groovy will invoke the set for us. At first sight we might think Groovy sets the variable in the class directly, but that is not true, because the set method is invoked. To get the value of a property we can use dot (.) notation instead of the get method.

Let's see this in action in code. We first create a simple JavaBean in Java code and then we set and get the property in different ways.

// Simple Java Bean.
public class Simple {
    private String text;
    
    public Simple() { 
        super(); 
    }

    public String getMessage() { 
        return "GET " + text; 
    }

    public void setMessage(final String text) {
        this.text = "SET " + text
    }
}

Now some Groovy code to get and set values for the text property.

def s1 = new Simple()
s1.setMessage('Old style')
assert 'GET SET Old style' == s1.getMessage()
s1.setMessage 'A bit more Groovy'  // No parenthesis.
assert 'GET SET A bit more Groovy' == s1.getMessage()

def s2 = new Simple(message: 'Groovy constructor')  // Named parameter in constructor.
assert 'GET SET Groovy constructor' == s1.getMessage()

def s3 = new Simple()
s3.message = 'Groovy style'  // = assigment for property.
assert 'GET SET Groovy style' == s3.message  // get value with . notation.

October 26, 2009

Groovy Goodness: Groovy SQL DataSet

In a previous post we learned about the basic Groovy SQL support. In this post we learn about the DataSet class. A DataSet is an abstraction on top of a table that we can use to add data to the table and to retrieve data from the table. The DataSet contains some nice magic to build queries, but there is an important issue when we use this: our Groovy script with the code must be in our classpath or the script must be run as a Groovy script (so not pre-compiled). If we don't add the script to our classpath we get the following exception: GroovyRuntimeException: Could not find the ClassNode for MetaClass....

In the following code snippet we are accessing a MySQL database with the name groovy. Both username and password for the database are groovy and MySQL is running on localhost and port 3306 (is default port).

import groovy.sql.*

// Create connection to MySQL with classic JDBC DriverManager.
def db = Sql.newInstance("jdbc:mysql://localhost/groovy", 'groovy', 'groovy', 'com.mysql.jdbc.Driver')

// Create a new table
db.execute 'drop table if exists languages'
db.execute '''
    create table languages(
        id integer not null auto_increment,
        name varchar(20) not null,
        primary key(id)
    )
'''

// Create a DataSet.
def languageSet = db.dataSet("languages")
languageSet.add(id: null, name: 'Groovy')
languageSet.add(name: 'Java')  // If we don't add the id column the value null is used.
languageSet.add(name: 'JRuby')
languageSet.add(name: 'Scala')

// Get data with each method.
def result = []
languageSet.each {
    result << it.name
}
assert 4 == result.size()
assert ['Groovy', 'Java', 'JRuby', 'Scala'] == result

// Use findAll and sort to define a query condition.
def firstItems = languageSet.findAll { it.id < 3 }.sort { it.name }
// No database acccess yet, only the query is constructed.
// We can see the query with sql property and parameters with parameters property.
assert 'select * from languages where id > ? order by name' == firstItems.sql
assert [3] == firstItems.parameters

// We call each to really access the database.
firstItems.findAll { it.name == 'Groovy' }.each { row ->
    assert 1 == row.id
    assert 'Groovy' == row.name
}

October 25, 2009

Groovy Goodness: Groovy SQL

Groovy has powerful SQL support to work with in our scripts and classes. It is all based on JDBC, but so much easier to code. For example to create a connection to a database we only need one line of code and we get a powerful object in return. With this object we can run queries and SQL statements to manipulate data. In this post we look at the basic SQL support in Groovy. In a next post we learn a more powerful Groovy SQL feature: DataSets.

In the following code snippet we are accessing a MySQL database with the name groovy. Both username and password for the database are groovy and MySQL is running on localhost and port 3306 (is default port).

import groovy.sql.*

def username = 'groovy', password = 'groovy', database = 'groovy', server = 'localhost'

// Create connection to MySQL with classic JDBC DriverManager.
def db = Sql.newInstance("jdbc:mysql://$server/$database", username, password, 'com.mysql.jdbc.Driver')

// Or we can create a connection with a DataSource (also via JNDI possible)
def ds = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource(
    databaseName: database, user: username, password: password, serverName: server
)
assert 'jdbc:mysql://localhost:3306/groovy' == ds.url
def dbDS = new Sql(ds)

// Create a new table
db.execute 'drop table if exists languages'
// We can use multi-line strings to create readable SQL in our code.
db.execute '''
    create table languages(
        id integer not null auto_increment,
        name varchar(20) not null,
        primary key(id)
    )
'''

// Fill table with data in different ways.
// First a normal statement.
db.execute 'insert into languages values(null, "Groovy")'
assert 1 == db.updateCount
// String with extra parameters will become a prepared statement.
db.execute 'insert into languages values(null, ?)', ['Java']
assert 1 == db.updateCount
// GString will become a prepared statement.
def langValue = 'JRuby'
db.execute "insert into languages values(null, $langValue)"
assert 1 == db.updateCount

// With executeInsert we get the generated id(s) back.
def insertedIds = db.executeInsert 'insert into languages values(null, "Scalaa")'
assert 4 == insertedIds[0][0]

// executeUpdate return number of rows affected.
def old = 'Scalaa', new = 'Scala'
def updated = db.executeUpdate "update languages set name=$new where name=$old"
assert 1 == updated


// Now let's get data from the table Groovy style.
// With rows we get a list of GroovyResultSet objects and this means we can
// use column names to access data in a row.
def all = db.rows('select * from languages')
assert 4 == all.size()
assert ['Groovy', 'Java', 'JRuby', 'Scala'] == all.collect{ it.name }
assert ['Groovy', 'JRuby'] == all.findAll{ it.name ~= /y/ }

// With eachRow we can use a closure to do something with each row.
// The closure parameter is also of type GroovyResultSet.
def maxId = 3
db.eachRow("select id, name from languages where id < $maxId") { row ->
    if (row.id == 1) assert 'Groovy' == row.name
    if (row.id == 2) assert 'Java' == row.name
}
db.eachRow("select name from language where name=?", ['Java']) { 
    assert 'Java' == it.name
}

def countRows = db.firstRow("select count(*) as numberOfRows from languages")
assert 4 == countRows.numberOfRows

October 24, 2009

Groovy Goodness: Optional Parenthesis

Groovy can make code more readable with small features like optional parenthesis. If a method contains at least one argument we can leave out the parenthesis. There must also be no ambiquity, before we can leave out the parenthesis, otherwise the results can be unexpected. This also works for methods with named parameters and as a result the code could already look like a more natural language.

class User {
    String name    
    def connections = []
    
    def speaks(args) {
        connections.find{it.name == args.to.name}.listen(args.saying)
    }
    
    def meets(user) {
        connections << user
    }
    
    def listen(text) {
        println "I, $name, am listening to '$text'"
    }

    def greeting() {
        "Hi, I am $name."
    }
}

def mrhaki = new User(name: 'mrhaki')
def hubert = new User(name: 'hubert')

mrhaki.meets hubert  // No parenthesis needed.

println mrhaki.greeting()  // Need to use parenthesis for greeting, otherwise Groovy thinks greeting is a property.
// Output: Hi, I am mrhaki

mrhaki.speaks to: hubert, saying: 'How are you doing?'  // Named parameters.
// Output: I, hubert, am listening to 'How are you doing?'

// Look out with closures as the last element.
// The method can be invoked in several ways.
def list = [1,2,3,4]
list.sum(100, { it * 2 })  // Traditional, all parenthesis and comma.
list.sum(100) { it * 2 }  // Last argument is closure, so can be outside parenthesis and no comma 
list.sum 100, { it * 2 }  // No parenthesis, but with the comma.

October 23, 2009

Invoke Grails commands from SpringSource Tool Suite (STS)

Okay, we have setup SpringSource Tool Suite (STS) for Groovy and Grails support, but how do we create new domain classes or controllers? Once we have created a Grails project we can press Ctrl+G (in Windows) in our editor and a little popup shows where we can type Grails commands. We get code completion for the commands we can type so it easy to execute them.

The output of the commands is shown in the Output window.

On the Grails website there is now also an article on Groovy and Grails STS Integration.

Groovy Goodness: Static Imports

Java already has static imports, but Groovy takes it to the next level. In a previous post we learned how we use the as keyword to assign a class we import to a variable in the import statement. But with static imports we can do this even for static methods and properties. This makes for code which may confuse us, but if we look at the import section all will be revealed.

import static HttpURLConnection.HTTP_OK  // Normal Java static import.
import static HttpURLConnection.HTTP_OK as okay 
import static HttpURLConnection.setFollowRedirects as redirect
import java.net.HttpURLConnection as http // Non static import.

redirect false  // HttpURLConnection.setFollowRedirects(false)
assert false == HttpURLConnection.followRedirects

def c = (http) 'http://mrhaki.blogspot.com'.toURL().openConnection()
assert c instanceof HttpURLConnection

assert okay == c.responseCode
assert HTTP_OK == c.responseCode

October 22, 2009

Groovy Intentions in IntelliJ IDEA Community Edition

IntelliJ IDEA Community Edition has a nice feature called intentions. Intentions offer a way to simplify our code. In our editor we can select an intention with Alt+Enter and IntelliJ IDEA shows a popup with available intensions. Let's take a look at some useful intentions when developing Groovy code.

def s = "Simple test ${obj.ide}"

// Becomes:
def s = "Simple test $obj.ide"
def output = s != null ? s : '' 

// Becomes:
def output = s ?: ''
def list = ['a', 'b', 'c']
for (c in list) {
    println c.toUpperCase()
}

// Becomes:
def list = ['a', 'b', 'c']
list.each { c ->
    println c.toUpperCase()
}
def c = list.getAt(0)

// Becomes:
def c = list[0]
def printObj(date, text, list) {
    println """
        Print on $date $text and list has size ${list.size()}
    """
}

// Becomes:
def printObj(params) {
    println """
        Print on $params.date $params.text and list has size ${params.list.size()}
    """
}
list.contains('d')

// Becomes:
list.contains 'b'
class User { String name }
def u = new User()
u.setName('mrhaki')

// Becomes:
class User { String name }
def u = new User()
u.name = 'mrhaki'
def s = 'Simple test with ' + obj.ide

// Becomes:
def s = "Simple test with $obj.ide"

Adding Groovy and Grails Support to SpringSource Tool Suite (STS)

After reading all tweets about the released Groovy and Grails support this week I thought it would be a good idea to install it and see it for myself. In this post we look at how we can install the Groovy and Grails plugins into SpringSource Tool Suite.

First we must open the STS Dashboard (Help | STS Dashboard) and select the Extensions tab. Here we see at the top just the two plugins we want:

We select both plugins (no Grails without Groovy) and click on the Install button. Next STS opens a new dialog window with more details about the plugins. Both need to be selected before we continue by clicking on the Next button.

We are presented with more detailed information and we click on the Next button to continue.

Finally we need to accept the licenses that apply for the Groovy and Grails support. We click on the Finish button and STS will download all needed files and installs the plugin.

After the code is installed STS requires a restart. We wait until STS is restarted and we go to File | New Project to see both Groovy and Grails projects are available as project templates.

On the Grails website there is also an article about Groovy and Grails STS Integration.

Groovy Goodness: Using the replaceAll Methods from String

Groovy adds two extra replaceAll methods to the String class. First we can pass a Pattern instead of a String argument with replaceAll(Pattern, String). And with the other method we can use a closure to replace a value found with replaceAll(String, Closure).

def s = "Programming with Groovy is fun!"

assert "Programming with Groovy rocks!" == s.replaceAll(~/is fun!/, "rocks!")  // Groovy extension to String.
assert "Programming with Groovy is awesome." == s.replaceAll("fun!", "awesome.")  // java.lang.String.replaceAll.

// Replace found String with result of closure.
def replaced = s.replaceAll(/fun/) {
    def list = ['awesome', 'cool', 'okay']
    list[new Random().nextInt(list.size())]
}
assert [
    "Programming with Groovy is awesome!",
    "Programming with Groovy is cool!",
    "Programming with Groovy is okay!"
].contains(replaced)
 
// Use closure to replace text and use grouping. 
// First closure parameter is complete string and following
// parameters are the groups.
def txt = "Generated on 30-10-2009 with Groovy."
def replacedTxt = txt.replaceAll(/.*(\d{2}-\d{2}-\d{4}).*(Gr.*)./) { all, date, lang ->
    def dateObj = Date.parse('dd-MM-yyyy', date)
    "The text '$all' was created with $lang on a ${dateObj.format('EEEE')}."
}
assert "The text 'Generated on 30-10-2009 with Groovy.' was created with Groovy on a Friday." == replacedTxt

October 21, 2009

Groovy Goodness: Groovlets as Lightweight Servlets

Groovlets are Groovy scripts that are executed by a servlet. With Groovlets a user can request a Groovy script that is executed on the server and the results are displayed in a web browser. We only have to define a servlet in the web.xml of a Java web application, place the Groovy libraries in the web application's lib folder and we can execute Groovy scripts.

The Groovy script, or we can call it a Groovlet, has a couple of implicit variables we can use. For example reqeust, response to access the HttpServletRequest and HttpServletResponse objects. We have access to the session with the session variable. And if we want to output data we can use out, sout and html.

Let's create a Groovy script serverinfo.groovy:

def method = request.method

if (!session) {
    session = request.getSession(true)
}

if (!session.groovlet) {
    session.groovlet = 'Groovlets rock!'
}

html.html {
    head {
        title 'Groovlet info'
    }
    body {
        h1 'General info'
        ul {
            li "Method: ${method}"
            li "RequestURI: ${request.requestURI}"
            li "session.groovlet: ${session.groovlet}"
            li "application.version: ${context.version}"
        }
        
        h1 'Headers'
        ul {
            headers.each {
                li "${it.key} = ${it.value}"
            }
        }
    }
}

A simple script to start Jetty so we can run our Groovlet:

import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.*
import groovy.servlet.*

@Grab(group='org.mortbay.jetty', module='jetty-embedded', version='6.1.14')
def startJetty() {
    def jetty = new Server(9090)
    
    def context = new Context(jetty, '/', Context.SESSIONS)  // Allow sessions.
    context.resourceBase = '.'  // Look in current dir for Groovy scripts.
    context.addServlet(GroovyServlet, '*.groovy')  // All files ending with .groovy will be served.
    context.setAttribute('version', '1.0')  // Set an context attribute.
    
    jetty.start()
}

println "Starting Jetty, press Ctrl+C to stop."
startJetty()

When we run the script to start Jetty and visit http://localhost:9090/serverinfo.groovy with our browser we get the following output:

October 20, 2009

Use GroovyDSL in IntelliJ IDEA Community Edition

If we define our own DSL or use dynamically added methods or properties we can use GroovyDSL to enable code completion in our project. Normally IntelliJ IDEA doesn't know about a DSL or dynamically added properties and methods, but we can describe them in GroovyDSL. GroovyDSL is a small framework we use to describe new behaviour of Groovy scripts. In an earlier post we saw how can use Dynamic properties to get a similar effect.

In this post we write a GroovyDSL script to enable code completion for Groovlets' implicit variables, like request, repsonse and application. We start by creating a new Groovy script in our project. We right-click on the src node and select Groovy script from the popup menu. We get a dialog window where we fill in the name of our script, groovletTransform, and change the Kind to GroovyDSL script:

We click the OK button and IntelliJ IDEA adds the file groovletTransform.gdsl to our project. We use the following code to define the DSL:

// Create context for Groovy script files which names end with groovlet.
def groovletContext = context(filetypes: ['groovlet'], scope: scriptScope())

contributor(groovletContext) {
    property name: 'request', type: 'javax.servlet.http.HttpServletRequest'
    property name: 'response', type: 'javax.servlet.http.HttpServletResponse'
    property name: 'session', type: 'javax.servlet.http.HttpSession'
    property name: 'application', type: 'javax.servlet.ServletContext'
    property name: 'context', type: 'javax.servlet.ServletContext'
    property name: 'params', type: 'java.util.LinkedHashMap'
    property name: 'headers', type: 'java.util.LinkedHashMap'
    property name: 'html', type: 'groovy.xml.MarkupBuilder'
    property name: 'out', type: 'java.io.PrintWriter'
    property name: 'sout', type: 'javax.servlet.ServletOutputStream'

    method name: 'forward', type: 'void', params: [path: 'java.lang.String']
    method name: 'include', type: 'void', params: [path: 'java.lang.String']
    method name: 'redirect', type: 'void', params: [path: 'java.lang.String']
}

At the top of our editor window we get the following message: DSL descriptor file has been changed and isn't currently executed. Click to activate it back. We click on this message and a popup menu with the action Activate appears:

We select Activate and now the rules in our DSL are active for our project. So we can create a new Groovy script with the extension groovlet and in the editor we get code completion for the variables and methods that are available for Groovlets:

It takes some extra effort, but especially when we define our own DSL or on a large project adding code completion for dynamic properties and methods can save a lot of time (and errors) in the long run.

Groovy Goodness: Using the Template Engines

Groovy has a built-in template mechanism to generate text dynamically. We can use the SimpleTemplateEngine, GStringTemplateEngine and XmlTemplateEngine to create a dynamic text from a static source. The XmlTemplateEngine is best used for generating XML, the GStringTemplateEngine is best used for streaming scenarios and otherwise we use the SimpleTemplateEngine.

To use a template engine we must read in the static text from a file, URL or String, bind dynamic data to the template engine and get the generated text. These steps are very easy to follow and that makes using the Groovy template engine so easy.

import groovy.text.*

// SimpleTemplateEngine.
def simple = new SimpleTemplateEngine()
def source = '''Dear $name,
Please respond to this e-mail before ${(now + 7).format("dd-MM-yyyy")}
Kind regards, mrhaki'''
def binding = [now: new Date(109, 11, 1), name: 'Hubert Klein Ikkink']
def output = simple.createTemplate(source).make(binding).toString()

assert "Dear Hubert Klein Ikkink,\nPlease respond to this e-mail before 08-12-2009\nKind regards, mrhaki" == output

// GStringTemplateEngine with out variable.
def gstring = new GStringTemplateEngine()
def gsource = '''Dear <%= name %>,
Text is created for <% if (gstring) out << 'GStringTemplateEngine' else out << 'other template engine'%>.'''
def gbinding = [name: 'mrhaki', gstring: true]
def goutput = gstring.createTemplate(gsource).make(gbinding).toString()

assert "Dear mrhaki,\nText is created for GStringTemplateEngine." == goutput

// XmlTemplateEngine with gsp:scriplet and gsp:expression tags.
def xmlEngine = new XmlTemplateEngine()
def xml = '''<?xml version="1.0"?>
<users xmlns:gsp='http://groovy.codehaus.org/2005/gsp'>
    <gsp:scriptlet>users.each {</gsp:scriptlet>
        <user id="${it.id}"><gsp:expression>it.name</gsp:expression></user>
    <gsp:scriptlet>}</gsp:scriptlet>
</users>'''
def xmlBinding = [users: [
    new Expando(id: 1, name: 'mrhaki'),
    new Expando(id: 2, name: 'Hubert')]
]
def xmlOutput = xmlEngine.createTemplate(xml).make(xmlBinding).toString()

assert '''\
<users>
  <user id='1'>
    mrhaki
  </user>
  <user id='2'>
    Hubert
  </user>
</users>
''' == xmlOutput

October 19, 2009

Use Dynamic Properties in IntelliJ IDEA Community Edition

We can tell IntelliJ IDEA Community Edition that a property is dynamically added to a class or object. If we have told IntelliJ IDEA the type of the object we get complete code completion for the property in the text editor.

For example if we have a Groovlet where we use the request property, then IntelliJ IDEA shows a line under request. This indicates IntelliJ IDEA doesn't know about request, but if we press Alt+Enter when the cursor is on the keyword we get a little popup menu:

We must select the first option Add dynamic property 'request' and IntelliJ IDEA opens a dialog window. Here we must tell which type this property is. The request property is of type javax.servlet.http.HttpServletRequest, so we type in the classname and press OK:

We are back in our editor. We can open the window Dynamic properties to see which properties are defined as dynamic and of which type they are. But we also get complete code completion for our request object:

Groovy Goodness: BigDecimal

In Groovy java.math.BigDecimal is the default type for non-integer floating types. Because of default imports we don't have to import the BigDecimal class, but we can use it right away. To create a BigDecimal (or BigInteger) we can use the "G" or "g" suffix.

assert 123g instanceof BigInteger
assert 42G instanceof BigInteger
assert 1.423 instanceof BigDecimal
assert 42.0g instanceof BigDecimal
assert 9203.10291G instanceof BigDecimal

// Let's do some math.
assert 3.2 == 1.2G + 2G
assert 10 == 10.1g - 0.1G

October 18, 2009

Use Gradle Support in IntelliJ IDEA Community Edition

IntelliJ IDEA Community Edition supports Gradle scripts. We can create a Gradle script in the IDE and run it with a Run Configuration. Let's see how we do this in this blog post.

First we must define where we have Gradle installed on our local computer. We go to File | Settings. Here we select Gradle from the left navigation menu.

We can type the complete path to the Gradle directory or click on the ... button to select the directory graphically.

Once we have set the Gradle directory we are ready to create our first Gradle build script. In our project we add a new file build.gradle. We right-click on the project and select File | New File. We use the name build.gradle and press the OK button. In the root of our project we now have the file build.gradle. We open the file and type the following simple hello task definition:

task hello << {
    println 'Hello world'
}

But how do we execute our hello task? We need to pass hello to the command-line and we can do this with a Run configuration. We go to Run | Run... and IntelliJ IDEA opens a dialog window. We can change the name here, so it easy to see what we are running if we want to run this command again. Let's change the name to build::hello. And we must set hello at the Script Parameters: input field.

To execute our task we only have to press the Run button and IntelliJ IDEA runs our tasks. We look at the Run window to see the ouput of our task:

We can re-run the task by going to Run | Run... and select build::hello from the list of configurations.

Groovy Goodness: Getting the Tail of a List

Groovy adds several methods to the List interface. In this post we look at the head() and tail() methods. The head() method returns the first element of the list, and the tail() returns the rest of the elements in the list after the first element. The following code snippet shows a simple recursive method to reverse a list.

def list = [1, 2, 3, 4]

def reverse(l) {
    if (l.size() == 0) {
        []
    } else {
        reverse(l.tail()) + l.head()
    }
}

assert [4, 3, 2, 1] == reverse(list)

// For the same result we can of course use the List.reverse() method,
// but then we didn't learn about tail() and head() ;-)
assert [4, 3, 2, 1] == list.reverse()

October 17, 2009

Groovy Goodness: Check If Method or Property is Available

In Groovy we can easily see if a method or property is available for an object. We can use the respondsTo() and hasProperty() methods to see if the method or property can be invoked or accessed. We can not check for methods or properties which are added by overriding the methodMissing()/propertyMissing() or invokeMethod()/getProperty() methods.

class Simple {
    String language
    
    def whatDoYouSpeak() {  
        language
    }
    
    def say(String text) {
        "You say $text in $language"
    }
}

def s = new Simple(language: 'Groovy')

assert s.metaClass.respondsTo(s, 'whatDoYouSpeak')
assert Simple.metaClass.respondsTo(s, 'say')
assert s.metaClass.respondsTo(s, 'say', String)
assert !s.metaClass.respondsTo(s, 'say', Integer)  // No say(Integer) method.
assert Simple.metaClass.respondsTo(s, 'toString')  // Method in parent object.

assert s.metaClass.hasProperty(s, 'language')
assert Simple.metaClass.respondsTo(s, 'getLanguage')  // Get/set methods are generated.
assert s.metaClass.respondsTo(s, 'setLanguage')

October 16, 2009

Simple Groovy Project in IntelliJ IDEA Community Edition

The Community Edition of JetBrain's IntelliJ IDEA promises to be a good IDE to create Groovy applications and scripts. Let's start with a simple Groovy project and create a very simple script to see how easy it is to get started. We start IntelliJ IDEA 9 Community Edition and create a new project (File | Project). IntelliJ shows a dialog where we select the first option: Create Project From Scratch and we click on the Next button.

In the next screen we type in a name for our project: helloworld. We must make sure we select Java Module. We can change the location of our project if we want, but we can also leave the default values. We select the Next button to go the next screen.

Now we can change the source directory, but for now we leave the value src as is. When we click on the Next button we get to the last screen.

In this final screen we can select Groovy. If we installed the Scala plugin we also get Scala as an option, but for this example we only have to select Groovy. As this is the first Groovy project we are creating we must define a Groovy directory.

We select the ... button in the Groovy Settings section. IntelliJ opens a dialog window to select the directory where we installed Groovy on our local computer. Once we have selected the directory we want we click on the OK button.

IntelliJ has all information to create a new project so we click the Finish button. During the creation process we get a dialog window with the question if we want our Groovy library to be only for our project or global, so it can be used in other projects. Let's select the option to create a global library, so we can use it again when we create a new Groovy project in the future.

We now have our newly created helloworld project. When we right-click on the src node we get a pop-up menu. Here we select New | Groovy Script to create a new script.

We have to set a name for our Groovy script in the following dialog window. Let's call our script HelloWorld and press the OK button.

Our project contains the file HelloWorld.groovy and it is opened in the editor. We can type our code and run it with Run | Run... (or press Alt+Shift+F10 in Windows). IntelliJ IDEA provides code completion for Groovy methods and variables, so with a few keystrokes we can write our Groovy scripts and classes.

IntelliJ IDEA 9 Community Edition is a good Groovy editor to create Groovy applications with code completion, compiler, debugger, syntax highlighting and smart code navigation and search.

Groovy Goodness: Navigating with GPath

Groovy has GPath, a path expression language to navigate in XML or POJOs. We can use a simple dot-notation to identify elements in XML or a set of POJOs. This results in clean and dense code.

def xml = '''
<languages>
    <language id="1" jvm="true">Groovy</language>
    <language id="2" jvm="true">Java</language>
    <language id="3" jvm="false">Ruby</language>
</languages>
'''

def languages = new XmlSlurper().parseText(xml)
// Navigate in XML with GPath.
assert 3 == languages.language.size()
assert 'Groovy' == languages.language.find { it.'@id' == 1 }.text()
assert ['Groovy', 'Java', 'Ruby'] == languages.language.collect { it.text() }
assert 1 == languages.language.find { it == /Groovy/ }['@id'].toInteger()

// Navigating with GPath through object graph.
assert 75 == String.metaClass.methods.name.size()
assert ['copyValueOf', 'format', 'valueOf'] == String.metaClass.methods.findAll { it.static }.name.unique()
assert ['replace', 'replace', 'replaceAll', 'replaceFirst'] == String.metaClass.methods.name.grep(~/replace.*/)
assert ['class', 'bytes', 'empty'] == String.metaClass.properties.name
assert ['java.lang.Class', 'byte[]', 'boolean'] == String.metaClass.properties.type.canonicalName

October 15, 2009

Groovy Goodness: Default Imports

Groovy allows to write dense code. For example we don't have to write explicit import statements for a lot of every day packages. The following packages are imported by default in Groovy:

java.io.* 
java.lang.* 
java.math.BigDecimal 
java.math.BigInteger 
java.net.* 
java.util.* 
groovy.lang.* 
groovy.util.* 

So we can write code like this without an import statement:

def now = new Date()
def file = new File(".")
def url = new URL('http://mrhaki.blogspot.com')
def list = new ArrayList()

October 14, 2009

Groovy Goodness: Grouping Map Elements

In a previous Groovy Goodness post we learned how to use the groupBy method on collections. The Map class has an extra method: groupEntriesBy. We must provide a closure for this method to define how we want the elements of the map to be grouped. The result is a new Map with keys and a list of Map$Entry objects for each key. This is different from the result of the groupBy method. Because then we get a Map with keys and a Map for each key.

// A simple map.
def m = [q1: 'Groovy', sort: 'desc', q2: 'Grails']

// Closure we use to define the grouping.
// We want all keys starting with 'q' grouped together
// with the key 'params', all other keys are not grouped.
def groupIt = { key, value ->
    if (key.startsWith('q')) { 
        'params'
    } else {
        key
    }
}

// Use groupEntriesBy.
def groupEntries = m.groupEntriesBy(groupIt)
assert 2 == groupEntries.size()
assert groupEntries.params & groupEntries.sort
assert 'desc' == groupEntries.sort[0].value  // Key for a list of Map$Entry objects.
assert 2 == groupEntries.params.size()
assert 'Groovy' == groupEntries.params[0].value
assert 'q1' == groupEntries.params[0].key
assert 'Grails' == groupEntries.params.find { it.key == 'q2' }.value
assert groupEntries.params instanceof ArrayList
assert groupEntries.params[0] instanceof Map$Entry

// Use groupBy.
def group = m.groupBy(groupIt)
assert 2 == group.size()
assert group.params & group.sort
assert 'desc' == group.sort.sort  // Key for Map with key/value pairs.
assert 2 == group.params.size()
assert 'Groovy' == group.params.q1
assert 'q1' == group.params.keySet().toArray()[0]
assert 'Grails' == group.params.q2
assert group.params instanceof Map
assert group.params.q1 instanceof String

October 13, 2009

Groovy Goodness: Using AntBuilder

Groovy 1.6.5 includes Ant 1.7.1 and we can use Ant from our Groovy code with the AntBuilder class. The AntBuilder provides a nice DSL to create Ant tasks and to execute them. The following piece of code shows some samples of what we can do with the AntBuilder:

// Create AntBuilder.
def ant = new AntBuilder()

// Simple echo task.
def world = 'Groovy'
ant.echo("Hello $world")  // Output: [echo] Hello Groovy

// Ant task properties are defined as a map.
def options = [src: 'http://mrhaki.blogspot.com', dest: 'blog.html']
ant.get(options)
// is the same as
ant.get(src: 'http://mrhaki.blogspot.com', dest: 'blog.html']

// Nice builder syntax for tasks with for example filesets.
def zipfile = 'test.zip'
def current = '.'
ant.zip(destfile: zipfile) {
    fileset(dir: current) {
        include(name: '**/*.txt')
    }
}

October 12, 2009

Groovy Goodness: Reading XML

In a previous Groovy Goodness post we learned how to write XML with builders. In this post we learn how to read XML with the XmlParser and XmlSlurper classes. The main difference between both parsers is that the XmlParser return a list of NodeList and Node objects and the XmlSlurper return a GPathResult.

First we parse the XML with the XmlParser. We define a namespace so we can access the meta.isbn elements with a namespace syntax.

import groovy.xml.*

def xml = '''
<books xmlns:meta="http://meta/book/info" count="3">
  <book id="1">
    <title lang="en">Groovy in Action</title>
    <meta:isbn>1-932394-84-2</meta:isbn>
  </book>
  <book id="2">
    <title lang="en">Groovy Programming</title>
    <meta:isbn>0123725070</meta:isbn>
  </book>
  <book id="3">
    <title>Groovy &amp; Grails</title>
    <!--Not yet available.-->
  </book>
  <book id="4">
    <title>Griffon Guide</title>
  </book>
</books>
'''

def ns = new Namespace('http://meta/book/info', 'meta')
def books = new XmlParser().parseText(xml)
assert books instanceof Node
assert 4 == books.book.size()
assert 11 == books.breadthFirst().size()
assert 'Groovy in Action' == books.book[0].title.text()
assert 'Groovy Programming' == books.book.find { it.'@id' == '2' }.title.text()
assert 'Groovy Programming' == books.book.find { it.attribute('id') == '2' }.title.text()
assert [1, 2, 3] ==  books.book.findAll { it.title.text() =~ /Groovy/ }.'@id'*.toInteger()
assert ['1-932394-84-2', '0123725070'] == books.book[ns.isbn].inject([]) { result, v -> result << v.text() }

We can try the code in Groovy Web Console.

Next we use XmlSlurper to parse the same XML.

import groovy.xml.*

def xml = '''
<books xmlns:meta="http://meta/book/info" count="3">
  <book id="1">
    <title lang="en">Groovy in Action</title>
    <meta:isbn>1-932394-84-2</meta:isbn>
  </book>
  <book id="2">
    <title lang="en">Groovy Programming</title>
    <meta:isbn>0123725070</meta:isbn>
  </book>
  <book id="3">
    <title>Groovy &amp; Grails</title>
    <!--Not yet available.-->
  </book>
  <book id="4">
    <title>Griffon Guide</title>
  </book>
</books>
'''

def books = new XmlSlurper().parseText(xml).declareNamespace([meta:'http://meta/book/info'])
assert books instanceof groovy.util.slurpersupport.GPathResult
assert 4 == books.book.size()
assert 11 == books.breadthFirst().size()
assert 'Groovy in Action' == books.book[0].title.text()
assert 'Groovy Programming' == books.book.find { it.@id == '2' }.title as String
assert [1, 2, 3] == books.book.findAll { it.title =~ /Groovy/ }.'@id'*.toInteger()
assert ['1-932394-84-2', '0123725070'] == books.book.'meta:isbn'*.toString()

We can try the code in Groovy Web Console.

October 11, 2009

Groovy Goodness: Finding Data in Collections

Groovy adds several methods to Collection classes to find elements in the collection. The findXXX() methods take a closure and if an element matches the condition defined in the closure we get a result. We can also use the any() method to verify if at least one element applies to the closure condition, or we use the every() method to everify all elements that confirm to the closure condition. Both the any() and every() method return a boolean value.

def list = ['Daffy', 'Bugs', 'Elmer', 'Tweety', 'Silvester', 'Yosemite']
assert 'Bugs' == list.find { it == 'Bugs' }
assert ['Daffy', 'Bugs', 'Elmer'] == list.findAll { it.size() < 6 }
assert 1 == list.findIndexOf { name -> name =~ /^B.*/ }  // Start with B.
assert 3 == list.findIndexOf(3) { it[0] > 'S' }  // Use a start index.
assert [0,3,5] == list.findIndexValues { it =~ /(y|Y)/ }  // Contains y or Y.
assert [3,5] == list.findIndexValues(2) { it =~ /(y|Y)/ }
assert 2 == list.findLastIndexOf { it.size() == 5 }
assert 5 == list.findLastIndexOf(1) { it.count('e') > 1 }
assert list.any { it =~ /a/ }
assert list.every { it.size() > 3 }

def map = [name: 'Messages from mrhaki', url: 'http://mrhaki.blogspot.com', blog: true]
def found = map.find { key, value -> key == 'name' }
assert found.key == 'name' && found.value == 'Messages from mrhaki'
found = map.find { it.value =~ /mrhaki/ }
assert found.key == 'name' && found.value == 'Messages from mrhaki'
assert [name: 'Messages from mrhaki', url: 'http://mrhaki.blogspot.com'] == map.findAll { key, value -> value =~ /mrhaki/ }
assert 1 == map.findIndexOf { it.value.endsWith('com') }
assert [1,2] == map.findIndexValues { it.key =~ /l/ }  // All keys with the letter 'l'.
assert 2 == map.findLastIndexOf { it.key =~ /l/ && it.value }
assert map.any { entry -> entry.value }
assert map.every { key, value -> key.size() >= 3 }

October 10, 2009

Groovy Goodness: Using Groovy on the Command-Line

We can use Groovy on the command-line to evaluate one-line scripts and pipe output to other commands or use input from other commands. This makes for some command-line scripting. We invoke groovy with the -e argument to evaluate a simple script. We can even use arguments in the script.

Other arguments are -n and -p to process each line of input from a file or from another command. We can also iterate over a list of files, change the contents and use the -i argument to define a backup file pattern when saving the files.

The last argument is -l to start Groovy in listening mode. We can use for example a telnet client to connect to groovy and do some processing.

// Pipe groovy output to grep.
$ groovy -e "Locale.availableLocales.each { println it.displayName }" | grep English

// Or do it all in Groovy.
$ groovy -e "Locale.availableLocales.displayName.findAll { it =~ args[0] }.each { println it }" English

// Using -n and -p to filter each line.
$ groovy -e "Locale.availableLocales.each { println it.displayName }" | groovy -ne "if (line =~ 'English') println line"
$ groovy -e "Locale.availableLocales.each { println it.displayName }" | groovy -pe "if (line =~ 'English') line"

// All will output:
English
English (United States)
English (Malta)
English (United Kingdom)
English (New Zealand)
English (Philippines)
English (South Africa)
English (Ireland)
English (India)
English (Australia)
English (Canada)
English (Singapore)

Starting Groovy in listening mode:

$ groovy -l 9000 -e "println 'You say: ' + line"
groovy is listening on port 9000

$ telnet localhost 9000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Groovy Rocks!
You say: Groovy Rocks!

October 9, 2009

Groovy Goodness: Executing String or List

Groovy adds the execute() method to the String and List classes. When we invoke the execute() we get a Process object back. We can get information from this object with some Groovy added methods. For example to get the output of the command we only have to access the text property. Or we can access the input and output streams to send data to the process or retrieve data from the process.

new File('.').eachFileMatch(~/.*.jpg$/) {
    // Use ImageMagick convert command to create a thumbnail for a JPEG image.
    def converter = "convert ${it.name} -thumbnail 100x100 thumb-${it.name - '.jpg'}.gif".execute()
    converter.waitFor()
    
    if (converter.exitValue()) {
        println "Error creating thumbnail for ${it.name}:"
        println converter.text
    } else {
        println "Created a thumbnail for ${it.name}."
    }
}

// We can also use a List. Useful if arguments have spaces or 
// for shell wildcards like *.
def thumbnail = ["convert", "file.jpg", "-thumbnail", "100x100", "thumb-file.gif"].execute()
thumbnail.waitFor()

println "Exit value: ${thumbnail.exitValue()}"
println "Output: ${thumbnail.text}"

October 8, 2009

Groovy Goodness: Using ConfigSlurper with Configuration Scripts

The ConfigSlurper class can be used to parse Groovy scripts with configuration information. This way we can use a real script instead of a properties file to define configuration information in our applications. In a previous post we saw how to use the ConfigSlurper from Java code and in this post we focus on using it in Groovy code.

Using the ConfigSlurper we can parse Groovy scripts into a ConfigObject. The ConfigObject is a subclass of LinkedHashMap and contains the configuration information. A configuration script contains information defined using dot notation or closures. Because it is a script we can use all Groovy constructs, or use any other Groovy and Java class we want.

To support different configuration settings per environment (for example development, test and production) we can define a special environments section in our script. When we create a new ConfigSlurper instance and use a environment name in the constructor, the environment section is used to determine values. If we don't specify the environment in the constructor the environments section is skipped.

Okay that is a lot of explaining, let's see some code:

// Configuration script as String, but can also be URL, file.
def mail = '''

// Dot notation.
mail.hostname = 'localhost'  

// Scoped closure notation.
mail {  
    // Using Groovy constructs.
    ['user', 'password'].each { 
        this."${it}" = 'secret' 
    }
}

// Environments section.
environments {
    dev {
        mail.hostname = 'local'
    }
    test {
        mail.hostname = 'test'
    }
    prod {
        mail.hostname = 'prod'
    }
}
'''

// Another configuration script.
def app = '''
app {
    version = version()  // Use method in script.
}

// Define method to build version info.
def version() {
    "1.0-${releasedate.format('yyyy_MM_dd')}"
}
'''

// Read mail configuration script for the prod environment.
def mailConfig = new ConfigSlurper('prod').parse(mail)

// We can pass information to the configuration with
// the setBinding method.
def appSlurper = new ConfigSlurper()
appSlurper.setBinding([releasedate: new Date(109, 9, 10)])
def appConfig = appSlurper.parse(app)

// Both configurations are merged into one.
def config = mailConfig.merge(appConfig)

assert 'prod' == config.mail.hostname
assert 'secret' == config.mail.user
assert 'secret' == config.mail.password
assert '1.0-2009_10_10' == config.app.version

October 7, 2009

Groovy Goodness: Reading URL Content

Groovy adds some methods to the URL class which make reading data from an URL easy. For example the text property returns the complete contents of the document that is identified by the URL. Or we can use the eachLine() method to loop through each line of the document. Groovy also adds a toURL() to the String class to make a URL object.

// Contents of http://www.mrhaki.com/url.html:
// Simple test document
// for testing URL extensions
// in Groovy.

def url = "http://www.mrhaki.com/url.html".toURL()

assert '''\
Simple test document
for testing URL extensions
in Groovy.
''' == url.text

def result = []
url.eachLine {
    if (it =~ /Groovy/) {
        result << it
    }
}
assert ['in Groovy.'] == result

url.withReader { reader ->
    assert 'Simple test document' == reader.readLine()
}

October 6, 2009

Groovy Goodness: Creating XML with MarkupBuilder

Groovy has some nice builder classes to create XML. We look at the MarkupBuilder and StreamingMarkupBuilder class in this post. Both allow us to define the XML structure with builder syntax. The MarkupBuilder is good for simple XML, but if we want to add for example namespaces we can use the StreamingMarkupBuilder.

import groovy.xml.*

def writer = new StringWriter()
def html = new MarkupBuilder(writer)
html.html {
    head {
        title 'Simple document'
    }
    body(id: 'main') {
        h1 'Building HTML the Groovy Way'
        p {
           mkp.yield 'Mixing text with '
           strong 'bold'
           mkp.yield ' elements.'
        }
        a href: 'more.html', 'Read more...'
    }
}
println writer

/*
Output:
<html>
  <head>
    <title>Simple document</title>
  </head>
  <body id='main'>
    <h1>Building HTML the Groovy Way</h1>
    <p>Mixing text with
      <b>bold</b> elements.
    </p>
    <a href="more.html">Read more..</a>
  </body>
</html>
*/

def builder = new StreamingMarkupBuilder()
builder.encoding = 'UTF-8'
def books = builder.bind {
    mkp.xmlDeclaration()
    namespaces << [meta:'http://meta/book/info']  // Or mkp.declareNamespace('meta':'http://meta/book/info')
    books(count: 3) {
        book(id: 1) {
            title lang:'en', 'Groovy in Action'
            meta.isbn '1-932394-84-2'
        }
        book(id: 2) {
            title lang:'en', 'Groovy Programming' 
            meta.isbn '0123725070'
        }
        book(id: 3) {
            title 'Groovy & Grails'  // & is converted to &amp;
            comment << 'Not yet available.'  // Or mkp.comment('Not yet available')            
        }
        book(id: 4) {
            mkp.yieldUnescaped '<title>Griffon Guide</title>'
        }
    }
}

println XmlUtil.serialize(books)

/* 
Output:
<?xml version="1.0" encoding="UTF-8"?>
<books xmlns:meta="http://meta/book/info" count="3">
  <book id="1">
    <title lang="en">Groovy in Action</title>
    <meta:isbn>1-932394-84-2</meta:isbn>
  </book>
  <book id="2">
    <title lang="en">Groovy Programming</title>
    <meta:isbn>0123725070</meta:isbn>
  </book>
  <book id="3">
    <title>Groovy &amp; Grails</title>
    <!--Not yet available.-->
  </book>
  <book id="4">
    <title>Griffon Guide</title>
  </book>
</books>
*/

October 5, 2009

Groovy Goodness: GroovyCollections Utility Class

Groovy has a utility class to make combinations of lists or arrays, or to tranpose lists or arrays: GroovyCollections. The class also contains min(), max() and sum() methods, but these are already available as methods on lists and arrays. Let's see the class in action:

def methods = ['min', 'max', 'sum']
def classes = ['Object[]', 'Collection']

def combinations = GroovyCollections.combinations([classes, methods])
assert 2 * 3 == combinations.size()
assert [['Object[]', 'min'], ['Collection', 'min'], ['Object[]', 'max'], ['Collection', 'max'], ['Object[]', 'sum'], ['Collection', 'sum']] == combinations
assert 3 == combinations.findAll { it[0] == 'Collection' }.size()

def keys = ['username', 'email']
def values = ['mrhaki', 'email@host.com', 'not-tranposed']
def transpose = GroovyCollections.transpose([keys, values, [0, 1]])
assert 2 == transpose.size()
assert [['username', 'mrhaki', 0], ['email', 'email@host.com', 1]] == transpose

October 4, 2009

Groovy Goodness: Join Elements to a String

In Groovy we can join elements in a list or array with the join() method to a String. We can set the separator that needs to be between each element. If we don't define a separator the elements are all concatenated together without any separation. The join() method knows when thet last element of the list is reached and no separator is added at the end of the String. Because the end result is a string, all elements are converted to their string counterparts with the toString() method.

def abc = ['a', 'b', 'c']
assert 'abc' == abc.join()
assert 'a::b::c' == abc.join('::')

def numbers = [0, 1, 2, 3, 4, 5] as Integer[]
assert '012345' == numbers.join()
assert '0 x 1 x 2 x 3 x 4 x 5' == numbers.join(' x ')
assert '0 1 2 3 4 5' == numbers.join(' ')

def objects = [new URL('http://www.mrhaki.com'), 'mrhaki', new Expando(name: 'mrhaki'), new Date(109, 10, 10)]
assert 'http://www.mrhaki.com,mrhaki,{name=mrhaki},Tue Nov 10 00:00:00 UTC 2009' == objects.join(',')

// Also great for creating URL query parameters.
def map = [q: 'groovy', maxResult: 10, start: 0, format: 'xml']
def params = map.inject([]) { result, entry -> 
    result << "${entry.key}=${URLEncoder.encode(entry.value.toString())}"
}.join('&')
assert 'q=groovy&maxResult=10&start=0&format=xml' == params

October 3, 2009

Groovy Goodness: Mixin Functionality to Classes

In a previous blog post we learned how to use Categories to add functionality to existing class. We had to use the use keyword to define a block in which the Category was valid. But we can also add new functionality with the @Mixin compile-time annotation or at runtime with the mixin() method (GDK extension to Class).

class Pirate {
    def talk(text) {
        "Aargh, walk the plank. ${text}"
    }
}

// Compile time mixin to Talk class. This add all
// methods from Pirate to Talk.
@Mixin(Pirate)  
class Talk {}

assert 'Aargh, walk the plank. Give me a bottle of rum.' == new Talk().talk("Give me a bottle of rum.")
import org.apache.commons.lang.StringUtils

class Parrot {
    static String speak(String text) {
        /Parrot says "$text"/
    }
}

// Runtime mixin on String class. 
// mixin() is a GDK extension to Class.
String.mixin Parrot, StringUtils

assert 'Parrot says "mrhaki"' == 'mrhaki'.speak()
assert 'Groovy is so much...' == 'Groovy is so much fun.'.abbreviate(20)  // StringUtils mixin.

October 2, 2009

Running Multiple Versions of Groovy or Grails

I use Cygwin on my Windows system to run Groovy and Grails applications. I have several versions of both Groovy and Grails on my system. Sometimes I need to run for example an application with Groovy version 1.6.4 or 1.6.5, or a Grails application with version 1.1 or 1.1.1. I set up aliases for all versions I want to run in my ~/.bashrc so I can pick the Groovy or Grails version I need without much effort.

alias groovy164='/usr/java/groovy/groovy-1.6.4/bin/groovy'
alias groovyConsole164='/usr/java/groovy/groovy-1.6.4/bin/groovyConsole'

alias groovy165='/usr/java/groovy/groovy-1.6.5/bin/groovy'
alias groovyConsole165='/usr/java/groovy/groovy-1.6.5/bin/groovyConsole'

alias groovy17beta1='/usr/java/groovy/groovy-1.7-beta-1/bin/groovy'
alias groovyConsole17beta1='/usr/java/groovy/groovy-1.7-beta-1/bin/groovyConsole'


alias grails111='/usr/java/grails/grails-1.1.1/bin/grails'
alias grails11='/usr/java/grails/grails-1.1/bin/grails'
$ groovy164 --version
Groovy Version: 1.6.4 JVM: 1.6.0_14

$ groovy165 --version
Groovy Version: 1.6.5 JVM: 1.6.0_14

$ groovy17beta1 --version
Groovy Version: 1.7-beta-1 JVM: 1.6.0_14

Groovy Goodness: Expando as Dynamic Bean

The Expando class in Groovy is sort of a dynamic bean. We can add properties and we can add closures as methods to an instance of the Expando class. This is useful if we don't want to create a new class for a simple bean.

def user = new Expando(username: 'mrhaki')
assert 'mrhaki' == user.username

// Add an extra property.
user.email = 'email@host.com'
assert 'email@host.com' == user.email

// Assign closure as method. The closure can
// take parameters.
user.printInfo = { writer ->
    writer << "Username: $username"
    writer << ", email: $email"
}

def sw = new StringWriter()
user.printInfo(sw)
assert 'Username: mrhaki, email: email@host.com' == sw.toString()

October 1, 2009

Groovy Goodness: Create a Singleton Class

Creating a singleton class in Groovy is simple. We only have to use the @Singleton transformation annotation and a complete singleton class is generated for us.

package com.mrhaki.blog

// Old style singleton class.
public class StringUtil {
    private static final StringUtil instance = new StringUtil();

    private StringUtil() {
    }

    public static StringUtil getInstance() { 
        return instance;
    }
    
    int count(text) { 
        text.size() 
    }
}

assert 6 == StringUtil.instance.count('mrhaki')

// Use @Singleton to create a valid singleton class.
// We can also use @Singleton(lazy=true) for a lazy loading
// singleton class.
@Singleton 
class Util {
    int count(text) {
        text.size()
    }
}

assert 6 == Util.instance.count("mrhaki")

try {
    new Util()
} catch (e) {
    assert e instanceof RuntimeException
    assert "Can't instantiate singleton com.mrhaki.blog.Util. Use com.mrhaki.blog.Util.instance" == e.message
}