本文使用JAX-WS2.2编译webservice,并使用HttpUrlConnection的POST方式对wsdl发送soap报文进行请求返回数据,
对错误Server returned HTTP response code: 500 的解决方法进行简单分析。
问题描述:
由于课程需要博主需要自己写一个webservice并且通过soap进行请求,
于是使用JAX-WS编译了下面java代码生成webservice服务
生成webservice的java代码:
[java] view plain copy
查看webservice
1. @WebService()
2. public class HelloWorld {
3. @WebMethod
4. public String sayHelloWorldFrom(String from) {
5. "getMessage.");
6. "Hello, world, from " + from;
7. System.out.println(result);
8. return result;
9. }
10. public static void main(String[] argv) {
11. "Service is running...");
12.
13. new HelloWorld ();
14. "http://localhost:9000/HelloWorld";
15. Endpoint.publish(address, implementor);
16. }
17. }
在网上查到的一个方法就是通过HttpUrlConnection进行请求,这边贴一下代码,应该很多人都有查到类似的方法
HttpUrlConnection请求实现代码:
[java] view plain copy
soap.xml代码如下:
1. public static void main(String[] args) throws Exception
2. {
3. "http://localhost:9000/HelloWorld?wsdl";//自定义的wsdl服务
4. new URL(urlString);
5. //打开连接
6.
7. "soap_xml\\soap.xml";//要发送的soap格式文件
8. new File(xmlFile);
9. byte[] buf = new byte[(int) fileToSend.length()];// 用于存放文件数据的数组
10.
11. new FileInputStream(xmlFile).read(buf);
12.
13. //Content-Length长度会自动进行计算
14. "Content-Type", "text/xml; charset=utf-8");
15. "POST");
16. true);
17. true);
18.
19. OutputStream out = httpConn.getOutputStream();
20.
21. out.write(buf);
22. out.close();
23.
24. new InputStreamReader(httpConn.getInputStream());
25. new BufferedReader(is);
26. String inputLine;
27. new BufferedWriter(new OutputStreamWriter(
28. new FileOutputStream("result.xml")));// 将结果存放的位置
29. while ((inputLine = in.readLine()) != null)
30. {
31. System.out.println(inputLine);
32. bw.write(inputLine);
33. bw.newLine();
34. }
35. bw.close();
36. in.close();
37. httpConn.disconnect();
38. }
[html] view plain copy
1. <?xml version="1.0" encoding="utf-8"?>
2. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
3. <soap:Body>
4. <sayHelloWorldFrom>
5. <arg0>
6. 撑撑
7. </arg0>
8. </sayHelloWorldFrom>
9. </soap:Body>
10. </soap:Envelope>
这段代码是网上找的,并没有错误,但是一运行就懵逼了,报了下面的错误
明明直接在浏览器查看wsdl接口是可以访问页面,但是返回500错误
错误代码:
[java] view plain copy
错误语句指向
1. Exception in thread "main" java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:9000/HelloWorld?wsdl
2. 1839)
3. 1440)
4. 38)
5. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
6. 62)
7. 43)
8. 497)
9. 147)
[java] view plain copy
- InputStreamReader is = new InputStreamReader(httpConn.getInputStream());
而网上其他大部分文章都没有给解决方法,或者给了其他的解决方法,我就在这边分享一下这个问题的详细解决方法。
解决流程(干货
首先应该确认具体的错误,通过下面的语句可以了解InputStream的错误详情。
[java] view plain copy
- InputStream is = httpConn.getErrorStream(); //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
这个语句其实也是从请求的服务方取回的错误信息,实质也是xml内容,用上面的BufferReader那一连串的语句解析出具体内容,然后输出查看,具体代码如下:
[java] view plain copy
错误详情输出如下:
1. InputStream is = httpConn.getErrorStream(); //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
2. InputStreamReader isr = new InputStreamReader(is,"utf-8");
3. BufferedReader in = new BufferedReader(isr);
4. String inputLine;
5. BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
6. new FileOutputStream("result.xml")));// 将结果存放的位置
7. while ((inputLine = in.readLine()) != null)
8. {
9. System.out.println(inputLine);
10. bw.write(inputLine);
11. bw.newLine();
12. bw.close();
13. }
14. in.close();
[html] view plain copy
在这边就要注意了!这个xml文件是第一个要点!
1. <?xml version='1.0' encoding='UTF-8'?>
2. <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
3. <S:Body>
4. <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
5. <faultcode>
6. S:Client
7. </faultcode>
8. <faultstring>
9. 找不到{}sayHelloWorldFrom的分派方法
10. </faultstring>
11. </S:Fault>
12. </S:Body>
13. </S:Envelope>
分析一下这段xml代码,可以看到有一个faultcode和faultstring,这就是解决这个问题的第一个突破口
灵光一闪百度了一下SOAP Fault(百科连接:http://baike.baidu.com/link?url=vehb23KNtl58uv2cwVDk8LYzDTUC4MHW9kmpaALl9qht9VXp8ASufe0QlpUrEELEApdKx80AMPzMsfCbUJtWiK)
这样就一目了然了,错误代码中faultcode所含的是Client,说明传递的消息有误,服务端是没有问题的。
于是从要发送的soap中查找错误。
这时候发现faultstring “{}找不到xxx的分派方法” 中有一个大括号,想不明白那个是什么,刚好查看了一下web服务的页面,就是最上面那张图片,发现服务名和端口名那边也有大括号{http://example/},然后也想起来之前看的其他xml代码中,要发送的方法的那个节点中有写命名空间(xmlns),就是网上那个getWeatherByCityName的那个例子,大家应该都有看过,我就不再这边费口舌了。
要是有仔细看我发送的soap.xml的代码,就可以看到sayHelloWorldFrom那个节点没有写命名空间,实在是查了这么多代码网上都没人提到,也没有查到关于soap报文的编写规范,还以为那边可以不用写,于是删掉了。
问题就出在这,我重新试了一下,先把命名空间随便写了个网址,再次运行后依然报错,但是大括号中就有了命名空间指向的网址了,于是把web服务里的大括号里的地址,即{http://example/}写上去,总算是请求成功并成功返回数据!
修改后的soap.xml(就是添加了命名空间)
[html] view plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body>
- <m:sayHelloWorldFrom xmlns:m="http://example/">
- <arg0>
- 撑撑
- </arg0>
- </m:sayHelloWorldFrom>
- </soap:Body>
- </soap:Envelope>
大括号里的地址其实就是wsdl中denfinition里定义的targetNameSpace,具体解释我贴个链接吧大家自己看吧,反正知道问题出在这边总算是解决了。
其实出了bug第一反应确实应该是找Error信息,这样才好针对性的进行处理,如果本文的方法还没办法帮你解决的话,那还是建议大家靠前面查看错误详情的方法去进行bug的查找~
主要内容到这边结束啦,希望能帮到大家~
附录
发送httpUrlConnection的java代码
[java] view plain copy
1. package soap;
2.
3. import java.io.*;
4. import java.net.HttpURLConnection;
5. import java.net.URL;
6.
7. /**
8. * Created by cc on 2016/10/21.
9. */
10. public class HelloSoap {
11.
12. public static void main(String[] args) throws Exception
13. {
14. "http://localhost:9000/HelloWorld?wsdl";//wsdl文档的地址
15. new URL(urlString);
16. //打开连接
17.
18. //String soapActionString = "http://localhost:9000/HelloWorld/sayHelloWorldFrom";//Soap 1.1中使用
19.
20. "soap_xml\\soap.xml";//要发送的soap格式文件
21. new File(xmlFile);
22. byte[] buf = new byte[(int) fileToSend.length()];// 用于存放文件数据的数组
23.
24. new FileInputStream(xmlFile).read(buf);
25.
26. //Content-Length长度会自动进行计算
27. "Content-Type", "text/xml; charset=utf-8");
28. //httpConn.setRequestProperty("soapActionString",soapActionString);//Soap1.1使用 其实完全可以不需要
29. "POST");
30. true);
31. true);
32.
33. OutputStream out = httpConn.getOutputStream();
34.
35. out.write(buf);
36. out.close();
37.
38. if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
39. {
40. new InputStreamReader(httpConn.getInputStream());
41. new BufferedReader(is);
42. String inputLine;
43. new BufferedWriter(new OutputStreamWriter(
44. new FileOutputStream("result.xml")));// 将结果存放的位置
45. while ((inputLine = in.readLine()) != null)
46. {
47. System.out.println(inputLine);
48. bw.write(inputLine);
49. bw.newLine();
50. }
51. bw.close();
52. in.close();
53. }
54. else{
55. //如果服务器返回的HTTP状态不是HTTP_OK,则表示发生了错误,此时可以通过如下方法了解错误原因。
56. //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
57. new InputStreamReader(is,"utf-8");
58. new BufferedReader(isr);
59. String inputLine;
60. new BufferedWriter(new OutputStreamWriter(
61. new FileOutputStream("result.xml")));// 将结果存放的位置
62. while ((inputLine = in.readLine()) != null)
63. {
64. System.out.println(inputLine);
65. bw.write(inputLine);
66. bw.newLine();
67. bw.close();
68. }
69. in.close();
70.
71. }
72. httpConn.disconnect();
73. }
74. }