Performance Zone is brought to you in partnership with:

Hi all, my name is Hubert A. Klein Ikkink. Not a very common name, right? To make things easier I just picked the first letters of my firstname and surname and came up with haki. So there you have it, now I am also known as Mr. Haki or mrhaki for short. You can read more blog postings at www.mrhaki.com. I am a passionate Groovy and Java developer based in Tilburg, The Netherlands. My goal is to write clean, elegant, user-centered and high quality software. You can find me on Google+ and Twitter. Hubert is a DZone MVB and is not an employee of DZone and has posted 162 posts at DZone. You can read more from them at their website. View Full User Profile

Groovy Goodness: @Builder Definition with Extra Type Checks

05.10.2014
| 3537 views |
  • submit to reddit

We have seen some features of the @Builder AST transformation in previous and other blog post. We can use another strategy to let the AST transformation generate a class where the class only has a constructor that accepts a builder class. And with @CompileStatic we can even make sure that all required properties must have a value set by the builder before the constructor accepts the argument. We use the builderStrategyannotation parameter and set it to InitializerStrategy:

import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy

@Builder(builderStrategy = InitializerStrategy)
class Message {
    String from, to, subject, body
}

def message = Message.createInitializer()
        .from('mrhaki@mrhaki.com')
        .subject('Groovy 2.3 is released')

// Returned object is not Message, but
// internal class Message$MessageInitializer
assert !(message instanceof Message)

// Now we can use the initializer in the
// only constructor of Message.
def messageInstance = new Message(message)

assert messageInstance instanceof Message
assert messageInstance.from == 'mrhaki@mrhaki.com'
assert messageInstance.subject == 'Groovy 2.3 is released'

We can customize which properties need to be set with the includes and/or excludes annotation parameter. We can also customize the name of the method that create the builder instance with the parameter builderMethodName:

package com.mrhaki.blog.groovy

import groovy.transform.CompileStatic
import groovy.transform.builder.Builder
import groovy.transform.builder.InitializerStrategy

@Builder(builderStrategy = InitializerStrategy,
        excludes = 'body',
        builderMethodName = 'creator')
class Message {
    String from, to, subject, body
}

// With @CompileStatic the compiler will check
// that all properties defined in the @Builder
// configuration are set. This way we can
// implement required properties for a class
// that need to be set before the object can
// be created.
@CompileStatic
def createMessage() {
    def messageInit = Message.creator()
            .from('mrhaki@mrhaki.com')
            .to('mail@host.nl')
            .subject('Groovy 2.3 is released')

    def message = new Message(messageInit)
    message
}

final Message message = createMessage()

assert message.from == 'mrhaki@mrhaki.com'
assert message.subject == 'Groovy 2.3 is released'

Code written with Groovy 2.3.

Published at DZone with permission of Hubert Klein Ikkink, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)