我正在使用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
答案 0 :(得分:4)
我找到了令人满意的解决方法。它使用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>
答案 1 :(得分: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());