4

我正在使用 JAXB 从几个 XSD 文件生成 Java 代码。然后,在 OSGi 容器中,我将 XML 文件解组为生成的代码。XSD 使用 xsd:any 元素:

<xsd:complexType name="GetReservationRSType">
    <xsd:sequence>
        <xsd:element name="Errors" type="pnrb:Errors.PNRB"
            minOccurs="0" />
        <xsd:choice>
            <xsd:element name="Reservation" type="pnrb:Reservation.PNRB"
                minOccurs="0" />
            <xsd:element name="Content" minOccurs="0">
                <xsd:complexType>
                    <xsd:choice>
                        <xsd:any processContents="lax" />
                    </xsd:choice>
                </xsd:complexType>
            </xsd:element>
        </xsd:choice>
    </xsd:sequence>
</xsd:complexType>

我在使其在生产代码中工作时遇到了几个问题,但最终我在手动添加 @XmlSeeAlso 注释时解决了它(@XmlSeeAlso(value = { OTATravelItineraryRS.class })在下面的代码中):

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "GetReservationRSType", propOrder = {
    "warnings",
    "errors",
    "reservation",
    "content"
})
@XmlSeeAlso({
    GetReservationRS.class
})
public class GetReservationRSType {

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "any"
    })
    @XmlSeeAlso(value = { OTATravelItineraryRS.class })
    public static class Content {
       //  ...
    }
    // ...
}

有什么办法可以强制 JAXB 自动添加这样的注释?例如,通过添加一些 JAXB 绑定配置选项或修改 XSD 文件?

编辑:

我在 OSGi env 中的 JAXBContext 以以下方式初始化(​​它获取所有生成的包名称作为参数) - 它们使用冒号分隔符列出,正如在几个与 JAXB 相关的帖子中所建议的那样:

<bean id="jaxbContext" class="javax.xml.bind.JAXBContext" factory-method="newInstance">
    <constructor-arg index="0" value="com.sabre.webservices.pnrbuilder:com.sabre.webservices.sabrexml._2003._07" />    
</bean>      

我收到以下异常:

Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[javax.xml.bind.JAXBException: class com.sabre.webservices.sabrexml._2003._07.OTATravelItineraryRS nor any of its super class is known to this context.]
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:318)
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244)
    at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:105)
    at org.apache.camel.converter.jaxb.FallbackTypeConverter.marshall(FallbackTypeConverter.java:174)
    at org.apache.camel.converter.jaxb.FallbackTypeConverter.convertTo(FallbackTypeConverter.java:88)
    ... 94 more
Caused by: javax.xml.bind.JAXBException: class com.sabre.webservices.sabrexml._2003._07.OTATravelItineraryRS nor any of its super class is known to this context.
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:246)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:261)
    at com.sun.xml.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:113)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:332)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:699)
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:152)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:332)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:328)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:593)
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:320)
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315)
    ... 98 more
Caused by: javax.xml.bind.JAXBException: class com.sabre.webservices.sabrexml._2003._07.OTATravelItineraryRS nor any of its super class is known to this context.
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:590)
    at com.sun.xml.bind.v2.runtime.property.SingleReferenceNodeProperty.serializeBody(SingleReferenceNodeProperty.java:105)
    ... 107 more
4

2 回答 2

4

我找到了一个令人满意的解决方法。它使用jaxb 注释插件。也许这不是完美的解决方案,但 - 至少 - 它阻止我将生成的类提交到 SVN 存储库。提到的插件只是添加了想要的注释。

这是pom.xml中所需的配置:

        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>

            <executions>
                <execution>
                    <id>schema-pnr-service</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <schemaDirectory>src/main/resources/xsd</schemaDirectory>
                        <schemaIncludes>
                            <include>GetReservationSTLRQ_v0.01.xsd</include>
                            <include>GetReservationSTLRS_v0.01.xsd</include>
                            <include>OTA_TravelItineraryReadCDI1.0.5RQ.xsd</include>
                            <include>OTA_TravelItineraryReadCDI1.0.5RQRS.xsd</include>
                            <include>OTA_TravelItineraryReadCDI1.0.5RS.xsd</include>
                            <include>OTA_TravelItineraryReadPNR1.0.5RS.xsd</include>
                        </schemaIncludes>
                        <extension>true</extension>
                        <args>
                            <arg>-Xannotate</arg>
                            <arg>-Xannotate-defaultFieldTarget=setter</arg>
                        </args>
                        <plugins>
                            <plugin>
                                <groupId>org.jvnet.jaxb2_commons</groupId>
                                <artifactId>jaxb2-basics-annotate</artifactId>
                            </plugin>
                        </plugins>                            
                    </configuration>
                </execution>
            </executions>
        </plugin>  

并且想要的注释在bindings.xjb文件中配置,该文件应该与 *.xsd 文件位于同一目录中 - 这里是它的内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
                xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
                xmlns:annox="http://annox.dev.java.net" 
                extensionBindingPrefixes="annox" version="2.1">
    <globalBindings typesafeEnumMaxMembers="600"/>

    <bindings schemaLocation="GetReservationSTLRS_v0.01.xsd" node="/xsd:schema">
        <bindings node="xsd:complexType[@name='GetReservationRSType']/xsd:sequence/xsd:choice/xsd:element[@name='Content']/xsd:complexType">
            <annox:annotate target="class">
                <annox:annotate annox:class="javax.xml.bind.annotation.XmlSeeAlso" value="com.sabre.webservices.sabrexml._2003._07.OTATravelItineraryRS" />
            </annox:annotate>           
        </bindings>

    </bindings>    
</bindings>
于 2013-01-16T18:20:59.900 回答
0

而不是试图强制@XmlSeeAlso注释,您应该JAXBContext在生成的包名称上创建。这样您就可以确保所有的类都被处理了。由于您处于 OSGi 环境中,因此可以使用其中一种带有ClassLoader参数的方法。

JAXBContext jc = JAXBContext.newInstance("com.example.foo", ObjectFactory.class.getClassLoader());

如果生成的包名不止一个,则上下文路径被:分隔。

JAXBContext jc = JAXBContext.newInstance("com.example.foo:org.example.bar", ObjectFactory.class.getClassLoader());
于 2013-01-16T13:09:38.233 回答