Axis2 всегда получает нулевые параметры, даже если запрос SOAP отправляется правильно?

У меня есть веб-сервис, написанный на Java, размещенный на сервере Axis2/Tomcat/Apache. Мое клиентское программное обеспечение написано на C#.

У меня было несколько раздражающих проблем с тем, как java2wsdl генерирует файл wsdl, что вызывало у меня несколько головных болей на раннем этапе, но с этой проблемой я полностью зашел в тупик.

В основном происходит то, что клиент видит веб-службу в порядке и отправляет совершенно действительный (или, по крайней мере, мне он кажется действительным) запрос SOAP с параметрами.

На сервере выполняется правильный веб-метод, но все параметры нулевые. Мой веб-сервис обнаруживает это и формирует ответ, который клиент получает и прекрасно понимает.

Я подозреваю, что Axis2 где-то рушится, но, учитывая головные боли, которые у меня были с java2wsdl, возможно, все, что мне нужно, это изменить мой файл wsdl.

Вот wsdl-файл:

    <?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:axis2="http://stws/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:ns0="http://stws/xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://stws/">
    <wsdl:types>
        <xs:schema xmlns:ns="http://stws/xsd" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://stws/xsd">
            <xs:element name="GetGroups">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="serialcode" nillable="true" type="xs:string"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="GetGroupsResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element maxOccurs="unbounded" minOccurs="0" name="return" nillable="true" type="ns0:Group"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:complexType name="Group">
                <xs:sequence>
                    <xs:element minOccurs="0" name="ID" type="xs:int"/>
                    <xs:element minOccurs="0" name="Name" nillable="true" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
            <xs:element name="GetMessages">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="serialcode" nillable="true" type="xs:string"/>
                        <xs:element maxOccurs="unbounded" minOccurs="0" name="groupids" type="xs:int"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="GetMessagesResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element maxOccurs="unbounded" minOccurs="0" name="return" nillable="true" type="ns0:Message"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:complexType name="Message">
                <xs:sequence>
                    <xs:element minOccurs="0" name="date" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="group" type="xs:int"/>
                    <xs:element minOccurs="0" name="messageID" type="xs:int"/>
                    <xs:element minOccurs="0" name="text" nillable="true" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
        </xs:schema>
    </wsdl:types>
    <wsdl:message name="GetMessagesRequest">
        <wsdl:part name="parameters" element="ns0:GetMessages"/>
    </wsdl:message>
    <wsdl:message name="GetMessagesResponse">
        <wsdl:part name="parameters" element="ns0:GetMessagesResponse"/>
    </wsdl:message>
    <wsdl:message name="GetGroupsRequest">
        <wsdl:part name="parameters" element="ns0:GetGroups"/>
    </wsdl:message>
    <wsdl:message name="GetGroupsResponse">
        <wsdl:part name="parameters" element="ns0:GetGroupsResponse"/>
    </wsdl:message>
    <wsdl:portType name="MyProjectPortType">
        <wsdl:operation name="GetMessages">
            <wsdl:input message="axis2:GetMessagesRequest" wsaw:Action="urn:GetMessages"/>
            <wsdl:output message="axis2:GetMessagesResponse" wsaw:Action="urn:GetMessagesResponse"/>
        </wsdl:operation>
        <wsdl:operation name="GetGroups">
            <wsdl:input message="axis2:GetGroupsRequest" wsaw:Action="urn:GetGroups"/>
            <wsdl:output message="axis2:GetGroupsResponse" wsaw:Action="urn:GetGroupsResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="MyProjectSOAP11Binding" type="axis2:MyProjectPortType">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        <wsdl:operation name="GetMessages">
            <soap:operation soapAction="urn:GetMessages" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="GetGroups">
            <soap:operation soapAction="urn:GetGroups" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="MyProjectSOAP12Binding" type="axis2:MyProjectPortType">
        <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        <wsdl:operation name="GetMessages">
            <soap12:operation soapAction="urn:GetMessages" style="document"/>
            <wsdl:input>
                <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="GetGroups">
            <soap12:operation soapAction="urn:GetGroups" style="document"/>
            <wsdl:input>
                <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="MyProjectHttpBinding" type="axis2:MyProjectPortType">
        <http:binding verb="POST"/>
        <wsdl:operation name="GetMessages">
            <http:operation location="MyProject/GetMessages"/>
            <wsdl:input>
                <mime:content type="text/xml" part="GetMessages"/>
            </wsdl:input>
            <wsdl:output>
                <mime:content type="text/xml" part="GetMessages"/>
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="GetGroups">
            <http:operation location="MyProject/GetGroups"/>
            <wsdl:input>
                <mime:content type="text/xml" part="GetGroups"/>
            </wsdl:input>
            <wsdl:output>
                <mime:content type="text/xml" part="GetGroups"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="MyProject">
        <wsdl:port name="MyProjectSOAP11port_http" binding="axis2:MyProjectSOAP11Binding">
            <soap:address location="http://localhost:8080/axis2/services/MyProject"/>
        </wsdl:port>
        <wsdl:port name="MyProjectSOAP12port_http" binding="axis2:MyProjectSOAP12Binding">
            <soap12:address location="http://localhost:8080/axis2/services/MyProject"/>
        </wsdl:port>
        <wsdl:port name="MyProjectHttpport" binding="axis2:MyProjectHttpBinding">
            <http:address location="http://localhost:8080/axis2/services/MyProject"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

