Skip to content

Building The Perfect Beast

Building object instances: soul-killing drudgery or trivial annoyance?

Are you one of those who, when asked to build an object with a large set of properties, gnash their teeth and wail “there must be a better use of my precious life-line than this?” Do you simply accept that when life throws a bunch of unset properties in your direction, all you can do is roll up your sleeves and get setting?

If you are in the former camp, rather than the latter, then Groovy 2.3 has something good for you!

Introducing the groovy.transform.builder package…more ways to create an object than you can shake a mouse at!

Building complex objects is now as easy as pie, as the following little example shows.

import groovy.transform.*
import groovy.transform.builder.*

// NB: 'true' Gb
Long.metaClass.getGb = { -> delegate.longValue() * 1024L * 1024L * 1024L }
Double.metaClass.getInch = { -> 2.54D * delegate.doubleValue() }

@ToString(includeNames=true)
@Builder
class User {
    String name
    String extension
}

@ToString
@Builder(builderStrategy=SimpleStrategy, prefix="", excludes=['id'])
class Computer {
    UUID id = UUID.randomUUID()
    String vendor
    String type
    Double screen  // cm
    Long ram       // bytes
    Long disk      // bytes
    User user
}

// need a class to embed logging into
@groovy.util.logging.Log
class Main {
    void goForIt() {
        def built = new Computer()
                        .vendor("Apple")
                        .type("Macbook Pro")
                        .screen(15.6D.inch)
                        .ram(16L.gb)
                        .disk(512L.gb)
                        .user(User.builder().name("Bob").extension("1234").build())
    log.info built.toString()
    }
}

new Main().goForIt()

Take a good look at the above; there are actually two styles of builder in use here: Computer and User configure the builder facility in two different ways.

A picture paints a thousand words, as they say:

Choice is good, no?

This is only a quick overview of what is actually a very configurable facility that probably has enough in it to satisfy all but the most rabid properties setter hater.

Never again should you write Groovy code like this:

Thing t = new Thing()
t.something('x')
t.somethingElse(42)
t.kill(8)
t.me('now')

I’ll be watching!

It is worth taking a look at the documentation to see what else this new feature can do to help you reclaim your life and dignity.

Just for the hell of it, I have also thrown in the very useful @ToString and @Log annotations…what fun!

I have also done a teeny-tiny bit of metaprogramming: take a look at how Long and Double are modified to give us a taste of DSL-y goodness.

And just to wrap things up neatly, be aware that Groovy has always had a few tools to make your life easier: the documentation specifically calls out the with statement (which I’ve raved about before) and maps as named parameters.

We’re spoiled for choice, we really are!

PS: I took the title for this posting from the title of Don Henley’s excelllent second album. Music to angrily program by!

Tags: ,

C, Java Enterprise Edition, JEE, J2EE, JBoss, Application Server, Glassfish, JavaServer Pages, JSP, Tag Libraries, Servlets, Enterprise Java Beans, EJB, Java Messaging Service JMS, BEA Weblogic, JBoss, Application Servers, Spring Framework, Groovy, Grails, Griffon, GPars, GAnt, Spock, Gradle, Seam, Open Source, Service Oriented Architectures, SOA, Java 2 Standard Edition, J2SE, Eclipse, Intellij, Oracle Service Bus, OSB