Android Ksoap2 - complex type(request and response)

11,898

Solution 1

Your UserRequest class needs to implement org.ksoap2.serialization.KvmSerializable.

Solution 2

I would insist to simply get the response in XML and use any XML Parser to parse the response that would be just easier. Also I would insist you to use ksoap2-android-assembly-2.5.4-jar-with-dependencies.jar the one you are using is deprecated.

AndroidHttpTransport is being replaced by HttpTransportSE

Here is how you can get response in XML,

HttpTransportSE androidHttpTransport = new HttpTransportSE(URL, 100);
androidHttpTransport.debug=true; 
androidHttpTransport.call(SOAP_ACTION, envelope);
String response = androidHttpTransport.responseDump;
Log.d("Response in XML", response);

You will get the response in response String and the you can parse it using SAX or any other XML parser.

Share:
11,898
Manoj
Author by

Manoj

Updated on June 05, 2022

Comments

  • Manoj
    Manoj almost 2 years

    I am using ksoap2 to call the java webservice in Android. Java Web service method is,

    ImageProcessImpl.java

    public UserResponse sample(UserRequest userRequest) {
         return ImageProcessDAO.sample(userRequest);
    }
    

    ImageProcessDAO.java

    public static String sample(UserRequest userRequest) {
         System.out.println(userRequest.getClientName());
         UserResponse UserResponse = new UserResponse();
         userResponse.setMessage("SUCCESS");
         return userResponse;
    }
    

    I am calling these webservices from Android as,

    try{
            String NAMESPACE = "http://impl.test.com";
            String URL = "http://10.0.2.2:8080/Webservice/services/ImageProcessImpl?wsdl";  
            String SOAP_ACTION = "http://impl.test.com/sample";
            String METHOD_NAME = "sample";
    
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 
    
            UserRequest userRequest = new UserRequest();            
            userRequest.setClientName("Test");
    
            PropertyInfo pi = new PropertyInfo();
            pi.setName("userRequest");
            pi.setValue(userRequest);
            pi.setType(UserRequest.class);
            request.addProperty(pi);
    
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
            envelope.setOutputSoapObject(request);  
            envelope.implicitTypes = true;
            envelope.addMapping(NAMESPACE, "UserResponse", UserResponse.class);
    
            AndroidHttpTransport httpTransport = new AndroidHttpTransport(URL);  
            httpTransport.debug = true;
            httpTransport.call(SOAP_ACTION, envelope);
    
           UserResponse response = (UserResponse) envelope.getResponse(); 
           Log.e(Test.LOG_TAG, response.getMessage());
            }catch (Exception e) {
                Log.e(Test.LOG_TAG, "throws an exception: " + e.getMessage());
            }
    

    But I am getting the error in my Logcat is "throws an exception: Cannot serialize: com.test.common.UserRequest". How to fix this error? Is this right way to call web service with complex type?

    my wsdl file is,

    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions targetNamespace="http://impl.test.com" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://impl.test.com" xmlns:intf="http://impl.test.com" xmlns:tns1="http://common.test.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <!--WSDL created by Apache Axis version: 1.4
    Built on Apr 22, 2006 (06:55:48 PDT)-->
     <wsdl:types>
      <schema elementFormDefault="qualified" targetNamespace="http://impl.test.com" xmlns="http://www.w3.org/2001/XMLSchema">
       <import namespace="http://common.test.com"/>
       <element name="sample">
        <complexType>
         <sequence>
          <element name="userRequest" type="tns1:UserRequest"/>
         </sequence>
        </complexType>
       </element>
       <element name="sampleResponse">
        <complexType>
         <sequence>
          <element name="sampleReturn" type="tns1:UserResponse"/>
         </sequence>
        </complexType>
       </element>
      </schema>
      <schema elementFormDefault="qualified" targetNamespace="http://common.test.com" xmlns="http://www.w3.org/2001/XMLSchema">
       <complexType name="UserRequest">
        <sequence>
         <element name="clientName" nillable="true" type="xsd:string"/>
        </sequence>
       </complexType>
       <complexType name="UserResponse">
        <sequence>
         <element name="message" nillable="true" type="xsd:string"/>
        </sequence>
       </complexType>
      </schema>
     </wsdl:types>
    
       <wsdl:message name="sampleRequest">
    
          <wsdl:part element="impl:sample" name="parameters">
    
          </wsdl:part>
    
       </wsdl:message>
    
       <wsdl:message name="sampleResponse">
    
          <wsdl:part element="impl:sampleResponse" name="parameters">
    
          </wsdl:part>
    
       </wsdl:message>
    
       <wsdl:portType name="ImageProcessImpl">
    
          <wsdl:operation name="sample">
    
             <wsdl:input message="impl:sampleRequest" name="sampleRequest">
    
           </wsdl:input>
    
             <wsdl:output message="impl:sampleResponse" name="sampleResponse">
    
           </wsdl:output>
    
          </wsdl:operation>
    
       </wsdl:portType>
    
       <wsdl:binding name="ImageProcessImplSoapBinding" type="impl:ImageProcessImpl">
    
          <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
          <wsdl:operation name="sample">
    
             <wsdlsoap:operation soapAction=""/>
    
             <wsdl:input name="sampleRequest">
    
                <wsdlsoap:body use="literal"/>
    
             </wsdl:input>
    
             <wsdl:output name="sampleResponse">
    
                <wsdlsoap:body use="literal"/>
    
             </wsdl:output>
    
          </wsdl:operation>
    
       </wsdl:binding>
    
       <wsdl:service name="ImageProcessImplService">
    
          <wsdl:port binding="impl:ImageProcessImplSoapBinding" name="ImageProcessImpl">
    
             <wsdlsoap:address location="http://localhost:8080/Webservice/services/ImageProcessImpl"/>
    
          </wsdl:port>
    
       </wsdl:service>
    
    </wsdl:definitions>
    

    I used the KvmSerializable. I have added one more array bean variable private Client[] clientNameList = null; in UserRequest.java.

    When I call the web service it is working fine in the request. But in the response I am getting one string that contains all values. The response string is given below.

    anyType{clientNameList=anyType{clientNameList=anyType{clientID=1; }; clientNameList=anyType{clientID=2; }; }; message=SUCCESS; }.

    How Can I parse this string?

    UserResponse.java

    public class UserResponse implements KvmSerializable{
    
    public String message = null;
    public Client[] clientNameList = null;
    
    @Override
    public Object getProperty(int index) {
        switch (index){
        case 0:
            return message;
        case 1:
            return clientNameList;
         default:
             return null;
        }
    }
    
    @Override
    public int getPropertyCount() {
        // TODO Auto-generated method stub
        return 2;
    }
    
    @Override
    public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
        switch(index)
        {
        case 0:
            info.type = PropertyInfo.STRING_CLASS;
            info.name = "message";
            break;
        case 1:
            info.type = PropertyInfo.OBJECT_TYPE;
            info.name = "clientNameList";
            break;
        default:
            break;
        }
    
    }
    
    @Override
    public void setProperty(int index, Object value) {
        switch(index)
        {
        case 0:
            message = value.toString();
            break;
        case 1:
            clientNameList = (Client[]) value;
            break;
        default:
            break;
        }
    
    }   
    }
    

    Client.java contains only clientId of Integer type.

    Updated code and wsdl

    ImageProcessImpl.java

    public UserResponse sample(UserRequest userRequest) {
         return ImageProcessDAO.sample(userRequest);
    }
    

    ImageProcessDAO.java

    public static String sample(UserRequest userRequest) {
        System.out.println(userRequest.getClientName());
        UserResponse userResponse = new UserResponse();
        userResponse.setMessage(SUCCESS);
        Client[] clients = new Client[2];
        Client client = null;
        for(int i=0;i<2;i++)
        {
            client = new Client();
            client.setClientID(i+1);
            clients[i] = client;
        }
        userResponse.setClientNameList(clients);
        return userResponse;
    }
    

    I am calling these webservices from Android as,

    try{
            String NAMESPACE = "http://impl.test.com";
            String URL = "http://10.0.2.2:8080/Webservice/services/ImageProcessImpl?wsdl";  
            String SOAP_ACTION = "http://impl.test.com/sample";
            String METHOD_NAME = "sample";
    
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME); 
    
            UserRequest userRequest = new UserRequest();            
            userRequest.setClientName("Test");
    
            PropertyInfo pi = new PropertyInfo();
            pi.setName("userRequest");
            pi.setValue(userRequest);
            pi.setType(UserRequest.class);
            request.addProperty(pi);
    
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); 
            envelope.setOutputSoapObject(request);  
            envelope.implicitTypes = true;
            envelope.addMapping(NAMESPACE, "userRequest", UserRequest.class);
            envelope.addMapping(NAMESPACE, "UserResponse", UserResponse.class);
    
            AndroidHttpTransport httpTransport = new AndroidHttpTransport(URL);  
            httpTransport.debug = true;
            httpTransport.call(SOAP_ACTION, envelope);
    
           SoapObject result = (SoapObject) envelope.getResponse();
           userResponse.message = result.getProperty(0).toString();
           Log.e(Test.LOG_TAG, userResponse.message);
            }catch (Exception e) {
                Log.e(Test.LOG_TAG, "throws an exception: " + e.getMessage());
            }
    

    my new wsdl file is,

    <?xml version="1.0" encoding="UTF-8"?>
    <wsdl:definitions targetNamespace="http://impl.test.com" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://impl.test.com" xmlns:intf="http://impl.test.com" xmlns:tns1="http://common.test.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <!--WSDL created by Apache Axis version: 1.4
    Built on Apr 22, 2006 (06:55:48 PDT)-->
     <wsdl:types>
      <schema elementFormDefault="qualified" targetNamespace="http://impl.test.com" xmlns="http://www.w3.org/2001/XMLSchema">
       <import namespace="http://common.test.com"/>
       <element name="sample">
        <complexType>
         <sequence>
          <element name="userRequest" type="tns1:UserRequest"/>
         </sequence>
        </complexType>
       </element>
       <element name="sampleResponse">
        <complexType>
         <sequence>
          <element name="sampleReturn" type="tns1:UserResponse"/>
         </sequence>
        </complexType>
       </element>
       <complexType name="ArrayOf_tns1_Client">
        <sequence>
         <element maxOccurs="unbounded" minOccurs="0" name="item" type="tns1:Client"/>
        </sequence>
       </complexType>
      </schema>
      <schema elementFormDefault="qualified" targetNamespace="http://common.test.com" xmlns="http://www.w3.org/2001/XMLSchema">
       <import namespace="http://impl.test.com"/>
       <complexType name="UserRequest">
        <sequence>
         <element name="clientName" nillable="true" type="xsd:string"/>
        </sequence>
       </complexType>
       <complexType name="Client">
        <sequence>
         <element name="clientID" type="xsd:int"/>
        </sequence>
       </complexType>
       <complexType name="UserResponse">
        <sequence>
         <element name="clientNameList" nillable="true" type="impl:ArrayOf_tns1_Client"/>
         <element name="message" nillable="true" type="xsd:string"/>
        </sequence>
       </complexType>
      </schema>
     </wsdl:types>
    
       <wsdl:message name="sampleRequest">
    
          <wsdl:part element="impl:sample" name="parameters">
    
          </wsdl:part>
    
       </wsdl:message>
    
       <wsdl:message name="sampleResponse">
    
          <wsdl:part element="impl:sampleResponse" name="parameters">
    
          </wsdl:part>
    
       </wsdl:message>
    
       <wsdl:portType name="ImageProcessImpl">
    
          <wsdl:operation name="sample">
    
             <wsdl:input message="impl:sampleRequest" name="sampleRequest">
    
           </wsdl:input>
    
             <wsdl:output message="impl:sampleResponse" name="sampleResponse">
    
           </wsdl:output>
    
          </wsdl:operation>
    
       </wsdl:portType>
    
       <wsdl:binding name="ImageProcessImplSoapBinding" type="impl:ImageProcessImpl">
    
          <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    
          <wsdl:operation name="sample">
    
             <wsdlsoap:operation soapAction=""/>
    
             <wsdl:input name="sampleRequest">
    
                <wsdlsoap:body use="literal"/>
    
             </wsdl:input>
    
             <wsdl:output name="sampleResponse">
    
                <wsdlsoap:body use="literal"/>
    
             </wsdl:output>
    
          </wsdl:operation>
    
       </wsdl:binding>
    
       <wsdl:service name="ImageProcessImplService">
    
          <wsdl:port binding="impl:ImageProcessImplSoapBinding" name="ImageProcessImpl">
    
             <wsdlsoap:address location="http://localhost:8080/Webservice/services/ImageProcessImpl"/>
    
          </wsdl:port>
    
       </wsdl:service>
    
    </wsdl:definitions>
    
    • Jaiprakash Soni
      Jaiprakash Soni over 11 years
      can you give response format return from server
    • Manoj
      Manoj over 11 years
      I have added response format(wsdl) in my question.
    • Jaiprakash Soni
      Jaiprakash Soni over 11 years
      You must check this answer from Theo stackoverflow.com/questions/11907434/…
    • Manoj
      Manoj over 11 years
      I have checked stackoverflow.com/questions/11907434/ksoap2-java-lang-runtim‌​eexception-cannot-se‌​rialize. But I got the response from webservice while sending "request.addProperty("variable","value");". When I pass a bean object((i.e) userRequest) as variable I can't invoke the service.
  • Manoj
    Manoj over 11 years
    Thanks. I will use KvmSerializable and let you know about the result.
  • Manoj
    Manoj over 11 years
    It is working. The webservice invoked and getting response. But I can't parse the response string.
  • Jason
    Jason over 11 years
    UserResponse also needs to implement KvmSerializable to be able to "automatically" cast the response to that type. If this is already done and you're getting an error please provide additional details.
  • Manoj
    Manoj over 11 years
    UserResponse also implements KvmSerializable. Still I am getting the issue. I added some additional details in the question. Please check it.
  • Jason
    Jason over 11 years
    According to your wsdl, this is correct - the UserResponse object has a single element, a string named message.
  • Manoj
    Manoj over 11 years
    Sorry. I have added one variable in my UserResponse. Now I update my wsdl and code in the question. Now I am getting response as a string " anyType{clientNameList=anyType{clientNameList=anyType{client‌​ID=1; }; clientNameList=anyType{clientID=2; }; }; message=SUCCESS; } ". How can I parse it?
  • Manoj
    Manoj over 11 years
    I used your code. Now I am getting the xml response. Thanks for the help.
  • Manoj
    Manoj over 11 years
    In my question , "UserResponse.java" I declared "public Client[] clientNameList = null;" and the "getPropertyInfo" method contains "info.type = PropertyInfo.OBJECT_TYPE;" Is is correct? what "info.type" I need to give for the clientNameList ?
  • Lalit Poptani
    Lalit Poptani over 11 years
    Now, forget about SOAP parsing(UserResponse.java) simple xml parsing will do. Also you can check my blog post
  • Jason
    Jason over 11 years
    You would need to also implement KvmSerializable in your Client class and add a mapping for it in your SoapSerializationEnvelope. To answer your question from the other comment, (if you continue using ksoap), clientNameList would have a type of Vector<Client>.
  • Manoj
    Manoj over 11 years
    thanks. But Client class already implements KvmSerializable. But still I didn't get parsable response. So I used "String response = androidHttpTransport.responseDump;" And I am getting xml response.
  • Manoj
    Manoj over 11 years
    I have added the question about parsing xml into pojo in the the following link "stackoverflow.com/questions/12095437/…". please tell me how can I fix it.
  • Manoj
    Manoj over 11 years
    Hai I am getting error while using the kvm serialization. the error posted in "stackoverflow.com/questions/12153053/…". please help me to fix this?
  • Manoj
    Manoj over 11 years
    I am getting error using kvm serialization. I posted the issue in "stackoverflow.com/questions/12153053/…". Please help me to fix this?
  • param
    param over 9 years
    awesome i was not able to get the response in xml format.. now my problem is solved. good job dude.. thanx :)