А вот пример запроса и ответа:

Запрос:

<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Body>
    <GetGroups xmlns="http://stws/xsd">
      <serialcode>123456-654321</serialcode>
    </GetGroups>
  </soap:Body>
</soap:Envelope>

Ответ

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <GetGroupsResponse xmlns="http://stws/xsd">
      <return>
        <ID>-101</ID>
        <name>ERROR: Empty Serial</name>
      </return>
    </GetGroupsResponse>
  </soapenv:Body>
</soapenv:Envelope>

Кто-нибудь знает, что может пойти не так?

Сообщение об ошибке в ответе может быть отправлено только тогда, когда параметр серийного кода в запросе пуст/нуль, поэтому я предполагаю, что что-то не так с тем, как Axis2 читает мои параметры.

============================================================

Как это исправить:

Это ответ на запрос Альдо о дополнительной информации о том, как я решил эту проблему.

Я не уверен, почему это исправление работает - возможно, это просто ошибка в Axis2 или что-то в этом роде. В любом случае, YMMV, поскольку я не знаю, была ли проблема вызвана моей настройкой или чем-то еще. Все, что я могу сказать, это то, что, сделав следующее, все заработало.

В любом случае, автоматически сгенерированный файл WSDL создает типы сложных элементов для веб-запросов и их параметров, даже если единственными параметрами являются простые типы, такие как строки или целые числа. Что я сделал, так это прошел и создал правильные теги простого типа для параметров (таких как «серийный код» или «строка даты»), а затем заменил ссылки на сложные типы в другом месте в файле WSDL ссылками на простые типы.

Пример ниже:

Автоматически сгенерированный метод и параметры WSDL

<!--Requests-->    
<wsdl:message name="RegisterClientRequest">
    <wsdl:part name="parameters" element="ns0:RegisterClient"/>
</wsdl:message>
<wsdl:message name="GetGroupsRequest">
    <wsdl:part name="parameters" element="ns0:GetGroups"/>
</wsdl:message>

<!--Parameters-->
<xs:element name="RegisterClient">
    <xs:complexType>
        <xs:sequence>
           <xs:element minOccurs="0" name="serialcode" nillable="true" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>
<xs:element name="GetGroups">
    <xs:complexType>
        <xs:sequence>
            <xs:element minOccurs="0" name="serialcode" nillable="true" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
 </xs:element>

По сути, вам следует отказаться от автоматически сгенерированных параметров и создать простые типы. Затем вы изменяете теги «запрос», чтобы использовать «тип», а не «элемент», и используете только что созданные простые типы.

Измененный/исправленный WSDL

