The JAXB's XJC is very popular tool for generating Java classes from a specification files (XSD or WSDL). Java 8 introduced new Date and Time API. Unfortunately this API does not come with (un)marshaller so XJC still generates code using XMLGregorianCalendar type by default.
Because I want to work with the LocalDateTime I had to find and link (un)marshaller for the new API to my project. I decided to use Mikhail Sokolov's adapters.
Then I had to tell XJC that it should generate code with the LocalDateTime for the specification's date-time types. This can be achieved by a binding file. So create a new binding.xjb
file and put mapping of xsd:dateTime
to LocalDateTime
type by using LocalDateTimeXmlAdapter
adapter/(un)marshaller.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
jaxb:version="2.1">
<jaxb:bindings>
<jaxb:globalBindings>
<xjc:javaType name="java.time.LocalDateTime" xmlType="xsd:dateTime"
adapter="com.migesok.jaxb.adapter.javatime.LocalDateTimeXmlAdapter"/>
</jaxb:globalBindings>
</jaxb:bindings>
</jaxb:bindings>
This binding file uses nonstandard adapter
parameter so you need to add -extension
switch to be able to execute XJC. Whole command should look like this: xjc -d <target_directory> -b binding.xjb -extension <specification_file.xsd>
The generated code is pretty ok except for one small thing. For initialisation of generic types the generated code uses verbose form instead of diamond operator. IntelliJ IDEA's static code analysis complains about it. To fix this I decided to post-process the code by regular expression and replace all verbose initialisations by the shorter diamond.
Whole process of the generating and the post-processing can be put into a shell script generate.sh
for easy use.
#!/bin/sh
# Tested on Mac OS X
specification_file=specification_file.xsd
target_dir=target
target_package=com.github.vkuzel.my_project
rm -rf ${target_dir}/*
mkdir -p ${target_dir}
xjc -d ${target_dir} -b binding.xjb -extension -p ${target_package} ${specification_file}
find ${target_dir} -name "*.java" -exec sed -i '' -E 's/(= new [^<]+<)[^>]+(>();)/\1\2/g' {} ;