January 20, 2011

JAXB and Date/Time Properties

In this post I will describe how JAXB handles date/time information.  This post will also cover how the @XmlSchemaType annotation can be used to customize the XML representation.


XML Schema (date.xsd)

The following XML schema will be used for this post.  Note that the date-of-birth element is of type xsd:date.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="customer">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element 
                    name="date-of-birth" 
                    type="xsd:date" 
                    minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

Generated Model - XMLGregorianCalendar Property


From this XML schema we can generate a class model using the following XJC call:

xjc -d out -p blog.date date.xsd

This will result in a Customer class that looks like the following.  There are a couple of interesting things to note:
  1. The dateOfBirth property is of type javax.xml.datatype.XMLGregorianCalendar.  
  2. The use of @XmlSchemaType
Some Java data types (like XMLGregorianCalendar) have multiple XML representations (like xsd:date, xsd:time, xsd:dateTime, etc.) and @XmlSchemaType is used to choose the desired representation.


package blog.date;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"dateOfBirth"})
@XmlRootElement(name = "customer")
public class Customer {

    @XmlElement(name = "date-of-birth")
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar dateOfBirth;

    public XMLGregorianCalendar getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(XMLGregorianCalendar value) {
        this.dateOfBirth = value;
    }

}

User Defined - Date (or Calendar) Property

Even though the JAXB XML schema to Java compiler (XJC) generates a property of type XMLGregorianCalendar by default, you are free to use java.util.Date and java.util.Calendar as well.

package blog.date;

import java.util.Date;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "customer")
public class Customer {

    @XmlElement(name = "date-of-birth")
    @XmlSchemaType(name = "date")
    protected Date dateOfBirth;

    public Date getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(Date value) {
        this.dateOfBirth = value;
    }

}

EclipseLink JAXB (MOXy) Extension

EclipseLink JAXB (MOXy) also supports the following types which are not covered in the JAXB specification (JSR-222):
  • java.sql.Date
  • java.sql.Time
  • java.sql.Timestamp

19 comments:

  1. Hi Dude,

    Thanks for presenting information in such a nice manner. I just got surprised that following types are not supported by JAXB specification
    * java.sql.Date
    * java.sql.Time
    * java.sql.Timestamp

    Any reason why they are not supported ?

    Thanks
    Javin
    What is the difference between Synchronized Collection classes and Concurrent Collection Classes ? When to use what ?

    ReplyDelete
  2. Hi Javin,

    I believe this was just an oversight when we were putting together the JAXB specification, and something that should be fixed in future versions.

    For JAXB implementations that do not provide an extension to handle this use case, it can always be handled with an XmlAdapter:

    - http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html

    -Blaise

    ReplyDelete
  3. Dei its not working

    ReplyDelete
  4. "Dei its not working"

    What problem are you seeing?

    -Blaise

    ReplyDelete
  5. When using XmlJavaTypeAdapter in combination with XmlSchemaType annotations at the package level the javatype adapter seems to take preference and the schematype is ignored.
    If I use it at the property/method level the xsd type does appear in the generated xsd.

    Is that according to spec or am I doing something wrong?

    ReplyDelete
  6. This may be a bug. You can track the issue using the link below:
    - https://bugs.eclipse.org/353446

    -Blaise

    ReplyDelete
  7. Blaise,

    How to handle XMLGregorianCalenar without DAYOFMONTH field? JAXB is not able to convert it to xml

    Thanks,
    Tony

    ReplyDelete
  8. Hi Tony,

    Can you provide how you are creating your XMLGregorianCalendar? If I do something like the following it converts to XML as expected:

    Code

    JAXBContext jc = JAXBContext.newInstance(Root.class);

    Root root = new Root();
    DatatypeFactory df = DatatypeFactory.newInstance();
    XMLGregorianCalendar xgc = df.newXMLGregorianCalendar();
    xgc.setYear(100);
    xgc.setMonth(3);
    System.out.println(xgc.getXMLSchemaType());
    root.setXjc(xgc);

    Marshaller marshaller = jc.createMarshaller();
    marshaller.marshal(root, System.out);


    Output

    {http://www.w3.org/2001/XMLSchema}gYearMonth
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
    <xjc>0100-03</xjc>
    </root>


    -Blaise

    ReplyDelete
  9. Hi,
    Here is how the XMLGregorianCalendar defined.
    @XmlElement(required = true)
    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar dateSince;

    And I print the value of dataSince. It does include time.
    **2011-10-19T17:00:00.000-07:00

    however, in the xml soap output, it does not print time just like your example.
    2011-10-19-07:00
    How can I include time in the xml?
    thank you

    ReplyDelete
  10. The @XmlSchemaType annotation is used to control how date/time information will be output to XML. If you want date and time information you will need to set @XmlSchemaType(name="dateTime"), this corresponds to the XML schema dateTime type.

    -Blaise

    ReplyDelete
  11. Thanks for this useful information. But I am using Java web services developer pack and JDK 1.4
    Can you tell me the alternative for this for JDK 1.4 where we do not have annotations.

    ReplyDelete
  12. With the above approach , date is shown in yyyy-dd-mm format.
    But what if I want in different format , lets say MM-dd-yyyy , is it possible?

    ReplyDelete
    Replies
    1. The default format for JAXB (JSR-222) implementations is yyyy-dd-mm. If you want another format you can use an XmlAdapter.
      - JAXB and Joda-Time: Dates and Times

      -Blaise

      Delete
    2. Blaise, thanks. I've searched Internet as much as possible to find out the default format, until I landed here.

      Delete
  13. Hi,
    Do you know how to set a xsd:date type in conjunction with the @XmlElements attribute as described in your blog http://blog.bdoughan.com/2010/10/jaxb-and-xsd-choice-xmlelements.html
    I can only get dateTime to work.

    Thanks

    ReplyDelete
    Replies
    1. Very good question. For your use case can you use XMLGregorianCalendar instead of Date. The XMLGregorianCalendar class can be created so that it can represent all the XML Schema date types.

      Delete
  14. Hi,
    you say above "you are free to use java.util.Date and java.util.Calendar as well." and define your "date of birth" as java.util.Date in the Customer class file.
    Is it also possible to define the field already in the "date.xsd" as java.util.Date without using an Adapter?
    Thanks and regards
    Patrick

    ReplyDelete
    Replies
    1. Starting from an XML Schema you are going to end up with an XmlAdapter if you want to have a property of type java.util.Date.
      - XML Schema to Java - Generating XmlAdapters

      Delete
    2. Yesterday I came to the same conclusion and have written an Adapter. Thanks for conforming it :)

      Delete

Note: Only a member of this blog may post a comment.