Ksoap2 空指针异常
Ksoap2 Nullpointer Exception
我有一个 Web 服务,它在 Tomcat 7.0.54(在我的本地机器上)上运行。它有两个方法,sayHelloFrom(String from),它应该 return 带有给定用户名的问候字符串。和 saveFile() 方法,它在调用时在我的本地机器上生成一个文件。
我还有 "standard" java 测试客户端用于此服务。
此外,我使用 this 一个远程网络服务进行测试。
现在我正在尝试使 KSOAP2 android 客户端成为我的网络服务。
所以。当我调用我的网络服务时,使用 "standard" java 客户端 - 一切正常。
当我使用 KSOAP2 android 客户端调用远程网络服务时,也没有问题。
但是,当我用 android KSOAP2 客户端调用我的网络服务时,我在 envelope.getResponse() 操作上得到 NullPointerException,同时,网络服务本身,被调用,文件被生成并且在 web 服务的堆栈跟踪中没有错误:
这是错误堆栈跟踪:
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.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.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.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.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)
这是我的 android activity 调用网络服务:
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();
}
});
}
}
以及来自清单的许可:
<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"/>
这是我的 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>
这是我的网络服务代码:
@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";
}
}
知道了!
首先,我将 doInBackground 中的所有内容都放入 try 块中。
然后我得到了新的 ecxeption,它是 classCastException。
因此,获取结果的代码行我更改为:
SoapPrimitive result =(SoapPrimitive)envelope.bodyIn;
Log.d("App", "" + result.toString());
response = result.toString();
洞 doInBackground 方法现在看起来像这样:
@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;
}
}
我有一个 Web 服务,它在 Tomcat 7.0.54(在我的本地机器上)上运行。它有两个方法,sayHelloFrom(String from),它应该 return 带有给定用户名的问候字符串。和 saveFile() 方法,它在调用时在我的本地机器上生成一个文件。 我还有 "standard" java 测试客户端用于此服务。 此外,我使用 this 一个远程网络服务进行测试。 现在我正在尝试使 KSOAP2 android 客户端成为我的网络服务。 所以。当我调用我的网络服务时,使用 "standard" java 客户端 - 一切正常。 当我使用 KSOAP2 android 客户端调用远程网络服务时,也没有问题。 但是,当我用 android KSOAP2 客户端调用我的网络服务时,我在 envelope.getResponse() 操作上得到 NullPointerException,同时,网络服务本身,被调用,文件被生成并且在 web 服务的堆栈跟踪中没有错误:
这是错误堆栈跟踪:
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.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.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.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.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)
这是我的 android activity 调用网络服务:
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();
}
});
}
}
以及来自清单的许可:
<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"/>
这是我的 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>
这是我的网络服务代码:
@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";
}
}
知道了!
首先,我将 doInBackground 中的所有内容都放入 try 块中。 然后我得到了新的 ecxeption,它是 classCastException。 因此,获取结果的代码行我更改为:
SoapPrimitive result =(SoapPrimitive)envelope.bodyIn;
Log.d("App", "" + result.toString());
response = result.toString();
洞 doInBackground 方法现在看起来像这样:
@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;
}
}