Developer's Guide

This document is a work in progress...

Help Wanted

The RevGen team welcomes anyone who has something to contribute. Please contact Richard Easterling (richard at JavaGen.com) to coordinate efforts.

Have a look at the TODO list for ideas.

Foundation Code

RevGen is simply a collection of templates, a configuration file and a few classes specific to generating Java code from database schemas. All the models, template handling and generation framework code is handled by JavaGen Agile. Please see the JavaGen Agile Developer's Guide.

Developing a new code generation module

Developing a new code generation module can be broken down into three broad steps:

  1. Create a model representation

    Creating the model may be just a matter of reusing one of the existing model modules or creating a whole new model hierarchy. Ideally models will not have any implementation details, just descriptive attributes.

  2. Populating the model

    Models can be populated from

    • an external source (DbLoader)
    • by transforming one model hierarchy to another (DbTransformerPass1)
    • by decorating an existing model hierarchy (LinkTableFinderVisitor)

    Often you'll use a combination of these techniques to construct your model. In fact, by breaking each discrete step into a separate visitor class, your code will be more flexible and reusable. Each visitor class can then be configured and sequenced within the pipeline to suite the user's needs.

  3. Write the templates to generate code from the model

I haven't figured out a good, fast way to unit test the template output so I usually invoke RevGen directly using something like this during the development phase:

SpringMain.main(new String[] {"classpath:biosql.properties", "classpath:RevGenSpringConfig.xml"});

I'll setup a temporary Eclipse project and point the generated output at that project in the property file:

applicationName=biosql
targetDirectory=../${applicationName}

And make sure the results compile by refreshing the project. See itests/sandbox for an example.

Then I write an integration test and put it in the itests folder and invoke it from the pom.xml with the properties specific to the new feature:

<build>
        <defaultGoal>test</defaultGoal>
        <plugins>
                <plugin>
                        <groupId>org.javagen.revgen</groupId>
                        <artifactId>maven-revgen-plugin</artifactId>
                        <version>1.0-beta1</version>
                        <configuration>
                                <sourceDirectory>${project.build.directory}/generated-sources/revgen-main/</sourceDirectory>
                                <testSourceDirectory>${project.build.directory}/generated-sources/revgen-test</testSourceDirectory>
                                <resourceDirectory>${project.build.directory}/generated-sources/revgen-resources</resourceDirectory>
                                <properties implementation="java.util.Properties">
                                        <extensionByInheritance>true</extensionByInheritance>
                                        <genEntityNameTemplate>#{modelName}Gen</genEntityNameTemplate>
                                </properties>
                        </configuration>
                        <executions>
                                <execution>
                                        <goals><goal>revgen</goal></goals>
                                </execution>
                        </executions>
                        <dependencies>
                                <dependency>
                                        <groupId>hsqldb</groupId>
                                        <artifactId>hsqldb</artifactId>
                                        <version>1.8.0.7</version>
                                </dependency>
                        </dependencies>                         
                </plugin>
        </plugins>
</build>

This could probably be more streamlined, so please let me know if you come up with something better!

Eclipse Tips

Generate an Eclipse project for RevGen:

 mvn eclipse:eclipse

Use the Maven 2 Eclipse Plugin.

Use the FreeMarker Eclipse Plugin.

By commenting out the javagen-agile dependency in the revgen pom.xml file and making javagen-agile a required project, you can edit both frameworks at once. This is a bit of a hack, so if you can figure out a better way of achieving the same result, I'm all ears!

FreeMarker Tips

FreeMarker is a more capable template engine than Velocity, however it is a lot less forgiving of null property values and type conversions. The most common problem I run into is null property values and I've wasted a lot of time misinterpreting the resulting cryptic error messages, so my advise is to always check for this first. You can do things like this in your template:

<#if foo?exists> ...</#if>

TODO

  • setup wiki
  • continuous integration server
  • composite/embedded object support
  • template modularization
  • collection support beyond SET
  • link table support for one-to-one and one-to-many relations
  • versioning/timestamp support
  • basic Eclipse plugin
  • Eclipse plugin with round-tripping support using @generated annotation
  • basic NetBeans plugin.
  • cleanup XML serialization by removing redundant/default settings
  • complete integration tests for property type and reference mappings
  • automated integration tests that combine various configuration settings - ie dynamic POMs
  • full mapping support in orm.xml file (use hbm.xml.ftl template as a reference)
  • are single column foreign keys supported to compound primary key tables in JPA/Hibernate 3.2? Need a working example
  • support timestamp for regeneration triggering in revgen plugin
  • Generated GUIs: JSF, SWT, Swing, Trails, Grails, ?