Mohamed Iqzas
Mohamed Iqzas

Reputation: 1046

ksoap - request response object mapping

I am getting the following error when I try to call a web service described by a hosted wsdl.

"Unable to un-marshall between the XML Document and JAXB Objects."
'org.xml.sax.SAXException: Unable to un-marshall between the XML Document and JAXB Objects.  See server logs for more details.
null' faultactor: 'null' detail: org.kxml2.kdom.Node@6782a9
    at org.ksoap2.serialization.SoapSerializationEnvelope.parseBody(SoapSerializationEnvelope.java:137)
    at org.ksoap2.SoapEnvelope.parse(SoapEnvelope.java:140)
    at org.ksoap2.transport.Transport.parseResponse(Transport.java:129)
    at org.ksoap2.transport.HttpTransportSE.parseResponse(HttpTransportSE.java:301)
    at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:274)

Actually I am testing the ksoap library in a JAVA program and not android. Once this test passes I am planning to migrate the code to Android. But since the error is occurring during un-marshalling, I assume the service call is happening and there is an issue with parsing the response.

Below is my Java program I am testing with:

package com.tc.wsdl.runner;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.KvmSerializable;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpResponseException;
import org.ksoap2.transport.HttpTransportSE;
import org.xmlpull.v1.XmlPullParserException;

import com.tc.ws.client.session.InternalServerException;
import com.tc.ws.client.session.InternalServerFaultFault;
import com.tc.ws.client.session.InvalidUserFaultFault;



public class TestRunner {

    /**
     * @param args
     */
    public static void main(String[] args) 
    {
        // TODO Auto-generated method stub
        try
        {
            ksoapGetAvailableServices();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }

    private static void ksoapGetAvailableServices()
            throws HttpResponseException, IOException, XmlPullParserException {

        String NAMESPACE = "http://somename.com/Services/Core/2006-03";
        String METHOD_NAME = "getAvailableServices";
        String URL="http://some.com:8080/tc/services/Core-2006-03-Session?wsdl";
        String SOAP_ACTION_PREFIX="/";


        GetAvailableServicesInput input = new GetAvailableServicesInput();
        PropertyInfo propInfo = new PropertyInfo();
        propInfo.name = "getAvailableServicesRequest";
        propInfo.setValue(input);
        propInfo.type = GetAvailableServicesInput.class;
        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
        request.addProperty(propInfo);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                SoapEnvelope.VER11);
        envelope.implicitTypes = true;

        envelope.setOutputSoapObject(request);


        envelope.addMapping("http://somename.com/Schemas/Core/2006-03/Session", "GetAvailableServicesInput",new GetAvailableServicesInput ().getClass());
        envelope.addMapping("http://somename.com/Schemas/Core/2006-03/Session", "GetAvailableServicesResponse",new GetAvailableServicesResponse ().getClass());
        envelope.addMapping("http://somename.com/Schemas/Soa/2006-03/Exceptions", "InvalidUserFault",new InvalidUserFaultFault ().getClass());
        envelope.addMapping("http://somename.com/Schemas/Soa/2006-03/Exceptions", "InternalServerFault",new InternalServerFaultFault ().getClass());


        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
        androidHttpTransport.debug = true;

        androidHttpTransport.call(NAMESPACE + SOAP_ACTION_PREFIX + METHOD_NAME,
                envelope);

        GetAvailableServicesResponse resultsRequestSOAP = (GetAvailableServicesResponse) envelope
                .getResponse();

        System.out.println("********" + resultsRequestSOAP);

    }

    static class GetAvailableServicesInput implements KvmSerializable
    {

