【发布时间】:2019-07-13 16:13:11
【问题描述】:
什么?
我正在使用 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 中未引用的命名空间,因此创建 JAXBContext 时使用的任何 ObjectFactory 类都不能解组该元素。因此,它最终成为原始 DOM 元素 (ElementNSImpl)。
我有定义PriceQuoteInfo 类型的架构吗?
是的,我已经获得了这个,并在其上运行wsdl2java 为其生成Java 类并将它们附加到类路径中。
我尝试了什么?
为了使PriceQuoteInfo能够独立解组,我创建了一个外部绑定文件来将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>
部分成功
然后我可以独立地解组 PriceQuoteInfo XML,使用 JAXBContext 初始化如下:
JAXBContext 上下文 = JAXBContext.newInstance(PQSriceQuoteInfo.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 接口上的@XmlSeeAlso 注释包含ObjectFactory 类的列表。
通过复制和扩展TravelItineraryReadPortType 接口并将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 中?
例如:有没有办法通过使用外部绑定来影响生成的 @XmlSeeAlso 注释,使其包含这个 ObjectFactory?
【问题讨论】:
标签: xml cxf jax-ws wsdl2java sabre