首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编组/解组JAXBElement时的NPE

编组/解组JAXBElement时的NPE
EN

Stack Overflow用户
提问于 2015-02-13 14:24:25
回答 1查看 936关注 0票数 0

我有以下JAXB映射的类:

代码语言:javascript
复制
@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; }
}

和相应的xsd:

代码语言:javascript
复制
<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>

当一个或两个end_datebegin_date设置为xsi:nil="true"时,MOXy抛出NPE:

代码语言:javascript
复制
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)

datexsi:nil时,它工作得很好,当begin_dateend_date都不是xsi:nil时,它也没问题。

代码语言:javascript
复制
@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);
EN

回答 1

Stack Overflow用户

发布于 2015-02-16 22:58:15

当我使用下面的设置时,一切都很好。

类DateOrDatetimeT ->

代码语言:javascript
复制
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 + "]";
    }

}

类DateOrPeriodT ->

代码语言:javascript
复制
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() + "}";
    }

}

ObjectFactory类

代码语言:javascript
复制
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);
    }

}

文件jaxb.properties

代码语言:javascript
复制
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

类测试

代码语言:javascript
复制
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);
        }
    }
}

不同版本的date.xml (使用EclipseLink 2.5.2测试)

代码语言:javascript
复制
<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>

如果您使用的是XML2.6.0,EclipseLink需要嵌套的date元素:

代码语言:javascript
复制
<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>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28493702

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档