I have a problem with the way JAXB is generating the bound classes for an XML schema (which, for sake of precision, I cannot modify). I want to map a xsd:date type to a Joda-time LocalDate object and, reading here, here and here, I created the following DateAdapter class:
public class DateAdapter extends XmlAdapter<String,LocalDate> {
private static DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyyMMdd");
public LocalDate unmarshal(String v) throws Exception {
return fmt.parseLocalDate(v);
}
public String marshal(LocalDate v) throws Exception {
return v.toString("yyyyMMdd");
}
}
And I added the following to my global binding file:
<jaxb:globalBindings>
<jaxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
parseMethod="my.classes.adapters.DateAdapter.unmarshal"
printMethod="my.classes.adapters.DateAdapter.marshal" />
</jaxb:globalBindings>
The problem is that, when I try to maven compile my project, it fails with the following error:
[ERROR] \My\Path\MyProject\target\generated-sources\xjc\my\classes\generated\Adapter1.java:[20,59] non-static method unmarshal(java.lang.String) cannot be referenced from a static context
[ERROR] \My\Path\MyProject\target\generated-sources\xjc\my\classes\generated\Adapter1.java:[24,59] non-static method marshal(org.joda.time.LocalDate) cannot be referenced from a static context
...and this is where things get weird. JAXB generates a class Adapter1 that contains the following:
public class Adapter1
extends XmlAdapter<String, LocalDate>
{
public LocalDate unmarshal(String value) {
return (my.classes.adapters.DateAdapter.unmarshal(value));
}
public String marshal(LocalDate value) {
return (my.classes.adapters.DateAdapter.marshal(value));
}
}
....which is the source of the compilation error.
Now, my questions are:
- being that my adapter is overriding XmlAdapter, I cannot make the methods static....how do I avoid this?
- Can I avoid the generation of Adapter1.class altogether?? Maybe using package-level annotation XmlJavaTypeAdapters, and if so, how do I do it exactly?? (JAXB generates already a package-info.java of its own....)
Hope I made my situation clear.
Thanks
A complete example. This is your bindings.xml:
plus the Java Class:
plus the pom.xml definition:
You do not need to extend
XmlAdapter
and with Joda-Time v2, you do not even need to implement static methods, as they are already provided.See JAXB datatype converters for xs:date xs:time and xs:dateTime
When generating XmlAdapters from an XML schema you need to put the logic for the conversion in static methods not in an
XmlAdapter
. This is so anXmlAdapter
that leverages that logic can be generated. I recognize that this is an odd mechanism.Complete Example
I found this solution as useful http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html
You will create an adapter
Then register it with annotations by defining a blog/jodatime/package-info.java in your sources
Then you should expect that the serialization of DateTime is done without any other changes, just don't forget to annotate your class with @XmlRootElement.
You do not need to extend
XmlAdapter
.Just create static methods on a POJO and it will work.
Example:
You are extending
XmlAdapter
which is used when you want to annotation your Java model for JaxB, that is through the annotation@XmlJavaTypeAdapter(Adapter1.class)
. For your case you just need a class with static methods that does not extendXmlAdapter
. You will need the parse method (take a string and return date) and print method (take a date and return a string) and that's about it.