views:

73

answers:

1

I need to write a WSDL file to an existing web service which is provided to me by a colleague (it's realized with Perl and SOAP::Lite). Therefore, I have a given format for the SOAP-response and need to define the service formally to be able to generate the code for a Java client to the service. To test the WSDL file against the service, I have been using both Eclipse's Web Service Explorer and soapUI, to generate the code for the client I aim to use the Axis version distributed with Eclipse (1.3.x).

The definition file I have at the moment does work to access the service through soapUI and returns the desired SOAP-response which can also be asserted to be Schema compliant by soapUI, but if I generate code from it and try to run the code, things start to fall apart. Apparently, Axis does not recognize the defined types correctly and just creates members with an "anyType" type. The response can therefore not be serialized correctly which results in an exception by the SAX parser.

When I try to validate my WSDL file, I'm told it is not allowed to define an element with just another element as child, which I assume is the root of my troubles here. I tried to nest the "prefix_map" element into an anonymous complexType as the single item of a sequence, but now the Schema compliance assertion in soupUI fails. So how can I define the types for the response-message correctly for the given response?

This is the SOAP-response I get from the service:

 <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema"&gt;
    <SOAP-ENV:Body>
    <namesp1:get_dest_prefixResponse xmlns:namesp1="PortaTAPI">
       <prefix_map>
          <country xsi:type="xsd:string">SWITZERLAND</country>
          <iso_3166_1_a2 xsi:type="xsd:string">CH</iso_3166_1_a2>
          <i_group xsi:type="xsd:int">0</i_group>
          <destination xsi:type="xsd:long">41445551234</destination>
          <i_env xsi:type="xsd:int">2</i_env>
          <i_dest xsi:type="xsd:int">10007</i_dest>
          <description xsi:type="xsd:string">Customer AG - Wholesale</description>
          <i_country_subdivision xsi:type="xsd:int">2855</i_country_subdivision>
          <dest_type xsi:null="1"/>
          <i_time_zone xsi:null="1"/>
       </prefix_map>
    </namesp1:get_dest_prefixResponse>
    </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>

This is the relevant part of my WSDL file:

 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <wsdl:definitions 
  name="PortaTAPI" 
  targetNamespace="PortaTAPI" 
  xmlns:tns="PortaTAPI"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;

  <!-- Type Definitions -->
  <wsdl:types>
   <xsd:schema targetNamespace="PortaTAPI">

    <xsd:complexType name="t_prefix_map">
     <xsd:all>
      <xsd:element name="country" type="xsd:string" minOccurs="1" />
      <xsd:element name="iso_3166_1_a2" type="xsd:string" minOccurs="1" />
      <xsd:element name="i_group" type="xsd:int" minOccurs="1" />
      <xsd:element name="destination" type="xsd:long" minOccurs="1" />
      <xsd:element name="i_env" type="xsd:int" minOccurs="1" />
      <xsd:element name="i_dest" type="xsd:int" minOccurs="1" />
      <xsd:element name="description" type="xsd:string" minOccurs="0" />
      <xsd:element name="i_country_subdivision" type="xsd:int" minOccurs="1" />
      <xsd:element name="dest_type" type="xsd:string" nillable="true" minOccurs="0" />
      <xsd:element name="i_time_zone" type="xsd:string" nillable="true" minOccurs="0" />
     </xsd:all>
    </xsd:complexType>

    <xsd:complexType name="t_tariff_map">
     <xsd:all>
      <xsd:element name="i_tariff" type="xsd:int"/>
     </xsd:all>
    </xsd:complexType>


    <xsd:element name="get_dest_prefix">
     <xsd:complexType>
      <xsd:all>
       <xsd:element name="prefix" type="xsd:long" minOccurs="1" />
       <xsd:element name="i_env" type="xsd:int" minOccurs="1" />
      </xsd:all>
     </xsd:complexType>
    </xsd:element>
    <xsd:element name="get_dest_prefixResponse">
     <xsd:element name="prefix_map" type="tns:t_prefix_map" />
    </xsd:element>
    <!-- This causes the Schema compliance assertion of soapUI to fail
    <xsd:element name="get_dest_prefixResponse">
     <xsd:complexType>
      <xsd:sequence>
       <xsd:element name="prefix_map" type="tns:t_prefix_map" />
      </xsd:sequence>
     </xsd:complexType>
    </xsd:element>
    -->

   </xsd:schema>
  </wsdl:types>

  <!-- Messages -->
  <wsdl:message name="get_dest_prefixRequest">
   <wsdl:part name="parameters" element="tns:get_dest_prefix" />
  </wsdl:message>
  <wsdl:message name="get_dest_prefixResponse">
   <wsdl:part name="result" element="tns:get_dest_prefixResponse" />
  </wsdl:message>

  <!-- Port -->
  <wsdl:portType name="PortaTAPI">

   <wsdl:operation name="get_dest_prefix">
    <wsdl:input message="tns:get_dest_prefixRequest" />
    <wsdl:output message="tns:get_dest_prefixResponse" />
   </wsdl:operation>

  </wsdl:portType>

  <!-- Bindings -->
  <wsdl:binding name="PortaTAPISOAP" type="tns:PortaTAPI">
   <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />

   <wsdl:operation name="get_dest_prefix">
    <soap:operation soapAction="PortaTAPI#get_dest_prefix" />
    <wsdl:input>
     <soap:body use="literal" />
    </wsdl:input>
    <wsdl:output>
     <soap:body use="literal" />
    </wsdl:output>
   </wsdl:operation>

  </wsdl:binding>

  <!-- Service -->
  <wsdl:service name="PortaTAPI">
   <wsdl:port binding="tns:PortaTAPISOAP" name="PortaTAPISOAP">
    <soap:address location="https://62.65.137.91:3113/soap.pl" />
   </wsdl:port>
  </wsdl:service>

 </wsdl:definitions>

This is the exception the client (generated by Axis) throws:

Sep 14, 2010 2:22:28 PM org.apache.axis.client.Call invoke
SEVERE: Exception:
org.xml.sax.SAXException: Deserializing parameter 'get_dest_prefixResponse':  could not find deserializer for type {http://www.w3.org/2001/XMLSchema}anyType
    at org.apache.axis.message.RPCHandler.onStartChild(RPCHandler.java:277)
    at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035)
    at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
    at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141)
    at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:236)
    at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384)
    at org.apache.axis.client.Call.invoke(Call.java:2467)
    at org.apache.axis.client.Call.invoke(Call.java:2366)
    at org.apache.axis.client.Call.invoke(Call.java:1812)
    at com.netstream.ch.porta.tapi.PortaTAPISOAPStub.get_dest_prefix(PortaTAPISOAPStub.java:261)
    at com.netstream.ch.porta.services.DestinationManagementService.getDestination(DestinationManagementService.java:49)
    at com.netstream.ch.porta.PortaServicesTest.actionPerformed(PortaServicesTest.java:219)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
    at java.awt.Component.processMouseEvent(Component.java:6263)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
    at java.awt.Component.processEvent(Component.java:6028)
    at java.awt.Container.processEvent(Container.java:2041)
    at java.awt.Component.dispatchEventImpl(Component.java:4630)
    at java.awt.Container.dispatchEventImpl(Container.java:2099)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4238)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
    at java.awt.Container.dispatchEventImpl(Container.java:2085)
    at java.awt.Window.dispatchEventImpl(Window.java:2478)
    at java.awt.Component.dispatchEvent(Component.java:4460)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode: 
 faultString: org.xml.sax.SAXException: Deserializing parameter 'get_dest_prefixResponse':  could not find deserializer for type {http://www.w3.org/2001/XMLSchema}anyType
 faultActor: 
 faultNode: 
 faultDetail: 
    {http://xml.apache.org/axis/}stackTrace:org.xml.sax.SAXException: Deserializing parameter 'get_dest_prefixResponse':  could not find deserializer for type {http://www.w3.org/2001/XMLSchema}anyType

Thanks for your help!

+1  A: 

Ok. After you comment below I have refined my answer. I believe that Axis is looking for a concrete type for the element in question. Since it is not defined it assumes it is anyType, which it then has a hard time with. I would do the following:

<xsd:element name="get_dest_prefix">
 <xsd:complexType>
  <xsd:all>
   <xsd:element name="prefix" type="xsd:long" minOccurs="1" />
   <xsd:element name="i_env" type="xsd:int" minOccurs="1" />
  </xsd:all>
 </xsd:complexType>
</xsd:element>
<xsd:element name="get_dest_prefixResponse" type="tns:t_get_dest_prefixResponse"/>
<xsd:complexType name="t_get_dest_prefixResponse">
  <xsd:sequence>
    <xsd:element name="prefix_map" type="tns:t_prefix_map" minOccurs="1"/>
  </xsd:sequence>
</xsd:complexType>

Did that help any? That might make it more explicit and allow Axis to find what it wants.

Chris Aldrich
The problem seems to be that it is not allowed to define an element directly within another element, like I tried to with the element "get_dest_prefixResponse" that contains the element "prefix_map". From my understanding of WSDL, I would think that it should not make any difference whether I define the Schema for the types inline as XSD or in a seperate XSD file.I had to create the WSDL file by hand from the SOAP envelope since SOAP:Lite apparently does not need one and, since Perl is dynamically typed, my colleague could not tell me the exact types of his replies.
wtfc63
It sure helped :-) Although the Schema compliance assertion in soapUI fails now, Axis is able to generate classes for a working client which, from the looks of it, interacts correctly with the service. Thanks a lot for your help!
wtfc63