<!--Requests-->    
<wsdl:message name="RegisterClientRequest">
    <wsdl:part name="parameters" type="ns0:SerialCode"/>
</wsdl:message>
<wsdl:message name="GetGroupsRequest">
    <wsdl:part name="parameters" type="ns0:SerialCode"/>
</wsdl:message>

<!--Parameters-->
<xs:simpleType name="SerialCode">
    <xs:restriction base="xs:string"/>
</xs:simpleType>

Очевидно, это зависит от ваших параметров на самом деле. В моем случае это все стандартные простые типы, такие как строки и целые числа. Если вы передаете более одного параметра, вам может потребоваться поиграть, сохранив автоматически сгенерированные элементы, но убедившись, что элемент относится к простым типам, а не просто включает атрибут типа как «xs: string» или что-то в этом роде. .

Извините, я не могу быть более ясным по этому поводу, но, как я уже сказал ранее, я не знаю, почему это работает.

И последнее: удалив атрибут ссылки «элемент» в тегах запроса, вы можете получить предупреждение синтаксического анализатора в журналах Axis2. До сих пор это не вызывало у меня никаких проблем, но об этом следует знать на случай, если у вас возникнут проблемы.


person HalliHax    schedule 16.06.2009    source источник
comment
Какой компонент выполняет проверку и генерирует это сообщение об ошибке? Если это ваш код, можете ли вы убедиться, что данные запроса отсутствуют к тому времени, когда он зайдет так далеко?   -  person skaffman    schedule 16.06.2009
comment
Фактические веб-методы сами выполняют быструю проверку (действительно, единственная причина, по которой проверка существует, заключается в том, что я получал нулевые результаты — это просто дает мне простой способ подтвердить, что ввод был нулевым!). Простое модульное тестирование кода веб-службы не приводит к этой проблеме, а собственный SOAPMonitor Axis2 показывает, что клиент действительно отправляет требуемые параметры, но по какой-то причине параметры обнуляются к тому времени, когда Axis2 вызывает веб-методы.   -  person HalliHax    schedule 16.06.2009


Ответы (6)


Я решил эту проблему, просматривая свой файл WSDL и, где это возможно, разбивая элементы на их аналоги простого типа и соответствующим образом обновляя ссылки между элементами XML.

Я не уверен, почему это работает, но это все равно решило мою проблему.

person HalliHax    schedule 29.06.2009

Если бы у вас был сложный атрибут, вот как вы могли бы это сделать

До

 <xs:element name="getMyMenu">
            <xs:complexType>
                <xs:sequence>
                    <xs:element minOccurs="0" name="number" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="var2" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="var3" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="var4" nillable="true" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>

После

            <xs:complexType name="getMyMenu">
                <xs:sequence>
                    <xs:element minOccurs="0" name="number" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="var2" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="var3" nillable="true" type="xs:string"/>
                    <xs:element minOccurs="0" name="var4" nillable="true" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>

А потом изменить это

<wsdl:message name="getMyMenuRequest">
    <wsdl:part name="parameters" type="ns0:getUssdMenu"/>
</wsdl:message>

To

<wsdl:message name="getMyMenuRequest">
    <wsdl:part name="parameters" type="ns:getUssdMenu"/>
</wsdl:message>

Это должно быть так! Это сделало это для меня ....

person Ngetha    schedule 04.11.2010

Это всего лишь догадка, но, возможно, у вас проблема с пространством имен. Если вы сосредоточитесь на этой части wsdl, обратите внимание, что ваш параметр имеет пространство имен «ns0» для элементов, но в ваших операциях, определенных позже, похоже, что вы используете пространство имен «axis2». Во всех моих WSDL, созданных Axis2, эти два пространства имен одинаковы.

<wsdl:message name="GetMessagesRequest">
    <wsdl:part name="parameters" element="ns0:GetMessages"/>
</wsdl:message>
<wsdl:message name="GetMessagesResponse">
    <wsdl:part name="parameters" element="ns0:GetMessagesResponse"/>
