Tuesday, May 12, 2009

Generated Java-XML bindings and external builders in Eclipse

Our project is using the Apache XMLBeans tool to bind XML schemas to Java code.

One possibility to deal with the bindings is to generate them on a local machine and check in the generated code. The drawback is that people maintaining the code need to deal with all sorts of file operations for things as simple as a namespace change. The Java bindings wiggles at the will of its source XSD file, so that checking it in is not far from checking in a generated JAR or WAR file.

The other possibility is to generate the code during build time, using the xmlbean ant task, which would be sort of annoying for developers using the Eclipse environment. Whenever the project was imported anew from the source control system, they would have to first invoke the generation target and then refresh their workspace.

It turns out Eclipse has a great solution for this, in the form of a project builder.


I created a new builder, which invoked the correct ant target every time a developer used "clean" or "build".

That was it for the easy part. The next trick was to make the Ant target as efficient as possible, since it would be impractical for developers to wait several seconds for the "xmlbean" task completion every time they did something as simple as updating an unrelated Java source file.

That is when the Ant conditional targets come in handy. It was only a matter of setting a property if the files had never been generated or if the source XSD file was updated after they had been generated.

<property name="xmlbean.javac.optimize" value="on" />
<property
name="xmlbean.verbose" value="false" />
<property
name="xmlbean.quiet" value="true" />
<property
name="design.info.schema" value="${dir.schema}/DesignInfo.xsd" />

...

<condition property="xmlbean.designinfo.updated">
<or>
<not>
<available
file="${dir.build.xml.classes}" />
</not>

<uptodate targetfile="${design.info.schema}">
<srcfiles
dir="${dir.build.xml.classes}" />
</uptodate>
</or>
</condition>

 

<target name="genxmlbeans.designinfo" if="xmlbean.designinfo.updated">

<xmlbean schema="${design.info.schema}"
classgendir="${dir.build.xml.classes}"
classpathref="class.path"
failonerror="true"
optimize="${xmlbean.javac.optimize}"
verbose="${xmlbean.verbose}"
quiet="${xmlbean.quiet}" />

</target>

No comments:

Post a Comment