xml - 如何扩展 CXF wsdl2java 生成的类使用的 JAXBContext 以包含额外的 ObjectFactory

标签 xml cxf jax-ws wsdl2java sabre

什么?

我正在使用 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 中未引用的命名空间,因此 没有任何 ObjectFactory 类JAXBContext 已创建,可以解码该元素。因此,它最终成为原始 DOM 元素 (ElementNSImpl)。

我是否有定义 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/

相关文章:

java - 非法字符实体 : expansion character (code 0xe

spring - cxf 和 spring MVC : No service was found

java - 具有重要名称的 WSDL 中的参数名称

xml - Xpath 等同于 http ://gskinner. com/RegExr/for Regex?

xml - 是否需要在根元素中声明 XML namespace 才能被 XPath 查询匹配?

grails - 关于disableCNCheck选项的wsdl2java CXF命令行错误

java - JAX-WS如何从第3方库返回自定义类对象

java - 从 Axis Web 服务手动抛出哪种异常?

xml - 从 XML 数据中读取 URL

xml - 我如何在 perl 中获取 xml 值?