The next screen snapshot demonstrates that I'm using JDK 1.7.0 build 134 and its associated JAXB 2.2.3 implementation's xjc for the examples in this post.
This is the version of JAXB included with Java 7 (JAXB was also delivered with Sun's Java SE 6 JVM). The next screen snapshot shows the
xjc
binding compiler's usage statement with the part about DTD support highlighted.The last screen snapshot tells us that
xjc
can generate Java classes from DTD by specifying the -dtd
option. However, it also warns us that this DTD support is "experimental" and "unsupported."For my simple example, I'm going to use a well-known DTD: log4j.dtd.
It is very simple to use
xjc
with a DTD. The following command, for example, will generated Java classes based on the log4j.dtd
:xjc -dtd -d generatedsrc -p dustin.examples log4j.dtd
This examples places the generated Java classes in a subdirectory called
generatedsrc
and creates subdirectories dustin\examples
so that these generated classes are part of the dustin.examples package
. The next screen snapshot proves that this worked.It is often preferable to include generation of Java classes as part of an Ant build rather than from the command-line. The JAXB reference implementation includes support for a custom Ant task called xjc. The following snippet of XML code demonstrates using this custom task to generate Java files from the same
log4j.dtd
as used before.<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask"> <classpath> <fileset dir="C:\Users\Dustin\Downloads\jaxb-ri-20110412\lib" includes="jaxb-xjc.jar" /> </classpath> </taskdef> <target name="generateLog4jJavaClasses" description="Generate Java classes from DTD with JAXB's xjc"> <property name="ant.xjc.target.dir" value="antgenerateddir" /> <mkdir dir="${ant.xjc.target.dir}" /> <xjc destdir="${ant.xjc.target.dir}" package="dustin.examples" schema="log4j.dtd"> </xjc> </target>
When I only use the JAXB/xjc included with the Java SE 7 distribution, the XJCTask class is not readily available to support the
xjc
Ant task. To use this, I need to download the reference implementation, which does provide the JAR with the XJCTask class. I like to match the same version of the JAXB RI as is included with the Java distribution when possible. That's JAXB 2.2.3 in this case (Java SE 7). The executable JAR JAXB2_20110412.jar unzips its contents into a new subdirectory (C:\Users\Dustin\Downloads\jaxb-ri-20110412
in this case). The XJCTask
class needed for the Ant custom task is in the JAR file (jaxb-xjc.jar
) and directory (C:\Users\Dustin\Downloads\jaxb-ri-20110412\lib
) provided specified in the taskdef
. However, the above XML does not include any reference to DTD type and the output from trying to build with it is shown next.The WARNING message ["Are you trying to compile DTD? Support for DTD is experimental. You may enable it by using the -dtd option."] is pretty good at hinting at what is likely the problem (schema is DTD rather than XML schema that is expected by default). The
xjc
Ant task needs to be told that a DTD is being used (similar to passing -dtd
to command-line as done earlier). This is added to the build.xml
file so that the relevant portion now looks like that shown in the next code listing.<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask"> <classpath> <fileset dir="C:\Users\Dustin\Downloads\jaxb-ri-20110412\lib" includes="jaxb-xjc.jar" /> </classpath> </taskdef> <target name="generateLog4jJavaClasses" description="Generate Java classes from DTD with JAXB's xjc"> <property name="ant.xjc.target.dir" value="antgenerateddir" /> <mkdir dir="${ant.xjc.target.dir}" /> <xjc destdir="${ant.xjc.target.dir}" package="dustin.examples" schema="log4j.dtd"> <arg value="-dtd" /> </xjc> </target>
This does the trick.
Conclusion
It isn't much more difficult to generate Java with JAXB from a DTD than it is from an XSD with the most significant difference being the addition of the simple
-dtd
parameter. Of course, there are other differences in the results because of the significantly less descriptive ability of the DTD when compared to XML Schema. However, if a DTD is what one has available, JAXB's xjc
binding compiler can make use of it to generate compliant Java classes.
1 comment:
Blaise Doughan posted JAXB and DTD - Apache log4j Example a few days ago. This is similar, but a different perspective to my post here.
Post a Comment