Using groovy to generate java sources in maven

In this article I’ll briefly cover how to use Groovy to generate java sources as part of a maven build.

There are times when you need to generate Java source which is either repetitive, based on external data or both. Now there are tools out there for some tasks like this, but for most simple tasks running a groovy script is more than enough.

Now for the purposes of this article, I’m going to presume we need an enum which represents the cards in a Standard deck of cards, one entry per card.

First we need to create our groovy script. Now the best place to put this is in the src/main/script directory of your project. Here’s the script for this (writing groovy is not in scope for this article) which goes into the file src/main/script/CardDeckGen.groovy:

class CardDeckGen {

    public generate( project, String packageName, String className ) {

        // Where to write the classes
        File targetDirectory = new File( project.build.directory + '/generated-sources/groovy' )

        // The directory to write the source to
        File packageDir = new File( targetDirectory, packageName.replace( '.', '/' ) )

        // Now to create our enum
        def out = []
        out<<'package '+packageName+';\n'
        out<<'public enum '+className+' {\n'

        // We have four suits
        def suit = [ 'D', 'S', 'H', 'C']

        // Each suit has A, 2-9, T, J, Q & K
        def rank = [ 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' ]

        // For each suit, write an entry for each card
        suit.eachWithIndex {
            s, i -> def indent = i==0 ? '    ' : ',\n    '
            rank.each {
                r -> out<< indent + s + r
                indent = ','
            }
        }

        // Mark the end of the enum list
        out<<';\n'

        // Finish the enum class
        out<<'}\n'

        // Convert the array into a string
        StringBuilder sb = new StringBuilder()
        out.each { sb.append(it) }

        // Now write the source, ensuring the directory exists first
        packageDir.mkdirs()
        new File( packageDir, className + ".java" ).write( sb.toString() );
    }

}

Next we need to get maven to run this script, so in pom.xml we first need to make sure we are using the correct version of the jdk – 1.5 or 1.6 would be enough:

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.6</source>
        <target>1.6</target>
    </configuration>
</plugin>

Next groovy, here we add the gmaven-plugin which runs a small code snippet calling our class:

<plugin>
    <groupId>org.codehaus.groovy.maven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <scriptpath>
                    <element>${basedir}/src/main/script</element>
                </scriptpath>
                <source>
                    CardDeckGen cdg = new CardDeckGen()
                    cdg.generate( project, 'uk.org.retep.example', 'CardDeck' )
                </source>
            </configuration>
        </execution>
    </executions>
</plugin>

Now that’s enough to generate our enum, however maven doesn’t know about it so it wont compile. To do that we need to add it so the compiler picks it up:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>add-groovy-sources</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>add-source</goal>
            </goals>
            <configuration>
                <sources>
                    <source>${project.build.directory}/generated-sources/groovy</source>
                </sources>
            </configuration>
        </execution>
    </executions>

Now you can run maven.mvn clean install
If all goes well you’ll get a maven artifact containing an enum:

package uk.org.retep.example;
public enum CardDeck {
    DA,D2,D3,D4,D5,D6,D7,D8,D9,DT,DJ,DQ,DK,
    SA,S2,S3,S4,S5,S6,S7,S8,S9,ST,SJ,SQ,SK,
    HA,H2,H3,H4,H5,H6,H7,H8,H9,HT,HJ,HQ,HK,
    CA,C2,C3,C4,C5,C6,C7,C8,C9,CT,CJ,CQ,CK;
}

This was a simple example but quite a powerful one. I’ve used this technique for generating more complex versions of Card’s to classes based on data contained within RFC’s (STRINGPREP etc).

For help on writing Groovy stripts take a look at the Groovy Getting Started Guide.

Author: petermount1

Prolific Open Source developer who also works in the online gaming industry during the day. Develops in Java, Go, Python & any other language as necessary. Still develops on retro machines like BBC Micro & Amiga A1200

2 thoughts on “Using groovy to generate java sources in maven”

  1. Have you figured out how to get GMaven use the Groovy 1.6.x compiler. The sparse documentation at Codehaus didn't show how to accomplish this.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: