Code Generation done right…

Code Generation solves a lot of problems. And everybody uses it all the day: Ever generated Getters/Setters using your IDE? Or method stubs? Or constructors?

And sometimes complete classes are generated. One famous example is Hibernate that is able to generate Java classes from a database schema.

Most of the projects I have seen so far use a templating engine (FreeMarker or Velocity) to create the source files. Hibernate switched from Velocity to FreeMarker some years ago…

This approach is quite good for simple cases. Those can be solved quite fast using that approach.

Complexity

But things get worse, if you have to generate more sophisticated code. Of course FreeMarker supports conditions and you can do quite amazing things using complex model classes. On the other hand those templates start to get really complicated and hard to debug over time.
And of course you always have two sources: The template file and your data model.

Imports

One thing special to Java source files are the imports. When you conditionally use a class somewhere, you also have to add the import statement conditionally… Nothing that can be solved easily using FreeMarker.

So sometimes one might wish to have a nice API that does all the dirty work for you…

The alternative: Codemodel

I have looked around to find such an API. And it took me quite a long time to find one.
And that API is quite near beside you. Just a little bit hidden.

JAXB has a sub project called codemodel. This is an API that allows you to create Java classes by just using an API…

How to use Codemodel

There is no separate jar for codemodel. But the classes are shipped with every JAXB installation. So since JDK 1.6 the classes are just here and waiting to be used. But since they have renamed the package as “internal” I suggest to import the JAXB jar manually:

For Maven users this should be enough:

<dependency>
  <groupId>com.sun.xml.bind</groupId>
  <artifactId>jaxb-xjc</artifactId>
  <version>2.2.1</version>
</dependency>

A quick introduction

The API is not perfect yet. And it is not documented very well. But it is nearly complete and I didn’t miss much.
Here is a short example that should give you a fast start:

JCodeModel codeModel = new JCodeModel();
JDefinedClass foo = codeModel._class( "a.b.c.Foo" ); //Creates a new class

JMethod method = foo.method( JMod.PUBLIC, Void.TYPE, "doFoo" ); //Adds a method to the class
method.body()._return( JExpr.lit( 42 ) ); //the return statement

The code can be written to the file system. But it can also be written to a single output stream. This is great for testing:

ByteArrayOutputStream out = new ByteArrayOutputStream();
codeModel.build( new SingleStreamCodeWriter( out ) );

This code outputs that code:

-----------------------------------a.b.c.Foo.java-----------------------------------

package a.b.c;

public class Foo {

public void doFoo() {
return 42;
}

}

Great, isn’t it?


27 Responses to “Code Generation done right…”

  • Nicolas Says:

    Well in fact, I use FreeMarker to generate the code I need.

    You mention the import thing.

    Well i made it work like that :

    - Each part of the code (whatever it is : method, field, constructor…) just provide the types they need (package + short name).

    Then a small algorythm is used to manage types :

    - some will be imported and shortName will be used for the type in the code.
    - in case of shortName conflict, the full name is used in the code.

    Basically this whole system is just a few line of code and not a problem at all.

    I’d say simply you need to divide your template into smaller parts. For exemple I have a class that can “render” any Type. The type can be renderred with or without the package prefix. I have another class for rendering imports. And the problem is simply solved.

    For other part, I have one template for fields in a class, for methods. On specialised for getters, setters, toString, equals and hashcode methods.

    Most templare are, one line long, maybe up to 3 to 5 lines long. No more.

    If I want to make a java bean with arbitrary numbers of fields, it’s just like 15 lines of java code i need to write. No more.

    Basically i managed to generate in a matter of day, just using java, JaxB (but for reading XML, not generating code) & FreeMarker :
    - Facade code (class & interface)
    - bean (with localized formating of numbers and dates) (Abstract generated implementation + concrete implementation you can change without you code being deleted each time you regenerate).
    - bo (business objects used by hibernate)
    - hibernate mapping
    - SQL code for stored procedures
    - code that transform bo into bean, and bean to bo.

    And this including, the XML parsing, full Unit Test suite of the code, javadoc documentation… It’s used now for all new developpmeents, it’s simple to use and extends as needed.

  • Larry Says:

    Yeah, now try to do something useful with it. It’s a lot harder than what you think. Cheers.

  • Dave Says:

    Why not use one of the existing libraries, like Javassist?

  • matto Says:

    Wow, nice project. I just wonder why it was not mentioned somewhere earlier.

  • johannes Says:

    Of course using templates is possible. And for simple cases it is enough.

    But there is a time, when using a “real” API is much more productive. And I think one reaches that point quite fast…

  • johannes Says:

    1. Codemodel is one of the existing libraries. And it is shipped with the JDK…

    2. Javassist is something completely different (at least as far as I understand):
    Javassist modifies the byte code of (existing) classes at loadtime.
    Codemodel allows you to generate Java source files (that have to be compiled).

  • johannes Says:

    I did (for http://serialization.cedarsoft.com – upcoming release).

    It needs some time to understand how to use the API, but the results are very satisfying (at least for me).

  • Vineet Sinha Says:

    Nice project – thanks for pointing it out.

    My view of things is that different project excel at different types of code generation. It would be great to see a comparison of some of them.

    I do know that the Eclipse Modeling world (http://www.eclipse.org/modeling/) has a number of libraries but I have only had guesses as to their strengths (power but complex side of code generation).

  • johannes Says:

    “different types of code generation”: Unfortunately I just know template engines based approaches and Codemodel.
    If you find any alternative, I’d be glad to hear about it…

    I don’t know any code generation library at eclipse. Do you have more informations?

  • Nicolas Says:

    johannes :
    Of course using templates is possible. And for simple cases it is enough.
    But there is a time, when using a “real” API is much more productive. And I think one reaches that point quite fast…

    Some compilers use templates for the code they generate and it works perfectly… It’s an an advenced case, isn’t it ?

    The solution shown here by you for codemodel share the same system as many code generation tools :

    You construct a tree of objects. And each object know how to render itself.

    Some API will use templates so using the same tree could result in several outputs. Some API will hardcode how to render in the object itself…

    I agree that using a full API that already exist is nice, but saying that using template works only for simple cases is not true.

  • epo Says:

    Another neat solution is to use Acceleo (http://eclipse.org/acceleo/),

    This is an eclipse project, that is based on the OMG standard M2T and XMI.

    It allows import management(like described in your post), complex projects
    and classes, you keep template to help maintenance.

    and the last release offers your engine to be embedded by picking some jars.

    Anf for me a killer feature, I did found in any of the precited is the
    ability to keep chosen snippet of code when re-genations of code.

    I use this in my projects and in one of my clients and it goes very well.

    Epo

  • Dave Says:

    Javassist can create classes at runtime as well.

  • Tweets that mention Code Generation done right… | Just Java -- Topsy.com Says:

    [...] This post was mentioned on Twitter by Richard Laksana, Jens Schauder. Jens Schauder said: Code Generation done right… | Just Java: http://blog.cedarsoft.com/2010/08/code-generation-done-right/ [...]

  • Karsten Says:

    Oh dear, welcome to the past. Could you really imagine to write complex code generators that way? Have you really done a none trivial example? I guess you would find out that template based engines are the most usable for complex situations. If you find that import organization is one major reason why template based approaches fail, then you might be looking for the wrong ones. OK, Velocity and Freemarker don’t support this, but import organization can be solved by postprocessing also in their case, and it is common practice. I’m implementing code generators in huge customer projects every day, and there are far more requirements to handle for code generation than just instantiating Java types. There is a world outside of Java code, even within Java projects. And then? Write another code generator engine? Have a look at Eclipse Modeling, you will find some advanced tooling there. Of course it requires a bit learning, but real world scenarios need what you find there.

    Just my 2 cents,
    ~Karsten

  • Alex Says:

    I know a rather widespread plugin that does code generation using an API style (so, absolutely not using a template engine): the JDT!

    Java Plugins for eclipse (the most important is the Java refactory plugin) work on API basis rather than a template engine.

    Actually, the JDT API is mixed: for example, when you create a method, its body can be expressed using API _OR_ using a String (the body content) so the JDT actually behaves with both styles, and what’s more important is permits to MIX them with a great flexibility.

    Look for org.eclipse.jdt.core.dom

  • johannes Says:

    Just as side note: Codemodel also allows you to add “raw strings” to a method. But of course there is no template engine build in.

    JDT: Is this usable as standalone API?
    IntelliJ also has a very nice API used for their code parsing stuff…

    But probably those approaches are only useful for very large and very complex scenarios.

  • johannes Says:

    “keep chosen snippet”: This is some sort of love/hate feature…
    I know it is very handy, but I also think it might be a bad smell, if it is necessary…

    So I try to avoid that as good as I can.
    But thanks for the hint, I will take a look at that library. Thanks.

  • johannes Says:

    Yes, I can imagine writing complex code generators that way. I can’t imagine writing them based on a template engine.

    But maybe it depends on what type of complexity you have in your project:

    “Complexity” in terms of:
    - A lot of boilerplate code (that is static in terms of code generation.
    Then yes, templates are a lot easier.
    -Very “dynamic” code: How could that be solved with templates?

  • Tedi Says:

    Great article – I was just looking for that.
    Thanks a lot,

  • Tedi Says:

    Hi, any chances you know how to make a variable generic? I want to generate List myVar; I am able to generate List myVar with the following code:

    JFieldVar property = clazz.field(JMod.PRIVATE,
    List.class, myVar);

    But no luck finding a way to make it generic.

    Thanks,

    Tedi

  • Denis Robert Says:

    Look at JClass.narrow()

  • Amit Says:

    Can you please share a snippet for creating setter method?

    eg.

    public void setName(String name) {

    this.name = name;
    }

  • Amit Says:

    Here is the snippet for setter method.

    JMethod setterMethodId = address.method(JMod.PUBLIC, Void.TYPE, “setId”);
    setterMethodId.param(String.class, “id”);
    setterMethodId.body().assign(JExpr._this().ref(“id”), JExpr.ref(“id”));

    If anyone has better solution, please share

  • richard Says:

    i try to add method to existing java file but i cant get defined class ref.

    CodeModel cm= new JCodeModel();
    JPackage jp = cm._package(packageName);
    JDefinedClass dc = jp._getClass(“Test”);

    at this point dc is null? how can i get defined class ref?

  • Cem Koc Says:

    Richard, I have same problem? Could you resolve this problem? It seems that adding to existence classses is not possible?

  • Plugin für XJC, Teil 2 | Kaffee Um Eins Says:

    [...] Code generation done right Gefällt mir:Gefällt mir Lade… Dieser Beitrag wurde unter Java, JAXB, XJC abgelegt und mit Codemodel, Custom, Getter, Java, Plugin, Setter, source code generation, XJC, XML, XSD verschlagwortet. Setze ein Lesezeichen auf den Permalink. ← Plugin für XJC, Teil 1 [...]

  • michal Says:

    Hey,
    is there a possibility that when I’m making a field in a class using JFieldVar, I may use Class or JType that doesn’t exist yet?

Leave a Reply