Проблема пространства имен в веб-сервисе с Apache CXF

Я использую Apache CXF 2.7.3 и сталкиваюсь с проблемой пространства имен, которую я действительно не понимаю. Я много пытался найти это, но большинство результатов, которые я нахожу, касается различного поведения. Проблема заключается в том, что при вызове веб-службы произойдет сбой, если элемент параметра квалифицирован как пространство имен. Все остальные элементы в сообщении являются квалифицированными, и он принимает это, но не элемент параметра. Вот точное поведение:

запрос БЕЗ параметра параметра квалифицирован:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:ord="http://www.example.org/order">
<soapenv:Header/>
   <soapenv:Body>
      <ord:getOrder>
         <id>a</id>
      </ord:getOrder>
   </soapenv:Body>
</soapenv:Envelope>

результаты в успехе:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns2:getOrderResponse xmlns:ns2="http://www.example.org/order">
         <return>
            <ns2:errorCode/>
            <ns2:errorMessage/>
            <ns2:order>
               <ns2:orderNumber>ABC123</ns2:orderNumber>
               <ns2:lastName>Smith</ns2:lastName>
            </ns2:order>
         </return>
      </ns2:getOrderResponse>
   </soap:Body>
</soap:Envelope>

Параметр запроса WITH уточнен:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
                  xmlns:ord="http://www.example.org/order">
   <soapenv:Header/>
   <soapenv:Body>
      <ord:getOrder>
         <ord:id>a</ord:id>
      </ord:getOrder>
   </soapenv:Body>
</soapenv:Envelope>

результаты в исключении из JAXB:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Client</faultcode>
         <faultstring>Unmarshalling Error: unexpected element (uri:"http://www.example.org/order", local:"id"). Expected elements are &lt;{}id></faultstring>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

Во всех исследованиях, которые я проводил, это обычно означает, что пространство имен где-то не совпадает. Но я проверил это полностью, и пространство имен везде одинаково, включая ObjectFactory.class, package-info.class и файл конфигурации cxf-servlet.xml, а также аннотацию @WebService. Кто-нибудь может указать мне правильное направление относительно того, что мне здесь не хватает?

1 ответ

Решение

Источник проблемы - wsgen, и я думаю, что это ошибка. Это не делает совместимые сгенерированные классы wsdl и jaxb. В сгенерированных jaxb классах элементы не соответствуют форме по умолчанию, что помещает элемент параметра в пустое пространство имен. Однако в WSDL это форма по умолчанию квалифицирована, и в этом заключается проблема. Вероятно, есть несколько способов решить эту проблему, самый быстрый и грязный способ, который я нашел, - это установить targetNamespace в аннотации @WebParam. Вот фрагменты кода, чтобы продемонстрировать, что я имею в виду, и я надеюсь, что это поможет кому-то еще, кто сталкивается с этим.

Вот что у меня было изначально для класса реализации снизу вверх:

@WebService(serviceName="OrderService")
public class OrderService {

    public OrderResponse getOrder(@WebParam(name="id", targetNamespace="http://www.example.org/order") String id)  {

Это приведет к следующим сгенерированным классам JAXB. Как вы можете видеть, он устанавливает пространство имен для корня, но не соответствует форме, и также не генерирует файл информации о пакете.

@XmlRootElement(name = "getOrder", namespace = "http://www.example.org/order")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getOrder", namespace = "http://www.example.org/order")

public class GetOrder {

    @XmlElement(name = "id")
    private java.lang.String id;

Затем я изменил класс реализации сервиса, чтобы добавить пространство имен в @WebParam:

@WebService(serviceName="OrderService", targetNamespace="http://www.example.org/order")
public class OrderService {

    public OrderResponse getOrder(@WebParam(name="id", targetNamespace="http://www.example.org/order") String id)  {

Хотя это не делает его пригодным для формы по умолчанию, оно добавляет пространство имен к элементу в сгенерированном классе JAXB:

@XmlRootElement(name = "getOrder", namespace = "http://www.example.org/order")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "getOrder", namespace = "http://www.example.org/order")

public class GetOrder {

    @XmlElement(name = "id", namespace = "http://www.example.org/order")
    private java.lang.String id;
Другие вопросы по тегам