Several Maven plugins exist for generating classes from a schema definition. One I have yet to try is the Maven JAXB2 Plugin. Below I'll show the minimum setup for using the plugin in your project, as well as a couple of methods for dealing with the package name assigned to the generated classes.
Given the simplistic schema below, placed in src/main/resources of the project:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns="http://example.org/message/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="message">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="text" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
We can add the plugin definition to our POM:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
The classes generated by the plugin can be found in target/generated-sources/xjc. Below is the single class, Message.java, generated by the plugin (with the imports optimized and comments removed for brevity):
package generated;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"text"})
@XmlRootElement(name = "message")
public class Message {
@XmlElement(required = true)
protected String text;
public String getText() {
return text;
}
public void setText(String value) {
this.text = value;
}
}
The first thing that stands out to me is the package name of generated. This might be ok if I wanted to use the generated classes within a single project, but if I wanted to distribute them, a more useful package name might be helpful.
The user guide for the plugin describes a list of configuration options. The one we're looking for might just be generatePackage, which we can add:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<executions>
<!-- ... -->
</executions>
<configuration>
<generatePackage>org.example.message</generatePackage>
</configuration>
</plugin>
The generated class can now be found in target/generated-sources/xjc/org/example/messsage/Message.java, with the new package name:
package org.example.message;
public class Message {
// ...
}
There are a couple more options for setting the package name, one is to add an annotation to the schema:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns="http://example.org/message"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">
<xsd:annotation>
<xsd:appinfo>
<jaxb:schemaBindings>
<jaxb:package name="org.example.test"/>
</jaxb:schemaBindings>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="message">
<!-- ... -->
</xsd:element>
</xsd:schema>
If you find annotating a schema to for something like JAXB impurifies the schema, you could influence to derive a namespace by providing a targetNamespace attribute to the root element of the schema:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns="http://example.org/message"
targetNamespace="http://example.org/message" ...>
<!-- ... -->
</xsd:schema>
If you have any other suggestions or feel like weighing in on the use of xjc annotations in schema definitions, please feel free to add a comment below.
Thank you for this useful quick tutorial.
ReplyDelete