ksoap - 请求响应对象映射

时间:2015-03-27 14:38:03

标签: android web-services wsdl android-ksoap2

当我尝试调用托管的wsdl描述的Web服务时,我收到以下错误。

"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)

其实我在JAVA程序中测试ksoap库而不是android。 一旦此测试通过,我计划将代码迁移到Android。 但是由于在非编组期间发生了错误,我假设正在进行服务调用,并且解析响应时存在问题。

以下是我正在测试的Java程序:

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;
        }

    }

}

以下是剥离的WSDL。我保留了与服务操作相关的部分 - getAvailableServices - 我在下面的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>

请帮助我找出错误。

GetAvailableServicesResponse类与通过wsimport生成的类相似。但是我希望这在Android中工作,所以我在类路径中避免除了ksoap-with-dependencies jar之外的所有外部库。因此响应对象包含一个String列表。

我在代码中也添加了名称空间映射。 我尝试了名称空间xmlns:tns和xmlns:imp2。在解析响应时仍然得到相同的Un-marhsall错误。有没有办法获取ksoap库试图解析的响应XML?

1 个答案:

答案 0 :(得分:1)

您需要映射新的KVSerializabel类,请使用:

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