I cannot get JAXB to unmarshal a timestamp in a Resteasy JAX-RS server application.
My class looks like this:
@XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "foo") public final class Foo { // Other fields omitted @XmlElement(name = "timestamp", required = true) protected Date timestamp; public Foo() {} public Date getTimestamp() { return timestamp; } public String getTimestampAsString() { return (timestamp != null) ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(timestamp) : null; } public void setTimestamp(final Date timestamp) { this.timestamp = timestamp; } public void setTimestamp(final String timestampAsString) { try { this.timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(timestampAsString); } catch (ParseException ex) { this.timestamp = null; } } }
Any ideas?
Thanks.
The JAXB Unmarshaller interface is responsible for governing the process of deserializing the XML data to Java Objects. The unmarshalling to objects can be done to variety of input sources.
JAXB simplifies access to an XML document from a Java program by presenting the XML document to the program in a Java format. The first step in this process is to bind the schema for the XML document into a set of Java classes that represents the schema.
JAXB can handle the java.util.Date class. However it expects the format:
"yyyy-MM-dd'T'HH:mm:ss" instead of "yyyy-MM-dd HH:mm:ss"
If you want to use that date format I would suggest using an XmlAdapter, it would look something like the following:
import java.text.SimpleDateFormat; import java.util.Date; import javax.xml.bind.annotation.adapters.XmlAdapter; public class DateAdapter extends XmlAdapter<String, Date> { private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Override public String marshal(Date v) throws Exception { return dateFormat.format(v); } @Override public Date unmarshal(String v) throws Exception { return dateFormat.parse(v); } }
You would then specify this adapter on your timestamp property:
import java.util.Date; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "foo") public final class Foo { // Other fields omitted @XmlElement(name = "timestamp", required = true) @XmlJavaTypeAdapter(DateAdapter.class) protected Date timestamp; public Foo() {} public Date getTimestamp() { return timestamp; } public void setTimestamp(final Date timestamp) { this.timestamp = timestamp; } }
JAXB cannot marshal Date
objects directly, because they don't have enough information to be unambiguous. JAXB introduced the XmlGregorianCalendar
class for this purpose, but it's very unpleasant to use directly.
I Suggest changing your timestamp
field to be a XmlGregorianCalendar
, and change your various methods to update this field while retaining the public interface you already have, where possible.
If you want to keep the Date
field, then you'll need to implement your own XmlAdapter
class to tell JAXB to how turn your Date
to and from XML.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With