Что?
Я использую wsdl2java из CXF для генерации классов Java из внешнего wsdl (TravelItineraryReadRQ.wsdl
).Когда я вызываю операцию, я получаю ответ, который могу разархивировать в классы Java, за исключением одного элемента и его дочерних элементов, которые по умолчанию имеют элементы DOM (ElementNSImpl
)
Что особенного в этомelement?
Рассматриваемый элемент (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
для самостоятельного разбора, я создал внешний файл привязки для аннотирования 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 context = JAXBContext.newInstance (PQSPriceQuoteInfo.class)
Когда unmarshalling 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)
И как выглядит неустранимый кодe?
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
Аннотация @XmlSeeAlso
в сгенерированном wsdl интерфейсе * PortType содержит список ObjectFactory
классов.Реплицируя и расширяя интерфейс TravelItineraryReadPortType
и добавляя com.sabre.ns.ticketing.pqs.v1_0.ObjectFactory
в список в аннотации @XmlSeeAlso
, мне удалось вызвать ошибку проверки XML во время демаршаллинга некоторых дочерних элементов элемента PriceQuoteInfo:
unexpected element (uri:"http://www.sabre.com/ns/Ticketing/pqs/1.0", local:"ValidatingCarrier")
Хотя и не очень элегантно, это показывает, что этот подход пытается демонтировать PriceQuoteInfo
вместо того, чтобы оставить его как объекты DOM, но что XML не совсем соответствует сгенерированной мной схеме GetPriceQuote
.Я либо отключу валидацию, либо найду подходящую схему для ее решения.
Вопрос
Можно ли повлиять на JAXBContext
, используемый в CXF /Вызов веб-службы JAX-WS для добавления ObjectFactory
для PriceQuoteInfo
к сгенерированному * PortType?
Например: есть ли способ повлиять на сгенерированную аннотацию @XmlSeeAlso, чтобы она включала этот ObjectFactory, используя внешние привязки?