Fernando Barrocal
Fernando Barrocal

Reputation: 13162

Soap WSDL ComplexType being posted as wrong argument type

I have a server (SoapUI) answering requests for a WSDL.

When sending test requests, my server code is receiving a list of arguments, but I'm trying to achieve is a single argument, of complex type, eg:

{
 ingredient_id   => INT
 something       => STRING
 ...
}

My types are as follow:

  <wsdl:types>
    <xsd:schema targetNamespace="/ingredient">
      <xsd:element name="getIngredientInfo" type="tns:IngredientRequest"></xsd:element>
      <xsd:element name="getIngredientInfoResponse" type="tns:ingredient"></xsd:element>

      <xsd:complexType name="ingredient">
        <xsd:sequence>
            <xsd:element name="ingredient_id" type="xsd:int" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="ingredient_name" type="xsd:string" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="status_gm" type="xsd:boolean" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="status_vegan" type="xsd:boolean" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="status_vegetarian" type="xsd:boolean" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="author_id" type="xsd:int" block="#all" minOccurs="1" maxOccurs="1"></xsd:element>
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="IngredientRequest">
        <xsd:sequence>
            <xsd:element name="ingredient_id" type="xsd:int"></xsd:element>
            <xsd:element name="something" type="xsd:string"></xsd:element>
        </xsd:sequence>
      </xsd:complexType>

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

Can somebody help me to understand why WSDL is making SoapUI send the arguments as a list of simple arguments, instead of a single complex argument?

EDIT: It might be some problem with sequence tag, but I can't find the issue in that, just need some light. Thanks in advance!


Sure, I have it right here:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions
  name="ingredient"
  targetNamespace="/ingredient"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="/ingredient"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <xsd:schema targetNamespace="/ingredient">
      <xsd:element name="getIngredientInfo" type="tns:IngredientRequest"></xsd:element>
      <xsd:element name="getIngredientInfoResponse" type="tns:ingredient"></xsd:element>

      <xsd:complexType name="ingredient">
        <xsd:sequence>
            <xsd:element name="ingredient_id" type="xsd:int" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="ingredient_name" type="xsd:string" minOccurs="1" maxOccurs="1"></xsd:element>

            <xsd:element name="status_gm" type="xsd:boolean" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="status_vegan" type="xsd:boolean" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="status_vegetarian" type="xsd:boolean" minOccurs="1" maxOccurs="1"></xsd:element>
            <xsd:element name="author_id" type="xsd:int" block="#all" minOccurs="1" maxOccurs="1"></xsd:element>
        </xsd:sequence>
      </xsd:complexType>


      <xsd:complexType name="IngredientRequest">
        <xsd:sequence>
            <xsd:element name="ingredient_id" type="xsd:int"></xsd:element>

            <xsd:element name="something" type="xsd:string"></xsd:element>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="getIngredientInfoRequest">
    <wsdl:part element="tns:getIngredientInfo" name="parameters"/>
  </wsdl:message>
  <wsdl:message name="getIngredientInfoResponse">

    <wsdl:part element="tns:getIngredientInfoResponse"
        name="parameters" />
  </wsdl:message>
  <wsdl:portType name="ingredient">
    <wsdl:operation name="getIngredientInfo">
      <wsdl:input message="tns:getIngredientInfoRequest"/>
      <wsdl:output message="tns:getIngredientInfoResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ingredientSOAP" type="tns:ingredient">

    <soap:binding style="document"
        transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getIngredientInfo">
        <soap:operation
            soapAction="http://entropy.homelinux.org/kasak/" />
        <wsdl:input>
            <soap:body use="literal" />
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal" />
        </wsdl:output>

    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ingredient">
    <wsdl:port binding="tns:ingredientSOAP" name="ingredientSOAP">
      <soap:address location="http://entropy.homelinux.org/kasak/"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Still have no hints on it :(

Upvotes: 2

Views: 23000

Answers (4)

wierob
wierob

Reputation: 4359

You need to write your WSDL in "Document/literal wrapped"-style. These WSDL-styles are a bit confusing but here is a good comparison.

In essence you will need to wrap your complexType into an element:

<element name="IngredientInfo">
  <complexType>
    <sequence>
            <element name="ingredient_id" type="xsd:int"></xsd:element>
            <element name="something" type="xsd:string"></xsd:element>
    </sequence>
  </complexType>
</element>

and specify this element to be send as message

<message name="getIngredientInfoRequest">
    <part name="parameters" element="IngredientInfo"/>
</message>

Thus the resulting SOAP message contains this the IngredientInfo-element as the only child of the SOAP body:

<soap:envelope>
    <soap:body>
        <IngredientInfo>
            <ingredient_id>42</ingredient_id>
            <something>"What is..."</something>
        </IngredientInfo>
    </soap:body>
</soap:envelope>

Upvotes: 11

rpg89
rpg89

Reputation: 11

My understanding is that you currently have something like the following (I'm doing a web service call in Java, so I'll example in it):

SOAPCaller.getIngredientInformation(3, "something");

However, what you'd really like is the following:

IngredientRequest ingredientRequest = new IngredientRequest(3, "something");
SOAPCaller.getIngredientInformation(ingredientRequest);

Trying something like what Wierob suggested caused the first case to be what was generated for me. Unfortunately, the only way that I found to achieve the second is to do extra encapsulation which is messy (extra classes are generated). Yet, it allows a single object to be sent and a single object to be returned, rather than a number of objects. Here's an example:

<!-- assume the including of your complex types from above -->
<xsd:element name="getIngredientInfo" >
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="ingredient" type="tns:IngredientRequest" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

<xsd:element name="getIngredientInfoResponse" >
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="ingredientResponse" type="tns:ingredient" />
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

Upvotes: 0

shivaspk
shivaspk

Reputation: 610

Ok after using your WSDL for generating a sample request using my SOAP UI here is what I see

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ing="/ingredient">
   <soapenv:Header/>
   <soapenv:Body>
      <ing:getIngredientInfo>
         <ingredient_id>?</ingredient_id>
         <something>?</something>
      </ing:getIngredientInfo>
   </soapenv:Body>
</soapenv:Envelope>

So as seen its creating a single getIngredientInfo request object no arrays. Please confirm, try using latest version of SOAP UI if required!

Upvotes: 0

shivaspk
shivaspk

Reputation: 610

I don't think WSDL Type (IngredientRequest) is the issue, can you show the complete WSDL, especially the operation which you are testing if that's accepting a array of IngredientRequest type then that is the answer, why SOAP UI is sending a list of arguments.

Upvotes: 1

Related Questions