JAXB和多态性

时间:2012-02-21 17:29:35

标签: xml jaxb polymorphism cxf marshalling

我无法通过Java的JAXB实现来编写以下类结构。我有一个抽象的标识符类,它有一个值。

对我而言,重要的是将价值表示为属性。

@XmlSeeAlso({
    AbstractIDInt.class
})
@XmlRootElement(name = "AbstractID")
@XmlAccessorType(XmlAccessType.PROPERTY)
public abstract class AbstractID {

    @XmlAttribute
    abstract Object getValue ();
}

并且,这是一个扩展抽象id类的类:

@XmlRootElement(name = "AbstractIDInt")
@XmlAccessorType(XmlAccessType.NONE)
public class AbstractIDInt extends AbstractID {
    Integer value;

    Integer getValue () {
        return value;
    }

    public void setvalue (Integer value) {
        this.value = value;
    }
}

目前,如果您尝试编组AbstractID类型的某些东西,Java的JAXB实现只会引发异常。

这是违反了JAXB标准中的内容还是Java的JAXB实现被破坏了?

1 个答案:

答案 0 :(得分:3)

JDK中包含的JAXB实现可能存在错误。使用JDK 1.6.0_29我得到了您可能会看到的异常:

Exception in thread "main" java.lang.NullPointerException
    at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:154)
    at com.sun.xml.internal.bind.v2.runtime.property.AttributeProperty.<init>(AttributeProperty.java:56)
    at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:93)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:145)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:479)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:305)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:376)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
    at forum9382200.Demo.main(Demo.java:9)

使用EclipseLink JAXB (MOXy)运行相同的演示代码我得到以下输出(我是MOXy领导):

<?xml version="1.0" encoding="UTF-8"?>
<AbstractIDInt value="1"/>

以下是我使用的演示代码:

package forum9382200;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws Exception  {
        JAXBContext jc = JAXBContext.newInstance(AbstractID.class);

        AbstractIDInt abstractIDInt = new AbstractIDInt();
        abstractIDInt.setvalue(1);

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

}

更多信息:


<强>更新

如果您需要使用Java SE中包含的JAXB RI,您可以尝试以下方法:

<强> AbstractID

将父类标记为@XmlTransient

package forum9382200;

import javax.xml.bind.annotation.*;

@XmlSeeAlso({
    AbstractIDInt.class
})
@XmlTransient
public abstract class AbstractID {

    abstract Object getValue ();
}

<强> AbstractIDInt

注释子类上的value属性:

package forum9382200;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "AbstractIDInt")
@XmlAccessorType(XmlAccessType.NONE)
public class AbstractIDInt extends AbstractID {
    Integer value;

    @XmlAttribute
    Integer getValue () {
        return value;
    }

    public void setvalue (Integer value) {
        this.value = value;
    }
}

了解更多信息