【问题标题】:How to force generation of @XmlSeeAlso annotation?如何强制生成@XmlSeeAlso 注释?
【发布时间】:2013-01-16 12:52:15
【问题描述】:

我正在使用 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

【问题讨论】:

  • AFAIK jaxb 会在架构中有扩展名时生成 @XmlSeeAlso。

标签: xsd jaxb


【解决方案1】:

我找到了一个令人满意的解决方法。它使用jaxb annotate plugin。也许这不是完美的解决方案,但 - 至少 - 它阻止我将生成的类提交到 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>

【讨论】:

    【解决方案2】:

    您应该在生成的包名称上创建JAXBContext,而不是尝试强制使用@XmlSeeAlso 注释。这样您就可以确保所有的类都被处理了。由于您在 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());
    

    【讨论】:

    • ClassLoader 参数非常重要。你发布了什么类型的配置文件?
    • 这是标准的 Spring beans.xml 文件。然后将 jaxbContext bean 注入到实际负责解组的其他 bean 中。
    • @LukaszBaran - 我似乎找不到允许您指定 ClassLoader 的 Spring 属性。我怀疑 Spring 在创建 JAXBContext 时不包括一个。相反,您可以在 Springs 要绑定的类列表中包含要使用 @XmlSeeAlso 引用的类。
    • 好吧,我刚刚尝试完全按照您的建议在 Java 代码中初始化 JaxbContext - 不幸的是,我一直遇到同样的异常。
    • @LukaszBaran - 听起来这更像是一个 Spring 问题而不是 JAXB 问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 2018-09-09
    • 2012-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多