什么?
我正在使用 CXF 的 wsdl2java 从外部提供的 wsdl (TravelItineraryReadRQ.wsdl
) 生成 Java 类。
当我调用该操作时,我会收到一个响应,我可以将其解码到 Java 类中,但一个元素及其子元素除外,默认为 DOM 元素 (ElementNSImpl
)
这个元素有什么特别之处?
相关元素 (PriceQuote
) 的类型为 (PriceQuoteType
),在 OpenReservation 架构中定义为 xs:any
:
<xsd:complexType name="PriceQuoteType">
<xsd:choice>
<xsd:any processContents="strict"/>
</xsd:choice>
</xsd:complexType>
为什么会发生这种情况?
我收到的元素(PriceQuoteInfo
元素)属于此 wsdl 中未引用的命名空间,因此 没有任何
已创建,可以解码该元素。因此,它最终成为原始 DOM 元素 (ObjectFactory
类JAXBContextElementNSImpl
)。
我是否有定义 PriceQuoteInfo
类型的架构?
是的,我已经获得了它,并在其上运行 wsdl2java
为其生成 Java 类并将它们附加到类路径中。
我尝试了什么?
为了使 PriceQuoteInfo
能够独立解码,我创建了一个外部绑定(bind)文件来将 PriceQuoteInfo
注释为 XmlRootElement
并引用此文件在 Maven 构建中:
<jaxb:bindings version="2.1"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="annox">
<jaxb:bindings schemaLocation="../PriceQuoteServices_v.3.0.0.xsd" node="/xsd:schema">
<jaxb:bindings node="xsd:complexType[@name='PriceQuoteInfo.Get.Response']">
<jaxb:class name="PQSPriceQuoteInfo"/>
<annox:annotate target="class">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="PriceQuoteInfo" namespace="http://www.sabre.com/ns/Ticketing/pqs/1.0"/>
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
部分成功
然后,我可以使用初始化如下的 JAXBContext
独立解码 PriceQuoteInfo
XML:
JAXBContext context = JAXBContext.newInstance(PQSPriceQuoteInfo.class)
将 PriceQuoteInfo
解码为 TravelItineraryReadRS
元素的子元素时,我还可以通过将 JAXBContext
声明为:
JAXBContext context = JAXBContext.newInstance(TravelItineraryReadRS.class, PQSPriceQuoteInfo.class)
或者,通过使用他们的对象工厂:
JAXBContext context = JAXBContext.newInstance(com.sabre.services.res.tir.v3_10.ObjectFactory.class, com.sabre.ns.ticketing.pqs.v1_0.ObjectFactory.class)
解码代码是什么样的?
InputStream inputStream = MyUnitTest.getResourceAsStream(filename)
Unmarshaller unmarshaller = context.createUnmarshaller()
JAXBElement<TravelItineraryReadRS> travelItineraryReadRS = unmarshaller.unmarshal(new StreamSource(inputStream), TravelItineraryReadRS.class)
这会将一些 TravelItineraryReadRS
XML 解码到 Java 类中,而无需任何原始 DOM 对象。
问题出在哪里?
当我通过 CXF/JAX-WS 调用此服务时,PriceQuoteInfo
会解码为原始 DOM 元素,因为我还没有找到修改它使用的 JAXBContext
的方法添加缺少的对象工厂。
@XmlSeeAlso
wsdl 生成的 *PortType 接口(interface)上的 @XmlSeeAlso
注释包含 ObjectFactory
类的列表。
通过复制和扩展 TravelItineraryReadPortType
接口(interface)并将 com.sabre.ns.ticketing.pqs.v1_0.ObjectFactory
添加到 @XmlSeeAlso
中的列表注释,我在解码 PriceQuoteInfo 元素的某些子元素期间成功触发了 XML 验证错误:
unexpected element (uri:"http://www.sabre.com/ns/Ticketing/pqs/1.0", local:"ValidatingCarrier")
虽然不是很优雅,但它表明这种方法正在尝试解码 PriceQuoteInfo
而不是将其保留为 DOM 对象,但 XML 与 GetPriceQuote
并不完全匹配> 我生成的架构。我将关闭验证或找到匹配的架构来解决该问题。
问题
是否可以影响 CXF/JAX-WS Web 服务调用中使用的 JAXBContext
以便为 PriceQuoteInfo
添加 ObjectFactory
到生成的 *PortType?
例如:是否有一种方法可以通过使用外部绑定(bind)来影响生成的 @XmlSeeAlso 注释,使其包含此 ObjectFactory?
最佳答案
也有类似的问题。我找不到影响JAXBContext
的方法直接但我能够通过 JaxWsProxyFactoryBean.setProperties()
注入(inject)我的 ObjectFactory创建 JAX-WS 代理时:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setProperties(
Collections.singletonMap(
"jaxb.additionalContextClasses",
new Class[{com.mypackage.ObjectFactory.class});
这样我就得到了JAXBElement<T>
而不是原始 DOM 对象( T
在你的情况下将是 PriceQuoteInfo
)。
希望有帮助。
关于xml - 如何扩展 CXF wsdl2java 生成的类使用的 JAXBContext 以包含额外的 ObjectFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54778428/