</wsdl:message>
<wsdl:message name="GetGroupsRequest">
    <wsdl:part name="parameters" element="ns0:GetGroups"/>
</wsdl:message>
<wsdl:message name="GetGroupsResponse">
    <wsdl:part name="parameters" element="ns0:GetGroupsResponse"/>
</wsdl:message>

<wsdl:portType name="MyProjectPortType">
    <wsdl:operation name="GetMessages">
        <wsdl:input message="axis2:GetMessagesRequest" wsaw:Action="urn:GetMessages"/>
        <wsdl:output message="axis2:GetMessagesResponse" wsaw:Action="urn:GetMessagesResponse"/>
    </wsdl:operation>
    <wsdl:operation name="GetGroups">
        <wsdl:input message="axis2:GetGroupsRequest" wsaw:Action="urn:GetGroups"/>
        <wsdl:output message="axis2:GetGroupsResponse" wsaw:Action="urn:GetGroupsResponse"/>
    </wsdl:operation>
</wsdl:portType>

Еще одна вещь, которую вы можете проверить, это убедиться, что wsdl, который вы получили от java2wsdl, совпадает с тем, который генерируется axis2. Если вы не изменили настройку по умолчанию «useoriginalwsdl» в файле services.xml, эти wsdls могут «выглядеть» по-разному. Мне никогда не приходилось выполнять java2wsdl вручную, чтобы мой веб-сервис работал правильно...

В общем, нажмите URL-адрес службы в браузере и добавьте ?wsdl в конце URL-адреса... вы должны получить wsdl для сравнения.

Кроме того, ваш клиент должен генерировать заглушки из wsdl сервера, а не из java2wsdl (при условии, что вы изначально использовали wsdl из java2wsdl). Опять же, нам никогда не приходилось никому передавать сгенерированный вручную wsdl... они просто потребляли динамически сгенерированный с сервера...

person Tim Reddy    schedule 16.06.2009
comment
Я так и думал, но пространство имен axis2 автоматически генерируется java2wsdl. Я бы подумал, что тот факт, что веб-метод вызывается успешно, означает, что это не может быть проблемой пространства имен, но я попытаюсь. - person HalliHax; 16.06.2009
comment
После изменения оси2 на ns0 клиент больше не мог интерпретировать возвращаемые значения, поэтому я не думаю, что это проблема. В любом случае спасибо за ваш вклад! - person HalliHax; 16.06.2009

Пробовали ли вы отправить такой запрос?

<?xml version='1.0' encoding='utf-8'?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soap:Body>
    <request>
      <GetGroups xmlns="http://stws/xsd">
        <serialcode>123456-654321</serialcode>
      </GetGroups>
    </request>
  </soap:Body>
</soap:Envelope>

Все мои запросы имеют тег request перед фактическими параметрами запроса.

person Community    schedule 26.06.2009
comment
Спасибо, что нашли время ответить osrichie, но мне удалось решить проблему, разбивая элементы на их эквиваленты простого типа, где это возможно. Я не понимаю, почему это работает (ошибка в Axis2?), но, кажется, это устраняет проблему. - person HalliHax; 29.06.2009

попробуйте это: 123456-654321

Поместите xmlns="" в тег параметра. У меня такая же проблема, и я не знаю, что я могу изменить, чтобы получить параметр без xmlnx.

person Community    schedule 24.08.2009

У меня другое исправление. В конце концов я обнаружил, что если я не позволю своей IDE (Netbeans 6.8) генерировать WSDL, веб-служба будет работать. В качестве альтернативы, если бы я удалил его, снял флажок с опции генерации и повторно развернул, тогда это сработало.

Сравнивая сгенерированный Netbeans WSDL с сгенерированным сервером, я заметил следующие различия:

  • xmlns:ns0="http:///xsd"
  • целевое пространство имен в конце тега wsdl:definitions имело завершающую косую черту
  • ns0 используется для выбора элементов, составляющих тег wsdl:message.

Удаление всего этого и повторное развертывание сработало!

person Ben Howell-Thomas    schedule 04.03.2010