Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
513 views
in Technique[技术] by (71.8m points)

xml - 如何扩展由CXF wsdl2java生成的类使用的JAXBContext,以包括一个附加的ObjectFactory(How do I extend a JAXBContext used by classes generated by CXF wsdl2java to include an additional ObjectFactory)

What?

(什么?)

I am using CXF's wsdl2java to generate Java classes from an externally supplied wsdl ( TravelItineraryReadRQ.wsdl ).

(我正在使用CXF的wsdl2java从外部提供的wsdl( TravelItineraryReadRQ.wsdl )生成Java类。)

When I call the operation, I get a response that I can unmarshal into Java classes, with the exception of one element and its children which default to DOM elements ( ElementNSImpl )

(当我调用该操作时,我得到一个可以解组到Java类的响应,除了一个元素及其子元素(默认为DOM元素)( ElementNSImpl )外)

What's special about this element?

(这个元素有什么特别之处?)

The element in question ( PriceQuote ) is of type ( PriceQuoteType ) defined in the OpenReservation schema as xs:any :

(有问题的元素( PriceQuote )的类型( PriceQuoteType )在OpenReservation模式中定义为xs:any :)

<xsd:complexType name="PriceQuoteType">
  <xsd:choice>
      <xsd:any processContents="strict"/>
    </xsd:choice>
</xsd:complexType>

Why does this happen?

(为什么会这样?)

The element that I receive (a PriceQuoteInfo element) belongs to a namespace that is not referenced in this wsdl, so none of the ObjectFactory classes that the JAXBContext has been created with, can unmarshal the element.

(我收到的元素( PriceQuoteInfo元素)属于此wsdl中未引用的名称空间,因此创建JAXBContextObjectFactory类都无法解组该元素。)

It therefore ends up as raw DOM elements ( ElementNSImpl ).

(因此,它最终成为原始DOM元素( ElementNSImpl )。)

Do I have the schema where the PriceQuoteInfo type is defined?

(我是否有定义PriceQuoteInfo类型的架构?)

Yes, I have obtained this, and run wsdl2java on it to generate Java classes for it and appended them to the classpath.

(是的,我已经获得了这个,并对其运行wsdl2java为其生成Java类,并将它们附加到类路径中。)

What have I tried?

(我尝试了什么?)

To enable the PriceQuoteInfo to be unmarshalled independently, I created an external binding file to annotate the PriceQuoteInfo as an XmlRootElement and referenced this file in the maven build:

(为了使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>

Partial Success

(部分成功)

I'm then able to unmarshal PriceQuoteInfo XML independently, using a JAXBContext initialised as the following:

(然后,我可以使用初始化为以下内容的JAXBContext独立解组PriceQuoteInfo XML:)

JAXBContext context = JAXBContext.newInstance(PQSPriceQuoteInfo.class)

(JAXBContext上下文= JAXBContext.newInstance(PQSPriceQuoteInfo.class))

When unmarshalling PriceQuoteInfo as a child of a TravelItineraryReadRS element, I can also unmarshal it by declaring the JAXBContext as:

(当将PriceQuoteInfoPriceQuoteInfoTravelItineraryReadRS元素的子TravelItineraryReadRS ,我还可以通过将JAXBContext声明为以下内容来解组它:)

  JAXBContext context = JAXBContext.newInstance(TravelItineraryReadRS.class, PQSPriceQuoteInfo.class)

or alternatively, by using their object factories:

(或者使用他们的对象工厂:)

  JAXBContext context = JAXBContext.newInstance(com.sabre.services.res.tir.v3_10.ObjectFactory.class, com.sabre.ns.ticketing.pqs.v1_0.ObjectFactory.class)

And what does the unmarshalling code look like?

(解组代码是什么样的?)

    InputStream inputStream = MyUnitTest.getResourceAsStream(filename)
    Unmarshaller unmarshaller = context.createUnmarshaller()
    JAXBElement<TravelItineraryReadRS> travelItineraryReadRS = unmarshaller.unmarshal(new StreamSource(inputStream), TravelItineraryReadRS.class)

And this unmarshals some TravelItineraryReadRS XML into Java classes, without any raw DOM objects.

(这就将一些TravelItineraryReadRS XML编组为Java类,而没有任何原始DOM对象。)

So what's the problem?

(所以有什么问题?)

When I call this service via CXF / JAX-WS the PriceQuoteInfo unmarshals into raw DOM elements as I haven't found a way of modifying the JAXBContext that it uses to add the missing object factory.

(当我通过CXF / JAX-WS调用此服务时, PriceQuoteInfo解组到原始DOM元素中,因为我还没有找到修改其用于添加缺少的对象工厂的JAXBContext的方法。)

@XmlSeeAlso

(@XmlSeeAlso)

The @XmlSeeAlso annotation on the wsdl's generated *PortType interface contains a list of ObjectFactory classes.

(wsdl生成的* PortType接口上的@XmlSeeAlso批注包含ObjectFactory类的列表。)

By replicating and extending the TravelItineraryReadPortType interface and adding com.sabre.ns.ticketing.pqs.v1_0.ObjectFactory to the list in the @XmlSeeAlso annotation, I succeeded in triggering an XML validation error during unmarshalling of some children of the PriceQuoteInfo element:

(通过复制和扩展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")

Although not very elegant it shows that this approach is attempting to unmarshal the PriceQuoteInfo rather than leaving it as DOM objects, but that the XML isn't exactly matching the GetPriceQuote schema I generated.

(尽管不是很优雅,但它表明此方法试图解组PriceQuoteInfo而不是将其保留为DOM对象,但是XML与我生成的GetPriceQuote模式不完全匹配。)

I'll either turn off validation or find a matching schema to resolve that.

(我将关闭验证或找到匹配的架构来解决该问题。)

The Question

(问题)

Is it possible to influence the JAXBContext used in a CXF / JAX-WS web service call so as to add the ObjectFactory for PriceQuoteInfo to the generated *PortType?

(是否可以影响CXF / JAX-WS Web服务调用中使用的JAXBContext ,以便将PriceQuoteInfoObjectFactory添加到生成的* PortType中?)

For example: is there a way of influencing the generated @XmlSeeAlso annotation so that it includes this ObjectFactory, by using external bindings?

(例如:是否有一种方法可以通过使用外部绑定来影响生成的@XmlSeeAlso批注,使其包含此ObjectFactory?)

  ask by roj translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Had a similar problem.

(遇到类似的问题。)

I found no way to influence JAXBContext directly but I was able to inject my ObjectFactory via JaxWsProxyFactoryBean.setProperties() when creating the JAX-WS proxy:

(我找不到直接影响JAXBContext方法,但是在创建JAX-WS代理时可以通过JaxWsProxyFactoryBean.setProperties()注入ObjectFactory:)

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

This way I got JAXBElement<T> instead of raw DOM objects ( T would be PriceQuoteInfo in your case).

(这样,我得到了JAXBElement<T>而不是原始DOM对象(在您的情况下, TPriceQuoteInfo )。)

Hope that helps.

(希望能有所帮助。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...