JAXB (Jakarta XML Binding) is a popular way to bind XML schemas to Java objects. However, out of the box, JAXB doesn’t support the modern Java 8+ java.time API like LocalDate or LocalDateTime. It still defaults to javax.xml.datatype.XMLGregorianCalendar.
In this post, I’ll show you how to configure JAXB and the jaxb2-maven-plugin to generate Java classes that use java.time.LocalDate and LocalDateTime instead.
The Problem
By default, this schema will generate a field of type XMLGregorianCalendar:
<xs:element name="timestamp" type="xs:dateTime"/>
That’s outdated and clunky in modern Java. Let’s fix that.
Configure the JAXB Plugin
We use the jaxb2-maven-plugin to generate the classes and apply a custom binding file to map xs:dateTime to java.time.LocalDateTime.
Here’s the plugin configuration:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version> <!-- or newer -->
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>src/main/resources/xsd/events.xsd</source>
</sources>
<xjbSources>
<xjbSource>src/main/resources/xsd/bindings.xjb</xjbSource>
</xjbSources>
<packageName>ch.transgourmet.demo.xml.messages</packageName>
<outputDirectory>${project.build.directory}/generated-sources/jaxb</outputDirectory>
</configuration>
</plugin>
Custom Bindings for java.time
Create a binding file (bindings.xjb) to tell JAXB to use LocalDateTime and LocalDate, and how to parse/print them.
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
jaxb:version="3.0">
<jaxb:globalBindings>
<jaxb:javaType name="java.time.LocalDateTime"
xmlType="xs:dateTime"
parseMethod="ch.transgourmet.demo.core.config.LocalDateTimeAdapter.parse"
printMethod="ch.transgourmet.demo.core.config.LocalDateTimeAdapter.print"/>
<jaxb:javaType name="java.time.LocalDate"
xmlType="xs:date"
parseMethod="ch.transgourmet.demo.core.config.LocalDateAdapter.parse"
printMethod="ch.transgourmet.demo.core.config.LocalDateAdapter.print"/>
</jaxb:globalBindings>
</jaxb:bindings>
Adapter Classes
Now provide static parse/print methods for the adapters. Keep it simple and robust:
LocalDateTimeAdapter
public class LocalDateTimeAdapter {
public static LocalDateTime parse(String value) {
return value != null ? LocalDateTime.parse(value) : null;
}
public static String print(LocalDateTime value) {
return value != null ? value.toString() : null;
}
}
LocalDateAdapter
ublic class LocalDateAdapter {
public static LocalDate parse(String value) {
return value != null ? LocalDate.parse(value) : null;
}
public static String print(LocalDate value) {
return value != null ? value.toString() : null;
}
}
✅ Tip: You can customize the format with DateTimeFormatter if needed.
Result
Now the generated JAXB classes use java.time.LocalDateTime and LocalDate directly. No more legacy date types!
@XmlElement(name = "timestamp", required = true) protected LocalDateTime timestamp;
Summary
With a simple binding file and some adapter glue code, JAXB becomes compatible with modern Java time APIs — making your code cleaner and your date handling less painful.


