JAXB Unmarshalling期间的InstantiationException(抽象基类,带有@XmlSeeAlso具体子类)

Ana*_*and 6 abstract-class jaxb

我遇到了JAXB Unmarshalling错误,如下所示.foo.bar.Base是一个抽象类,带有@XmlSeeAlso注释,其中列出了foo.bar.SubBase(这是foo.bar.Base的具体子类)

上述两个类都可以从main/entry类静态访问:com.example.Request

使用包字符串变量viz创建JAXBContext:

JAXBContext.newInstance("com.example",...);
Run Code Online (Sandbox Code Playgroud)

上面创建的JAXBContext正确列出了所有三个类: com.example.Request, foo.bar.Base and foo.bar.SubBase as "classes known to this JAXBContext"

但它在运行时在下面的解组调用中失败了.我无法弄清楚这里有什么问题.

unmarshaller.unmarshal(<some-DOM-Element-Instance>, com.example.Request.class);
Run Code Online (Sandbox Code Playgroud)

任何指针将不胜感激!谢谢!

堆栈跟踪是:

    Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of foo.bar.Base  - with linked exception: [java.lang.InstantiationException]

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)

    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:254)

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:609)

    at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:181)

    at com.sun.xml.bind.v2.runtime.unmarshaller.XsiTypeLoader.startElement(XsiTypeLoader.java:76)

    at com.sun.xml.bind.v2.runtime.unmarshaller.ProxyLoader.startElement(ProxyLoader.java:55)

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:481)

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:459)

    at com.sun.xml.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:71)

    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:148)

    at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:239)

    at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:276)

    at com.sun.xml.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:245)

    at com.sun.xml.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:122)

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:314)

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:293)

Caused by: java.lang.InstantiationException

    at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)

    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)

    at com.sun.xml.bind.v2.ClassFactory.create0(ClassFactory.java:123)

    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:261)

    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:603)

    ... 69 more
Run Code Online (Sandbox Code Playgroud)

编辑@Blaise和@Ross

非常感谢Blaise和Ross的指示.我想我应该在这里包含正在处理的模式.相关模式如下所示:

    <xs:complexType name="Request">
                    <xs:sequence>
                        <xs:element name="selectedBase" form="unqualified" nillable="true" type="xs:anyType" minOccurs="0"/>
                        <xs:element name="selectedSubBase" form="unqualified" nillable="true" type="ns1:SubBase" minOccurs="0"/>
                    </xs:sequence>
                </xs:complexType>


<xs:complexType name="Base">
                <xs:sequence>
                    <xs:element name="ID" form="unqualified" nillable="true" type="xs:string" minOccurs="0"/>
                </xs:sequence>
            </xs:complexType>
            <xs:complexType name="SubBase">
                <xs:complexContent>
                    <xs:extension base="ns1:Base">
                        <xs:sequence>
                            <xs:element name="subBaseElement" form="unqualified" nillable="true" type="xs:anyType" minOccurs="0"/>
                        </xs:sequence>
                    </xs:extension>
                </xs:complexContent>
            </xs:complexType>
Run Code Online (Sandbox Code Playgroud)

因此架构没有替换组定义(所以我想@XmlElementRef这里不适用,或者它仍然可以工作吗?),但是使用扩展.有效载荷将是:

<ns:Request>
         <selectedBase>123</selectedBase>
         <selectedSubBase>
            <ID>321</ID>
            <subBaseElement>123</subBaseElement>
         </selectedSubBase>
      </ns:Request>
Run Code Online (Sandbox Code Playgroud)

因此,在有效载荷发生的历史的元素<selectedSubBase>,而不是<selectedBase xsi:type="ns:SubBase"/>

那么哪种策略适用于此?

bdo*_*han 8

@XmlSeeAlso注解被用来作为一种方便的机制来告诉你JAXB IMPL的元数据也应该为引用的类来创建.虽然它最常用于指定子类,但它不是配置继承关系的机制.

由于JAXB正在尝试实例化抽象超类(foo.bar.Base)的实例,因此看起来好像您的XML消息没有包含足够的信息来指定要解组的正确子类型.

这可以使用以下xsi:type属性完成:

您还可以使用替换组(@XmlElementRef),其中元素名称用于确定适当的子类型:

JAXB实现(例如EclipseLink JAXB(MOXy))也包含用于处理继承的扩展:

如果您想完全忽略继承关系,可以使用@XmlTransient注释: