user1746915
user1746915

Reputation: 331

JAXB - marshall generic type (Date)

I am having trouble to marshall/unmarshall generic type using JAXB. Everything works fine, but when my generic field is Date (java.util.Date), unmarshalling will produce XMLGregorianCalendar instead

here is a piece of code I am talking about:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Entity<T> {
    private T field;

    public Entity() {
    }

    public T getField() {
        return field;
    }

    public void setField(T field) {
        this.field = field;
    }
}
import java.io.*;
import java.util.Date;
import javax.xml.bind.*;

public class JaxbTest {
    public JaxbTest() {

        Entity<Date> ent = new Entity<Date>();
        ent.setField(new Date());

        StringWriter sw = new StringWriter();

        try {
            // marshall
            JAXBContext jaxbContext = JAXBContext.newInstance(Entity.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.marshal(ent, sw);

            // unmarshall
            JAXBContext jc = JAXBContext.newInstance(Entity.class);
            Unmarshaller u = jc.createUnmarshaller();
            Entity<Date> ent2 = (Entity<Date>) u.unmarshal(new StringReader(sw
                    .toString()));// exception is thrown here
            System.out.println(ent2.getField());
        } catch (JAXBException e11) {
            e11.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new JaxbTest();
    }

}

the above code throws exception:

java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl cannot be cast to java.util.Date
    at JaxbTest.<init>(JaxbTest.java:31)
    at JaxbTest.main(JaxbTest.java:38)

Could you help me how to fix it? I was thinking about some adapter that would be "active" only if field is Date, but I don't think it is possible

thanks

Upvotes: 3

Views: 2617

Answers (2)

Gregor Valentin
Gregor Valentin

Reputation: 66

I had a similar problem with a generic field in an abstract class. I solved it by adding an annotated getter/setter which parses the value to/from a string. The getter/setter is then overwritten in my subclasses.

This was my solution:

@XmlSeeAlso({DateEntity.class})
@XmlType
public abstract class Entity<T> {
    private T field;

    public Entity() {}

    public T getField() {
        return this.field;
    }

    public void setField(T field) {
        this.field = field;
    }

    @XmlAttribute(name="value", required = true)
    public abstract String getSerializeField();
    public abstract void setSerializeField(String value);
}

My date sublcass:

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="dateEntity")
public class DateEntity extends Entity<Date> {

    public DateEntity() {}

    @Override
    public String getSerializeField(){
        DateFormat formatter = DateFormat.getInstance();
        return formatter.format(field);
    }

    @Override
    public void setSerializeField(String value) {
        DateFormat formatter = DateFormat.getInstance();
        this.value = formatter.parse(value);
    }
}

Hope this is helpful...

Upvotes: 0

bdoughan
bdoughan

Reputation: 149047

A JAXBContext is built on classes and not types. As far your JAXB (JSR-222) implementation is aware, the field property is of type Object. If you add the following to your code:

        String xml = sw.toString();
        System.out.println(xml);

You will see the output XML is the following. An xsi:type attribute has been added to preserve that the text value contains date information. On the unmarshal operation since JAXB thinks the property is of type Object it will recognize the xsi:type attribute and convert the value to the default date type which is XMLGregorianCalendar.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<entity>
    <field xsi:type="xs:dateTime" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2012-10-29T15:20:17.763-04:00</field>
</entity>

Upvotes: 1

Related Questions