java使用POST发送soap报文请求webservice返回500错误解析

文章摘要:

本文使用JAX-WS2.2编译webservice,并使用HttpUrlConnection的POST方式对wsdl发送soap报文进行请求返回数据,

对错误Server returned HTTP response code: 500 的解决方法进行简单分析。


问题描述:

由于课程需要博主需要自己写一个webservice并且通过soap进行请求,

于是使用JAX-WS编译了下面java代码生成webservice服务


生成webservice的java代码:

@WebService()
public class HelloWorld {
  @WebMethod
  public String sayHelloWorldFrom(String from) {
      System.out.println("getMessage.");
      String result = "Hello, world, from " + from;
      System.out.println(result);
      return result;
  }
  public static void main(String[] argv) {
    System.out.println("Service is running...");

    Object implementor = new HelloWorld ();
    String address = "http://localhost:9000/HelloWorld";
    Endpoint.publish(address, implementor);
  }
}
查看webservice



在网上查到的一个方法就是通过HttpUrlConnection进行请求,这边贴一下代码,应该很多人都有查到类似的方法

HttpUrlConnection请求实现代码:

public static void main(String[] args) throws Exception
    {
        String urlString = "http://localhost:9000/HelloWorld?wsdl";//自定义的wsdl服务
        URL url = new URL(urlString);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();//打开连接

        String xmlFile = "soap_xml\\soap.xml";//要发送的soap格式文件
        File fileToSend = new File(xmlFile);
        byte[] buf = new byte[(int) fileToSend.length()];// 用于存放文件数据的数组

        new FileInputStream(xmlFile).read(buf);

        //Content-Length长度会自动进行计算
        httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
        httpConn.setRequestMethod("POST");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        OutputStream out = httpConn.getOutputStream();

        out.write(buf);
        out.close();

        InputStreamReader is = new InputStreamReader(httpConn.getInputStream());
        BufferedReader in = new BufferedReader(is);
        String inputLine;
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream("result.xml")));// 将结果存放的位置
        while ((inputLine = in.readLine()) != null)
        {
            System.out.println(inputLine);
            bw.write(inputLine);
            bw.newLine();
        }
        bw.close();
        in.close();
        httpConn.disconnect();
    }

soap.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <sayHelloWorldFrom>
            <arg0>
                撑撑
            </arg0>
        </sayHelloWorldFrom>
    </soap:Body>
</soap:Envelope>

这段代码是网上找的,并没有错误,但是一运行就懵逼了,报了下面的错误

明明直接在浏览器查看wsdl接口是可以访问页面,但是返回500错误

错误代码:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:9000/HelloWorld?wsdl
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1839)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
	at soap.HelloSoap.main(HelloSoap.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

错误语句指向

        InputStreamReader is = new InputStreamReader(httpConn.getInputStream());


而网上其他大部分文章都没有给解决方法,或者给了其他的解决方法,我就在这边分享一下这个问题的详细解决方法。


解决流程(干货

首先应该确认具体的错误,通过下面的语句可以了解InputStream的错误详情。

            InputStream is = httpConn.getErrorStream();    //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。


这个语句其实也是从请求的服务方取回的错误信息,实质也是xml内容,用上面的BufferReader那一连串的语句解析出具体内容,然后输出查看,具体代码如下:  

            InputStream is = httpConn.getErrorStream();    //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
            InputStreamReader isr = new InputStreamReader(is,"utf-8");
            BufferedReader in = new BufferedReader(isr);
            String inputLine;
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream("result.xml")));// 将结果存放的位置
            while ((inputLine = in.readLine()) != null) 
            {
                System.out.println(inputLine);
                bw.write(inputLine);
                bw.newLine();
                bw.close();
            }
            in.close();
错误详情输出如下:

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
            <faultcode>
                S:Client
            </faultcode>
            <faultstring>
                找不到{}sayHelloWorldFrom的分派方法
            </faultstring>
        </S:Fault>
    </S:Body>
</S:Envelope>

在这边就要 注意了!这个xml文件是第一个要点!

分析一下这段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(就是添加了命名空间)

<?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,具体解释我贴个链接吧大家自己看吧,反正知道问题出在这边总算是解决了。

WebService 之 WSDL文件 讲解 http://blog.itpub.net/20200170/viewspace-740276/


其实出了bug第一反应确实应该是找Error信息,这样才好针对性的进行处理,如果本文的方法还没办法帮你解决的话,那还是建议大家靠前面查看错误详情的方法去进行bug的查找~

主要内容到这边结束啦,希望能帮到大家~


附录

发送httpUrlConnection的java代码
package soap;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by cc on 2016/10/21.
 */
public class HelloSoap {

    public static void main(String[] args) throws Exception
    {
        String urlString = "http://localhost:9000/HelloWorld?wsdl";//wsdl文档的地址
        URL url = new URL(urlString);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();//打开连接

        //String soapActionString = "http://localhost:9000/HelloWorld/sayHelloWorldFrom";//Soap 1.1中使用

        String xmlFile = "soap_xml\\soap.xml";//要发送的soap格式文件
        File fileToSend = new File(xmlFile);
        byte[] buf = new byte[(int) fileToSend.length()];// 用于存放文件数据的数组

        new FileInputStream(xmlFile).read(buf);

        //Content-Length长度会自动进行计算
        httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
        //httpConn.setRequestProperty("soapActionString",soapActionString);//Soap1.1使用 其实完全可以不需要
        httpConn.setRequestMethod("POST");
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        OutputStream out = httpConn.getOutputStream();

        out.write(buf);
        out.close();

        if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK)
        {
            InputStreamReader is = new InputStreamReader(httpConn.getInputStream());
            BufferedReader in = new BufferedReader(is);
            String inputLine;
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream("result.xml")));// 将结果存放的位置
            while ((inputLine = in.readLine()) != null)
            {
                System.out.println(inputLine);
                bw.write(inputLine);
                bw.newLine();
            }
            bw.close();
            in.close();
        }
        else{
            //如果服务器返回的HTTP状态不是HTTP_OK,则表示发生了错误,此时可以通过如下方法了解错误原因。
            InputStream is = httpConn.getErrorStream();    //通过getErrorStream了解错误的详情,因为错误详情也以XML格式返回,因此也可以用JDOM来获取。
            InputStreamReader isr = new InputStreamReader(is,"utf-8");
            BufferedReader in = new BufferedReader(isr);
            String inputLine;
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                    new FileOutputStream("result.xml")));// 将结果存放的位置
            while ((inputLine = in.readLine()) != null)
            {
                System.out.println(inputLine);
                bw.write(inputLine);
                bw.newLine();
                bw.close();
            }
            in.close();

        }
        httpConn.disconnect();
    }
}


  • 13
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值