JAXB can be a real time saver when working on a project that uses XSD to describe interfaces implemented in Java. Sometimes, however, the generated code is not up to standard. I ran into a problem that seems very common and found a very elegant solution to it on the web.

Yesterday, while working on the XML Schema for Document, I had to decide whether I would wrap collections in a surrounding element, like this:
[xml]
<Document>

<Replies>
<Reply>

</Reply>
<Reply>

</Reply>

</Replies>

</Document>
[/xml]
or I would just have a sequence of <Reply>-elements directly under Document. I think the general consensus is to use wrapping elements, but I decided to base the design on another measure: What would the (Java) code look like that would be generated from the Schema by JAXB.

After configuring the maven-jaxb-plugin into the project (which was really easy and it integrated out of the box with Eclipse through M2Eclipse), the Java code was a little disappointing: For every collection I would get the following structure:
[java]
class Document {

@XmlElement(name = "Replies")
private Replies replies;

public Replies getReplies() {
return replies;
}

public class Replies() {

@XmlElement(name = "Reply")
private List<Reply> reply;

public List<Reply> getReply() {
return reply;
}
}
}
[/java]
This would lead to the following usage pattern:
[java]
Document doc;

doc.getReplies().getReply().add(new Reply(…));
[/java]
which is in my opinion quite awful. I would expect there to be a simple collection structure:
[java]
Document doc;

doc.getReplies().add(new Reply(…));
[/java]
But whether I would use the wrapping element or not, I would still get the additional class.

There is a JAXB annotation that will help in this situation:
[java]
@XmlElementWrapper(name = "replies")
@XmlElement(name = "reply")
protected List<Reply> replies;
[/java]
And this is exactly what we want, but how to tell the JAXB code generator to use that annotation?

After some googling around, I found this blog posting, that provides a solution by using a custom plugin for XJB (the JAXB code generator). Configuring this in maven was quite easy:

  1. Add the plugin jar (which was unfortunately not available from a Maven repo) to the maven-jaxb-plugin dependencies.
  2. Add an <args>-element to the plugin configuration with the -Xxew option to activate the plugin.

The final Maven configuration looks like this:
[xml]
<plugin>
<groupId>com.sun.tools.xjc.maven2</groupId>
<artifactId>maven-jaxb-plugin</artifactId>
<executions>
<execution>
<id>jaxb-generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<includeSchemas>
<includeSchema>xsd/Document.xsd</includeSchema>
</includeSchemas>
<strict>true</strict>
<verbose>true</verbose>
<args>-Xxew</args>
</configuration>
<dependencies>
<dependency>
<groupId>xew</groupId>
<artifactId>xew</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>
[/xml]

The generated code now uses a simple collection, so it looks much more usable.

One last problem is that the generated Replies class, that is now no longer used, is not removed from the code: A little clean up task that must have slipped the plugin developers mind.

Do you want to know more about this subject?
Look at our consultancy services, training offers and careers below or contact us at info@xebia.com