tags:

views:

43

answers:

2

When using JAXB with Java-First, fields/properties of type java.util.Date are marshalled and unmarshalled as xs:dateTime and everything works as expected.

But if the type of the field/property is Object, JAXB unmarshals xs:dateTimeto XMLGregorianCalendarImpl.

I need to find a way that makes JAXB unmarshal date-time values to java.util.Date by itself using annotations. Otherwise, I'll need to go through all unmarshalled values in each use case.

Even if there were some after-unmarshall-hook to define on the classes containing Object fields and convert the instances manually would be good. But I couldn't find anything that can be used this way either.

Note that I have limited access to the JAXB context, as it is used inside Apache CXF.

+1  A: 

You can set the type property on @XmlElement.

@XmlElement(type=Date.class)
public Object getGenericDateProperty() {
    return date;
}

Edit:

Since you don't know the type you could use an XmlAdapter. If the unmarshalled value is an XMLGregorianCalendar convert it to a Date. For more info on XmlAdapter see:

Blaise Doughan
The object is not always a Date. It can be various types. In the generated XSD, it is specified as xs:anyType. The Date is one of the possible values.
Iravanchi
You could write an XmlAdapter to convert between date types.
Blaise Doughan
I have an XmlAdapter for converting between XMLGregorianCalendar and Date, but I can't apply it to a field of type Object using @XmlJavaTypeAdapter - it results in IllegalAnnotationException.
Iravanchi
You could try MOXy JAXB (I'm the tech lead), http://www.eclipse.org/eclipselink/moxy.php . I'll give it a try myself tomorrow when I have access to a computer.
Blaise Doughan
Your first answer led me to the solution, which I'm going to post now. Thanks. And for your last comment, I'd rather not replace JAXB implementation because it's used by CXF and I'm not sure how much headache is there to replace.
Iravanchi
Glad I could help. I'm not sure if this is true for CXF, but for Jersey you can configure the JAXB impl used at the model level through the use of a jaxb.properties file. For an example see: http://bdoughan.blogspot.com/2010/08/creating-restful-web-service-part-35.html
Blaise Doughan
+1  A: 

In addition to Blaise Doughan's answer:

I could finally figure this out, thanks for help from Blaise Doughan. Actually his answer works with just a small change: if there's several types expected to be unmarshalled as the Object property, there needs to be multiple @XmlElement annotations placed on it using @XmlElements annotation.

Here's my code now:

@XmlElements
        ({
                @XmlElement(name = "dateValue",    type = Date.class),
                @XmlElement(name = "stringValue",  type = String.class),
                @XmlElement(name = "booleanValue", type = Boolean.class),
                @XmlElement(name = "listValue",    type = ArrayList.class),
                @XmlElement(name = "bytesValue",   type = Byte[].class)
        })
public Object getFieldValue()
{
    return fieldValue;
}

Note: specifying "name" is required for this to work, since there should be a way for the marshaller / unmarshaller to identify the type of the content.

There are two minor issues here:

  1. You need to specify a list of all of the types expected (which is logical, given the case of marshalling)

  2. There's no way to specify a single name for this property. In my case, where JAXB is used in CXF web services, code generated from WSDL in .NET names this field as "Item". If there was a way, for example, to wrap the XML elements in another one which has a single name, the generated code could be a little bit nicer.

Iravanchi