Reputation: 1830
I have following JAXB-mapped class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "date_or_period_t", propOrder = {
"date", "beginDate", "endDate"
})
public class DateOrPeriodT
implements Serializable
{
private final static long serialVersionUID = 1L;
@XmlElementRef(name = "date", type = JAXBElement.class, required = false)
protected JAXBElement<DateOrDatetimeT> date;
@XmlElementRef(name = "begin_date", type = JAXBElement.class, required = false)
protected JAXBElement<Date> beginDate;
@XmlElementRef(name = "end_date", type = JAXBElement.class, required = false)
protected JAXBElement<Date> endDate;
public JAXBElement<DateOrDatetimeT> getDate() { return date; }
public void setDate(JAXBElement<DateOrDatetimeT> value) { this.date = value; }
public JAXBElement<Date> getBeginDate() { return beginDate; }
public void setBeginDate(JAXBElement<Date> value) { this.beginDate = value; }
public JAXBElement<Date> getEndDate() { return endDate; }
public void setEndDate(JAXBElement<Date> value) { this.endDate = value; }
}
and corresponding xsd:
<xsd:complexType name="date_or_period_t">
<xsd:choice minOccurs="0">
<xsd:element name="date" type="date_or_datetime_t" nillable="true"></xsd:element>
<xsd:sequence>
<xsd:element name="begin_date" type="xsd:date" nillable="true"></xsd:element>
<xsd:element name="end_date" type="xsd:date" nillable="true"></xsd:element>
</xsd:sequence>
</xsd:choice>
</xsd:complexType>
When one or both end_date
, begin_date
is set to xsi:nil="true"
, MOXy throws NPE:
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.jaxb.XMLJavaTypeConverter.convertDataValueToObjectValue(XMLJavaTypeConverter.java:155)
at org.eclipse.persistence.oxm.mappings.converters.XMLConverterAdapter.convertDataValueToObjectValue(XMLConverterAdapter.java:28)
at org.eclipse.persistence.oxm.mappings.converters.XMLConverterAdapter.convertDataValueToObjectValue(XMLConverterAdapter.java:1)
at org.eclipse.persistence.internal.jaxb.JAXBElementConverter.convertDataValueToObjectValue(JAXBElementConverter.java:78)
at org.eclipse.persistence.internal.jaxb.JAXBElementConverter.convertDataValueToObjectValue(JAXBElementConverter.java:56)
at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.convertDataValueToObjectValue(XMLDirectMapping.java:526)
at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getAttributeValue(XMLDirectMapping.java:296)
at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getAttributeValue(XMLDirectMapping.java:1)
at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.endElement(XMLDirectMappingNodeValue.java:165)
at org.eclipse.persistence.internal.oxm.XMLChoiceObjectMappingNodeValue.endElement(XMLChoiceObjectMappingNodeValue.java:177)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.endElement(UnmarshalRecordImpl.java:1050)
at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parseEvent(XMLStreamReaderReader.java:154)
at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:99)
at org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader.parse(XMLStreamReaderReader.java:86)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:895)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:659)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:585)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:140)
When date
is xsi:nil
it works fine, when both begin_date
and end_date
is not xsi:nil
it's fine.
@XmlElementDecl(namespace = "", name = "date", scope = DateOrPeriodT.class)
public JAXBElement<DateOrDatetimeT> createDateOrPeriodTDate(DateOrDatetimeT value) {
return new JAXBElement<DateOrDatetimeT>(_DateOrPeriodTDate_QNAME, DateOrDatetimeT.class, DateOrPeriodT.class, value);
}
@XmlElementDecl(namespace = "", name = "begin_date", scope = DateOrPeriodT.class)
@XmlJavaTypeAdapter(AdapterDate.class)
public JAXBElement<Date> createDateOrPeriodTBeginDate(Date value) {
return new JAXBElement<Date>(_DateOrPeriodTBeginDate_QNAME, Date.class, DateOrPeriodT.class, value);
}
@XmlElementDecl(namespace = "", name = "end_date", scope = DateOrPeriodT.class)
@XmlJavaTypeAdapter(AdapterDate.class)
public JAXBElement<Date> createDateOrPeriodTEndDate(Date value) {
return new JAXBElement<Date>(_DateOrPeriodTEndDate_QNAME, Date.class, DateOrPeriodT.class, value);
Upvotes: 0
Views: 1070
Reputation: 391
When I use the following setup, everything works fine.
class DateOrDatetimeT ->
package org.eclipse.persistence.testing.jaxb.aso.np;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "date", propOrder = {
"date"
})
public class DateOrDatetimeT {
private java.util.Date date;
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
@Override
public String toString() {
return "DateOrDatetimeT [date=" + date + "]";
}
}
class DateOrPeriodT ->
package org.eclipse.persistence.testing.jaxb.aso.np;
import java.io.Serializable;
import java.util.Date;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "date_or_period_t", propOrder = {
"date", "beginDate", "endDate"
})
public class DateOrPeriodT
implements Serializable {
private final static long serialVersionUID = 1L;
@XmlElementRef(name = "date", type = JAXBElement.class, required = false)
protected JAXBElement<DateOrDatetimeT> date;
@XmlElementRef(name = "begin_date", type = JAXBElement.class, required = false)
protected JAXBElement<Date> beginDate;
@XmlElementRef(name = "end_date", type = JAXBElement.class, required = false)
protected JAXBElement<Date> endDate;
public JAXBElement<DateOrDatetimeT> getDate() {
return date;
}
public void setDate(JAXBElement<DateOrDatetimeT> value) {
this.date = value;
}
public JAXBElement<Date> getBeginDate() {
return beginDate;
}
public void setBeginDate(JAXBElement<Date> value) {
this.beginDate = value;
}
public JAXBElement<Date> getEndDate() {
return endDate;
}
public void setEndDate(JAXBElement<Date> value) {
this.endDate = value;
}
@Override
public String toString() {
return "DateOrPeriodT [date=" + getJAXBElementString(date) + ", beginDate=" + getJAXBElementString(beginDate) + ", endDate=" + getJAXBElementString(endDate) + "]";
}
private String getJAXBElementString(JAXBElement<?> element) {
if (null == element) {
return null;
}
return "{" + element.getName() + ":" + element.getValue() + "}";
}
}
class ObjectFactory
package org.eclipse.persistence.testing.jaxb.aso.np;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
import java.util.Date;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name = "date")
JAXBElement<DateOrDatetimeT> createDate(Date date) {
DateOrDatetimeT dateOrDateTime = new DateOrDatetimeT();
dateOrDateTime.setDate(date);
return new JAXBElement<DateOrDatetimeT>(new QName("date"), DateOrDatetimeT.class, dateOrDateTime);
}
@XmlElementDecl(name = "begin_date")
JAXBElement<Date> createBeginDate(Date date) {
return new JAXBElement<Date>(new QName("begin_date"), Date.class, date);
}
@XmlElementDecl(name = "end_date")
JAXBElement<Date> createEndDate(Date date) {
return new JAXBElement<Date>(new QName("end_date"), Date.class, date);
}
}
file jaxb.properties
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
class Test
package org.eclipse.persistence.testing.jaxb.aso.np;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import java.io.InputStream;
import java.util.HashMap;
public class Test {
public static void main(String[] args) throws Exception {
try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("org/eclipse/persistence/testing/jaxb/aso/date.xml")) {
JAXBContext jc = JAXBContext.newInstance(new Class[]{DateOrPeriodT.class, DateOrDatetimeT.class, ObjectFactory.class}, new HashMap<String, Object>());
Unmarshaller marshaller = jc.createUnmarshaller();
JAXBElement el = (JAXBElement) marshaller.unmarshal(is);
DateOrPeriodT dateOrPeriodT = (DateOrPeriodT) el.getValue();
System.out.println("dateOrPeriodT=" + dateOrPeriodT);
}
}
}
different versions of date.xml (tested with EclipseLink 2.5.2)
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<date>2015-02-16T14:49:46.583+01:00</date>
<begin_date>2015-02-16T14:49:46.583+01:00</begin_date>
<end_date>2015-02-15T14:49:46.583+01:00</end_date>
</date_or_period_t>
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<date>2015-02-16T14:49:46.583+01:00</date>
<begin_date xsi:nil="true" />
<end_date>2015-02-15T14:49:46.583+01:00</end_date>
</date_or_period_t>
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<date>2015-02-16T14:49:46.583+01:00</date>
<begin_date xsi:nil="true" />
<end_date xsi:nil="true" />
</date_or_period_t>
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<begin_date xsi:nil="true" />
<end_date>2015-02-15T14:49:46.583+01:00</end_date>
</date_or_period_t>
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<begin_date xsi:nil="true" />
<end_date xsi:nil="true" />
</date_or_period_t>
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<begin_date>2015-02-15T14:49:46.583+01:00</begin_date>
<end_date>2015-02-15T14:49:46.583+01:00</end_date>
</date_or_period_t>
If you use EclipseLink 2.6.0, xml needs nested date element:
<date_or_period_t xsi:type="date_or_period_t" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<date><date>2015-02-16T14:49:46.583+01:00</date></date>
<begin_date>2015-02-16T14:49:46.583+01:00</begin_date>
<end_date>2015-02-15T14:49:46.583+01:00</end_date>
</date_or_period_t>
Upvotes: 1