I have some dates I have to represent in an XML file in a format different than the one JAXB uses by default.
So, I’ve written some static methods to print and parse the required format:
public static String toDateTime(XMLGregorianCalendar d) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(d.toGregorianCalendar().getTime());
}
public static XMLGregorianCalendar parseDateTime(String s)
throws DatatypeConfigurationException, ParseException {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.parse(s));
return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
}
And I’ve written a .xjb file specifying to use these parse and print methods:
<jxb:bindings
node="//xs:element[@name='date']">
<jxb:javaType name="javax.xml.datatype.XMLGregorianCalendar"
parseMethod="MyClass.parseDateTime"
printMethod="MyClass.toDateTime"
/>
</jxb:bindings>
(The XML schema specifies the element as an xsd:dateTime).
The xjc tool is generating an adapter that calls my methods:
public XMLGregorianCalendar unmarshal(String value) {
return (MyClass.parseDateTime(value));
}
public String marshal(XMLGregorianCalendar value) {
return (MyClass.toDateTime(value));
}
My problem is that the generated adapter won’t compile. The unmarshal method is declared not to throw exceptions, but MyClass.parseDateTime does. It seems perfectly reasonable that it should, since the date might be invalid. And indeed, the unmarshal method of java.xml.bind.annotation.adapters.XmlAdapter that the generated adapter overrides declares that it throws Exception.
I couldn’t find any way to declare in the xjb file which exceptions the parseMethod throws. It occurred to me that maybe I should create my own adapter class, but I couldn’t find any way to declare in the xjb that my custom adapter should be used. I would very much like to be able to generate the classes from the xsd and xjb with xjc and not have to modify them afterwards.
What is the best way to resolve this situation?
You should handle both checked exceptions in your code. For an invalid date-time, you have to decide whether to leave it as null (and maybe emit a warning), or blow up and kill the whole parsing attempt (in that case, throw a
RuntimeExceptionwrapping the originalParseException).In the case of
DatatypeConfigurationException, this is one of the JDK APIs that is badly designed, throwing checked exceptions when there’s nothing your code can do. Just rethrow it asRuntimeException.