Introduction: why would you ever want to generate Java code?
In my current project at work we have quite a few value objects with giant constructor methods; these behemoths take 20 to 30 arguments each and it’s crucial that you get all of them in the right order, which is a pain in those cases when you’re only really interested in setting one or two of them. Just as an example, let’s just say that these classes looks something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
About a year ago or so we started using the
Builder pattern, creating a separate Builder class for
each value object class. The builder has one setter method for each
parameter, and one
create() method that instantiates the new object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Since the setter methods return a reference to the builder itself it is possible to chain invocations:
However convenient these builder classes are to use, I very quickly tired of maintaining them. Every time you add or remove a property to a value object, you also need to make the corresponding change to the builder. Keeping two classes in sync doesn’t seem like too much work, but it is unnecessary, and it occurred to me that I could probably write something to generate the builders automatically.
Writing a Maven plugin
We use Maven for our builds. Ok, ok, I know. Maven is horrible, maven downloads the whole universe, maven is braindead. Yes, I know all these things. But here’s the ting: Maven is like democracy: It’s not perfect, but it’s the best we have.
One of the nice things about maven is that it has a well-defined
standard build lifecycle. The build process is divided into steps, and
during one of the steps,
generate-sources, a maven plugin has the
opportunity to generate source that will then be compiled during the
When invoked, we’d like the plugin to:
Loop over our java classes, looking for constructors marked with our custom
For each matching constructor, generate a new source file under
target/generated-sources/builderbuilder/containing the Builder class.
The plugin is invoked before the compilation step, meaning that all the generated code will be included in the final output.
As an example, this code (in
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Will generate the following (in
target/generated-sources/builderbuilder/example/CatBuilder.java) when run through our plugin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
For those of you who like to read along, the code for the whole plugin
is on github. The finished version has some extra bells and
whistles, like the ability to generate abstract builder classes and
explicitly the name of the
Parsing Java code
Okay, so let’s say we want to pick apart the java class files and for
each constructor found we want to generate a helper class as discussed
above. Now, normally we’d use the introspection facilities already
built into java, but now we have one problem: our code-generating code
will run during the
generate-sources step, before any compilation
has actually taken places.
This is a problem. What we need is a java parser that can pull apart
the relevant bits of the source files and give us enough information
that so we can generate the new classes. Preferably the level of
detail should be on par with with that of the
functions, and it should also be fast. I actually started writing
something like that, but that’s another story. Instead,
let’s check out QDox, an amazing little library used
internally by maven.
Using it is pretty simple. First, create a new
and tell it where the source code you want to parse lives:
1 2 3 4
Then loop over all known classes and generate the builder:
1 2 3
Generating the output
This is the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
This is all pretty straightforward; we loop through the methods for
the class, looking for a constructor that has the
Lines 6-12 checks if the tag has any values specified for
package, reverting to default values if not.
Lines 14-23 instantiates a new
StringTemplate object and supplies it
with values for the
attributes (the latter being the class that we want the builder to
actually build). Lines 19-23 loops through the constructor arguments
and creates value object holding the name & type of each.
Finally, a new file is created (lines 25-26) and written (lines 28-34).
There are an abundance of templating frameworks out there. I choose to go with StringTemplate for this project, since it makes it easy to use subtemplates in a functional way, and generally fits my way of thinking. I could just as easily have used something like FreeMarker or Velocity, though.
The templates are not that interesting, so I won’t go into it here. You can check them out on github if you are curious.
Automatic code generation in java projects is not only feasible, but also quite convenient with maven. We’ve been using BuilderBuilder internally in production for a few months now, and it greatly cuts down on code maintenance.
It would be nice, though, if there was a more general approach to code generation. Just for BuilderBuilder, I had to dive into Maven internals (which are surprisingly poorly documented), learn QDox (ditto) and write all the java code that solved this particular problem. Imagine instead if there was some kind of transformation language that operated on java sources, kind of like what XSLT does for XML? Now, that would be cool.