        @Override
        public String getInnerText() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Object getProperty(int arg0) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public int getPropertyCount() {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public void getPropertyInfo(int arg0, Hashtable arg1, PropertyInfo arg2) {
            // TODO Auto-generated method stub

        }

        @Override
        public void setInnerText(String arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void setProperty(int arg0, Object arg1) {
            // TODO Auto-generated method stub

        }

    }


    static class GetAvailableServicesResponse implements KvmSerializable
    {

        protected ArrayList<String> serviceNames;

        @Override
        public String getInnerText() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Object getProperty(int index) {
            // TODO Auto-generated method stub
            switch (index){
            case 0:
                return serviceNames;

             default:
                 return null;
            }
        }

        @Override
        public int getPropertyCount() {
            // TODO Auto-generated method stub
            return 1;
        }

        @Override
        public void getPropertyInfo(int index, Hashtable arg1, PropertyInfo info) {
            // TODO Auto-generated method stub
            switch (index)
            {
            case 0:
                info.type = PropertyInfo.VECTOR_CLASS;
                info.name = "serviceNames";
                break;
            default:
                break;
            }
        }

        @Override
        public void setInnerText(String arg0) {
            // TODO Auto-generated method stub

        }

        @Override
        public void setProperty(int index, Object arg1) {
            // TODO Auto-generated method stub
            switch (index){
            case 0:
                serviceNames = (ArrayList<String>) arg1;
                break;

             default:
                 break;
            }

        }

        public  ArrayList<String> getServiceNames() {
            if (serviceNames == null) {
                serviceNames = new ArrayList<String>();
            }
            return this.serviceNames;
        }

        public void setServiceNames(ArrayList<String> serviceNames) {
            this.serviceNames = serviceNames;
        }

    }

}

Below is the stripped out WSDL. I have kept the parts related to the service operation - getAvailableServices - I am calling in the below wsdl:

<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:imp0="http://somename.com/Schemas/Soa/2006-03/Base" 

xmlns:imp1="http://somename.com/Schemas/Soa/2006-03/Exceptions" xmlns:imp2="http://somename.com/Schemas/Core/2006-03/Session" 

xmlns:imp3="http://somename.com/webservices/2005-06/schemas/WSFaults" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 

xmlns:tns="http://somename.com/Services/Core/2006-03" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsi="http://ws-

i.org/schemas/conformanceClaim/" xmlns:xs="http://www.w3.org/2001/XMLSchema" 

targetNamespace="http://somename.com/Services/Core/2006-03">

<wsdl:types>
<xs:schema>
<xs:import namespace="http://somename.com/Schemas/Soa/2006-03/Base" schemaLocation="../schemas/SoaBase.xsd"/>
<xs:import namespace="http://somename.com/Schemas/Soa/2006-03/Exceptions" schemaLocation="../schemas/SoaExceptions.xsd"/>
<xs:import namespace="http://somename.com/Schemas/Core/2006-03/Session" schemaLocation="../schemas/Core0603Session.xsd"/>
<xs:import namespace="http://somename.com/webservices/2005-06/schemas/WSFaults" schemaLocation="../schemas/WSFaults.xsd"/>
</xs:schema>
</wsdl:types>

<wsdl:message name="InternalServerFaultFault">
<wsdl:part element="imp1:InternalServerFault" name="exx01"/>
</wsdl:message>
<wsdl:message name="InvalidCredentialsFaultFault">
<wsdl:part element="imp1:InvalidCredentialsFault" name="exx02"/>
</wsdl:message>

<wsdl:message name="ServiceFaultFault">
<wsdl:part element="imp1:ServiceFault" name="exx01"/>
</wsdl:message>
<wsdl:message name="InvalidUserFaultFault">
<wsdl:part element="imp1:InvalidUserFault" name="exx02"/>
</wsdl:message>

<wsdl:message name="getAvailableServicesRequest">
<wsdl:part element="imp2:GetAvailableServicesInput" name="in0"/>
</wsdl:message>

<wsdl:message name="getAvailableServicesResponse">
<wsdl:part element="imp2:GetAvailableServicesResponse" name="out"/>
</wsdl:message>

<wsdl:portType name="Core0603Session">

<wsdl:operation name="getAvailableServices">

<wsdl:documentation>
<![CDATA[
This will return a list of services that this server instance supports.
]]>
</wsdl:documentation>

<wsdl:input message="tns:getAvailableServicesRequest" name="getAvailableServicesRequest"/>

<wsdl:output message="tns:getAvailableServicesResponse" name="getAvailableServicesResponse"/>

<wsdl:fault message="tns:InternalServerFaultFault" name="InternalServerFaultError"/>

<wsdl:fault message="tns:InvalidUserFaultFault" name="InvalidUserFaultError"/>

</wsdl:operation>

</wsdl:portType>

<wsdl:binding name="Core0603SessionSoapBinding" type="tns:Core0603Session">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

<wsdl:operation name="getAvailableServices">

<soap:operation soapAction="getAvailableServices" style="document"/>

<wsdl:input>

<soap:body use="literal"/>

</wsdl:input>

<wsdl:output>

<soap:body use="literal"/>

</wsdl:output>

<wsdl:fault name="InternalServerFaultError">
<soap:fault name="InternalServerFaultError" use="literal"/>
</wsdl:fault>

<wsdl:fault name="InvalidUserFaultError">
<soap:fault name="InvalidUserFaultError" use="literal"/>
</wsdl:fault>

</wsdl:operation>

</wsdl:binding>

<wsdl:service name="Core0603SessionService">

<wsdl:port binding="tns:Core0603SessionSoapBinding" name="Core-2006-03-Session">

<soap:address location="http://somewhere.com:8080/app/services/Core-2006-03-Session"/>

</wsdl:port>

</wsdl:service>

</wsdl:definitions>

Kindly help in identifying the mistake I have made.

The GetAvailableServicesResponse class is similar to the one generated through wsimport. But I want this to work in Android so I am avoiding all external libraries except ksoap-with-dependencies jar in classpath. So the response object contains a list of String.

I have added the namespace mapping also as updated in the code. I tried both the namespaces xmlns:tns and xmlns:imp2. Still getting the same Un-marhsall error while parsing the response. Is there a way to get the response XML that the ksoap library is trying to parse?

Upvotes: 0

Views: 1004

Answers (1)

Jose Sanchez
Jose Sanchez

Reputation: 11

You need map your new KVSerializabel class, use this:

envelope.setOutputSoapObject(request);
envelope.addMapping(NAMESPACE, "YourObjectOnWebServices",new GetAvailableServicesInput ().getClass());    
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

Upvotes: 1

Related Questions