Search code examples
javaandroidweb-serviceswsdlksoap2

Ksoap2 Nullpointer Exception


I have a web-service, which runs on Tomcat 7.0.54 (on my local machine). It has two methods, sayHelloFrom(String from), which should return greeting string with a given user name. And saveFile() method, which generates a file on my local machine when called. Also I have "standard" java test client for this service. Also, I use this one remote web-service for tests. Now I'm trying to make KSOAP2 android client to my web-service. So. When I call my webservice, using "standard" java client - everything works fine. When I call remote web-service with KSOAP2 android client there is no problems too. But, when I call my webservice with an android KSOAP2 client I get a NullPointerException on envelope.getResponse() action, and at the same time, webservice, itself, is called, file is generated and there is no errors in stacktrace of the webservice:

Here is error stacktrace:

05-26 17:19:33.900  30066-30340/my.test.ru.app E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #2
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:278)
            at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)
     Caused by: java.lang.NullPointerException
            at activity.my.test.ru.WebService$myAsyncTask.doInBackground(WebService.java:84)
            at activity.my.test.ru.WebService$myAsyncTask.doInBackground(WebService.java:38)
            at android.os.AsyncTask$2.call(AsyncTask.java:264)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)

Here is my android activity for calling a webservice:

public class WebService extends Activity {
    private final String NAMESPACE = "http://example";
    private final String URL = "http://192.168.1.88:8080/services/HelloWorld?wsdl";
    private final String SOAP_ACTION = "http://example/saveFile";
    private final String METHOD_NAME = "saveFile";
    Button b;
    private TextView tv;
    private String response;

    private class myAsyncTask extends AsyncTask<Void, Void, Void> {


        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            tv.setText(response);
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... arg0) {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            //request.addProperty("from", "Naseko");
            //request.addProperty("iTopN", "5");
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.setOutputSoapObject(request);

            HttpTransportSE httpTransport = new HttpTransportSE(URL);

            httpTransport.debug = true;
            try {
                httpTransport.call(SOAP_ACTION, envelope);
            } catch (HttpResponseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (XmlPullParserException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } //send request
            SoapObject result = null;
            try {
                result = (SoapObject) envelope.getResponse();
                Log.d("App", "" + result);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Log.d("App", "" + result.getProperty(1).toString());
            response = result.getProperty(1).toString();
            return null;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_web_service);
        //Fahrenheit Text control
        tv = (TextView) findViewById(R.id.tv_result);
        //Button to trigger web service invocation
        b = (Button) findViewById(R.id.button1);
        //Button Click Listener
        b.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                myAsyncTask myRequest = new myAsyncTask();
                myRequest.execute();
            }
        });
    }
}

And permition from manifest:

   <uses-permission android:name="android.permission.GET_ACCOUNTS"/> 
   <uses-permission android:name="android.permission.READ_PROFILE"/> 
   <uses-permission android:name="android.permission.READ_CONTACTS"/> 
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
   <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

Here is my WSDL:

<wsdl:definitions xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://example" xmlns:intf="http://example" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example">
<!--
WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)
-->
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://example">
<element name="saveFileReturn" type="xsd:string"/>
<element name="from" type="xsd:string"/>
<element name="sayHelloWorldFromReturn" type="xsd:string"/>
</schema>
</wsdl:types>
<wsdl:message name="saveFileRequest"></wsdl:message>
<wsdl:message name="saveFileResponse">
<wsdl:part element="impl:saveFileReturn" name="saveFileReturn"/>
</wsdl:message>
<wsdl:message name="sayHelloWorldFromResponse">
<wsdl:part element="impl:sayHelloWorldFromReturn" name="sayHelloWorldFromReturn"/>
</wsdl:message>
<wsdl:message name="sayHelloWorldFromRequest">
<wsdl:part element="impl:from" name="from"/>
</wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="saveFile">
<wsdl:input message="impl:saveFileRequest" name="saveFileRequest"/>
<wsdl:output message="impl:saveFileResponse" name="saveFileResponse"/>
</wsdl:operation>
<wsdl:operation name="sayHelloWorldFrom" parameterOrder="from">
<wsdl:input message="impl:sayHelloWorldFromRequest" name="sayHelloWorldFromRequest"/>
<wsdl:output message="impl:sayHelloWorldFromResponse" name="sayHelloWorldFromResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldSoapBinding" type="impl:HelloWorld">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="saveFile">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="saveFileRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="saveFileResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="sayHelloWorldFrom">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="sayHelloWorldFromRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHelloWorldFromResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldService">
<wsdl:port binding="impl:HelloWorldSoapBinding" name="HelloWorld">
<wsdlsoap:address location="http://192.168.1.88:8080/services/HelloWorld"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

That is my web-service code:

@WebService
public class HelloWorld {
    @WebMethod
    public String sayHelloWorldFrom(String from) {
        String result = "Hello, world, from " + from;
        System.out.println(result);
        return result;
    }

    @WebMethod
    public String saveFile() {
        try {
            String content = "This is the content to write into file";
            File file = new File("C:\\test\\filename.txt");
            // if file doesnt exists, then create it
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();
            System.out.println("Done!!!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "OK";
    }
}

Solution

  • Got it!

    First, I put everything inside doInBackground into try block. Then i got new ecxeption, and it was classCastException. So, lines of code for getting the result I changed to this:

                SoapPrimitive result =(SoapPrimitive)envelope.bodyIn;
                Log.d("App", "" + result.toString());
                response = result.toString();
    

    And the hole doInBackground method now looks like this:

        @Override
        protected Void doInBackground(Void... arg0) {
            try {
                SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                envelope.setOutputSoapObject(request);
                HttpTransportSE httpTransport = new HttpTransportSE(URL);
                //httpTransport.debug = true;
                httpTransport.call(SOAP_ACTION, envelope);
                SoapPrimitive result =(SoapPrimitive)envelope.bodyIn;
                Log.d("App", "" + result.toString());
                response = result.toString();
            } catch (IOException | XmlPullParserException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }  //send request
            return null;
        }
    }