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.