Friday, May 8, 2009

JAXB Quicktip: XMLGregorianCalendar

Assume you have the following type-declaration in your XSD:

<xs:simpleType name="dateType">
	<xs:annotation> 
		<xs:documentation>Date without Timezone with the following format: YYYY-MM-DD</xs:documentation>
	</xs:annotation>
	<xs:restriction base="xs:date">
		<xs:pattern value="\d{4}-\d{2}-\d{2}"/>
	</xs:restriction> 
</xs:simpleType> 

If you are using XJC to generate Java classes from the above XSD, then references of Type XMLGregorianCalendar are generated.

Now, if you instantiate a new XMLGregorianCalendar in your Java code like this:

GregorianCalendar cal = new GregorianCalendar( 1976, Calendar.DECEMBER, 22 );
XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar( cal );

… and then let JAXB render the xml, the corresponding XML looks like this:

<birthday>1976-12-22T00:00:00.000+01:00</birthday>

… this XML fragment is not valid according to the above schema!
What we want would look like this:

<birthday>1976-12-22</birthday>

An quick workaround is to set the unwanted fields of XMLGregorianCalendar to DatatypeConstants.FIELD_UNDEFINED like this:

XMLGregorianCalendar gc = DatatypeFactory.newInstance().newXMLGregorianCalendar( c );
gc.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
gc.setTime(DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED);

Of course it would be much cleaner if JAXB would respect the constraints when generating the Java code. I guess this could be achieved by configuring JAXB accordingly … but I did not go so far.

 

12 comments:

  1. My project instantiates XMLGregorianCalendar objects, and allows JAXB to serialize them to xs:date and xs:dateTime fields.

    I could not marshal any documents without getting schema errors, because JAXB didn't care that the field is xs:date -- it kept writing time into the value as well.

    Your post is the -only- resource I could find that describes setting time fields to "undefined" in order to fix this.

    THANK YOU!

    ReplyDelete
  2. Seeing this issue is interesting. We have been dealing with JAXB code generation for web services and using the same xsd file to create Action Scripts for Flex AMF services. We also use the JAXB object for pure POJO services as a way to serialize our Model Objects. Based on our long list of experiences, we just don't think it's worth it to use date type in the xsd at all. Simple "String" works wonder. As long as we define a unique format for our application, no matter it's a Flex client in Action Script, a HTML form with Spring MVC binding or a back-end database transaction using Java/JDBC, we know how to deal with that String in each of the tiers. Until the day that there is a "standard datetime" object spec for all different clients and server API implementation, I don't think there is a point to try to use anything other than a well-formatted String.
    If you need to deal with time zone between a Flash client(or HTML form) and the services on the server side, you will be very thankful that you ignore the "XMLGregorianCalendar" all together.

    ReplyDelete
    Replies
    1. For now I will use this workaround. But I Totally agree with you. Plain old well formatted String...

      Delete
  3. Thanks for this post. was helpful.

    ReplyDelete
  4. Thank you for posting this! :]

    ReplyDelete
  5. This is the only resource to i coukld find for this fix.
    Thanks a ton...

    ReplyDelete
  6. thanks a lot very helpful tips.

    ReplyDelete
  7. Exactly what i was looking for. Thanks for the post.

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...