JAXB with Maven
Fredrik was recently blogging about "Two way SSL with Java" and about his frustration about the lack of knowledge and documentation. This time I want to blog about another area of software development where frustration is running high - XML processing. On the surface things looks easy, but who does not remember the classpath problems around XML parsing in the early days (SAX vs XERCES vs DOM, etc). And who really fully understands the XSD syntax and is able to create a properly designed xsd? And documentation - let's just not talk about it!
But let's get to the actual problem. I wanted to use JAXB to write a parser for XML files matching a given xsd. Given that Sun introduced JAXB as official XML binding framework for Java it seems the obvious choice for the task. Unfortunately, another requirement was that the code would work under JDK 5 and 6. However, the JAXB API is only offical part of the JDK since version 6. To solve this problem a little trick is needed. Let's take it step by step using Maven as build system. First we have to include the plugin by adding the following to the POM:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> <executions> <execution> <goals> <goal>xjc</goal> </goals> </execution> </executions> <configuration> <packageName>org.hibernate.validation.xml</packageName> <outputDirectory>${basedir}/target/generated-sources</outputDirectory> <extension>true</extension> </configuration> </plugin>
The task of the plugin is to create the Java binding classes for the xsd. Per default the xsd file has to be placed into the directory /src/main/xsd. The configuration in the POM specifies the default package name for the generated classes and in which directory the classes have to be generated. The meaning of extension we will discuss a little later.
The setup so far will work fine with JDK 6, but in order to make it work for JDK 5 as well we have to use profiles. The idea is to add the required libraries which are missing in JDK 5 depending on the JDK version. This can be achieved by adding the following to the POM:
<profiles> <profile> <id>jaxb</id> <activation> <jdk>1.5</jdk> </activation> <dependencies> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.1.3</version> </dependency> </dependencies> </profile> </profiles>
So far things were quite simple to figure out. The hard part is one more requirement I haven't mentioned yet. The parser should be tolerant against whitespaces. Some googling and I figured out that in JAXB this kind of things are done with adapters. In fact the CollapsedStringAdapter seems to be exactly what I want. The javadoc says:"This adapter removes leading and trailing whitespaces, then truncate any sequnce of tab, CR, LF, and SP by a single whitespace character '". Great, but how do I configure JAXB so that it automatically uses this adapter. Here the frustration really starts. The best a search for CollapsedStringAdapter results in is the javadoc for this class. Nothing about how to use it. Not in plain JAXB nor in conjunction with the maven plugin. Frustration started to mount again. To cut a long story short. It took many mailing list posts and a lot of try and error to figure it out. The outcome is that first of all you need the
<?xml version="1.0" encoding="UTF-8"?> <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"> <jxb:bindings schemaLocation="../xsd/validation-mapping-1.0.xsd" node="/xs:schema"> <jxb:globalBindings> <xjc:javaType name="java.lang.String" xmlType="xs:string" adapter="javax.xml.bind.annotation.adapters.CollapsedStringAdapter"/> </jxb:globalBindings> </jxb:bindings> </jxb:bindings>
In the customization file a global binding gets defined for all java.lang.String types. It looks simple, but believe me it was damn hard to figure out. Hopefully this blog will save someone the painful hours I had.
My personal conclusion was that documetnation around XML related topics still sucks :(
--Hardy
Old comments