【问题标题】:How do I extend a JAXBContext used by classes generated by CXF wsdl2java to include an additional ObjectFactory如何扩展 CXF wsdl2java 生成的类使用的 JAXBContext 以包含额外的 ObjectFactory
【发布时间】: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 以便将PriceQuoteInfoObjectFactory 添加到生成的*PortType 中?

例如:有没有办法通过使用外部绑定来影响生成的 @XmlSeeAlso 注释,使其包含这个 ObjectFactory?

【问题讨论】:

    标签: xml cxf jax-ws wsdl2java sabre


    【解决方案1】:

    遇到了类似的问题。我发现无法直接影响JAXBContext,但在创建 JAX-WS 代理时我能够通过JaxWsProxyFactoryBean.setProperties() 注入我的 ObjectFactory:

    JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
    factory.setProperties(
        Collections.singletonMap(
                    "jaxb.additionalContextClasses",
                    new Class[{com.mypackage.ObjectFactory.class});
    

    这样我得到了JAXBElement&lt;T&gt; 而不是原始DOM 对象(在你的情况下T 将是PriceQuoteInfo)。 希望对您有所帮助。

    【讨论】:

    • 你有一个语法错误,正确的是: factory.setProperties( Collections.singletonMap( "jaxb.additionalContextClasses", new Class[]{ObjectFactory.class}));
    猜你喜欢
    • 2012-10-05
    • 2014-09-27
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 2014-08-28
    • 2011-04-12
    相关资源
    最近更新 更多