У меня есть веб-сервис, написанный на 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. До сих пор это не вызывало у меня никаких проблем, но об этом следует знать на случай, если у вас возникнут проблемы.