We have a xsd with xs:dateTime
fields. This is our in-house internal API, and we can guarantee that the offset data is always included, so that it's ISO-8601 compatible. For example:
2016-01-01T00:00:00.000+01:00
Currently, the jaxb2 plugin maps xs:dateTime
to a field of type XMLGregorianCalendar
. How to configure the plugin, so that it uses OffsetDateTime
instead?
I don't care whether the solution is for maven-jaxb2-plugin
, jaxb2-maven-plugin
or cxf-codegen-plugin
, we'll use whichever works.
You can use the jaxb2-maven-plugin
with a jaxb-bindings
file.
First I created a odt.xsd
file:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="teste" type="Teste" />
<xsd:complexType name="Teste">
<xsd:sequence>
<xsd:element name="date" type="xsd:dateTime" minOccurs="1"
maxOccurs="1" nillable="false"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Then I created a jaxb-bindings.xjb
file, that defines the type of the date
field, and also the class that converts from and to it:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" jaxb:version="2.0">
<jaxb:bindings schemaLocation="odt.xsd">
<jaxb:bindings node="//xsd:element[@name='date']">
<jaxb:javaType name="java.time.OffsetDateTime"
parseMethod="xsd.test.OffsetDateTimeAdapter.parse"
printMethod="xsd.test.OffsetDateTimeAdapter.print" />
</jaxb:bindings>
<jaxb:schemaBindings>
<jaxb:package name="xsd.test" />
</jaxb:schemaBindings>
</jaxb:bindings>
</jaxb:bindings>
This file references the xsd.test.OffsetDateTimeAdapter
class and the respective methods to convert the OffsetDateTime
from and to a String
, so I also created it:
package xsd.test;
import java.time.OffsetDateTime;
public class OffsetDateTimeAdapter {
public static OffsetDateTime parse(String value) {
return OffsetDateTime.parse(value);
}
public static String print(OffsetDateTime value) {
return value.toString();
}
}
Then, in pom.xml
I've added the configuration for the plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- The package of your generated sources -->
<packageName>xsd.test</packageName>
<sources>
<source>src/main/resources/odt.xsd</source>
</sources>
<xjbSources>
<xjbSource>src/main/resources/jaxb-bindings.xjb</xjbSource>
</xjbSources>
</configuration>
</plugin>
With this, I've just built the project with mvn clean package
and the jar created contains the generated files in the xsd.test
package. The Teste
class contains the date
field as a OffsetDateTime
:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Teste", propOrder = {
"date"
})
public class Teste {
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected OffsetDateTime date;
// getter and setter
}
With this, the date
field is mapped to a OffsetDateTime
, using the autogenerated Adapter1
(which internally uses the xsd.test.OffsetDateTimeAdapter
class created above). Example of parsing the date from a xml:
ObjectFactory f = new ObjectFactory();
JAXBContext context = JAXBContext.newInstance("xsd.test");
Unmarshaller unmarshaller = context.createUnmarshaller();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns2:teste xmlns:ns2=\"xsd.test\"><date>2016-01-01T00:00+01:00</date></ns2:teste>";
JAXBElement<Teste> jaxElement = unmarshaller.unmarshal(new StreamSource(new ByteArrayInputStream(xml.getBytes())), Teste.class);
OffsetDateTime odt = jaxElement.getValue().getDate();
System.out.println(odt); // 2016-01-01T00:00+01:00
And when marshalling the date to a xml, the OffsetDateTime
is directly converted to a String
such as 2016-01-01T00:00+01:00
.
Another way is to use the command line xjc
, which comes with the JDK:
xjc src/main/resources/odt.xsd -d src/main/java/ -p xsd.test -b src/main/resources/jaxb-bindings.xjb
This generates the classes in src/main/java
directory, at the xsd.test
package.