从SOAP响应中获取HTTP状态代码

时间:2013-04-01 10:05:54

标签: java http soap

如何从SOAPConnection.call()

的结果中获取HTTP状态

5 个答案:

答案 0 :(得分:9)

取自W3C note on SOAP (Section 6.2)

  

SOAP HTTP遵循HTTP状态代码的语义   在HTTP中传递状态信息。例如,2xx状态   代码表示客户端的请求包括SOAP组件   成功接收,理解和接受等。

     

如果在处理请求时出现SOAP错误,则为SOAP HTTP   服务器必须发出HTTP 500“内部服务器错误”响应和   在包含SOAP Fault元素的响应中包含SOAP消息   (参见第4.4节)表明SOAP处理错误。

来自documentation on SOAPFault in the API

  

SOAPBody对象中包含错误和/或状态的元素   信息即可。此信息可能与SOAPMessage中的错误有关   对象或与内容无关的问题   消息本身。

所以,可能的答案可能是

SoapMessage soapMessage = null;
soapMessage = MySOAPConnection.call(...);
soapMessage.getSOAPPart().getEnvelope().getBody().getFault().getFaultCode();

一些帮助我创建这个答案的参考文献是:

答案 1 :(得分:4)

简单的答案是你不能。深入研究HttpSOAPConnection代码,HttpURLConnection对象的本地实例用于与目标服务进行实际通信。这确实得到了httpResponse代码,但它或多或少完全隐藏了它来自调用者。您得出的结论是,如果您没有获得异常但返回的SOAPMessage包含SOAPFault,则返回代码为HttpURLConnection.HTTP_INTERNAL_ERROR(即500)。没有例外,没有SOAPFault意味着返回代码是200到206,所有这些都是" SUCCESS" - 遗憾的是,HttpURLConnection对象中HTTP标头的状态条目显式没有复制到返回的SOAPMessage中的MIMEHeaders ......

// Header field 0 is the status line so we skip it.

其他任何内容都会引发异常,代码将在异常的消息字段中的开括号之后开始,可能是三位数,很难准确,因为有人忘了关闭括号或任何其他分隔符消息之前......

throw new SOAPExceptionImpl(
                    "Bad response: ("
                        + responseCode
                        + httpConnection.getResponseMessage());

例如:

com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Bad response: (502internal error - server connection terminated

依赖于异常中文本消息的格式化很可怕,但响应代码并未在其他任何地方公开。

答案 2 :(得分:1)

您可以通过MessageContext界面访问HTTP标头。

http://docs.oracle.com/javaee/5/api/javax/xml/ws/handler/MessageContext.html

最直接的方法可能是实现一个SOAPHandler,它可以让你访问MessageContext:

http://docs.oracle.com/cd/E15051_01/wls/docs103/webserv_adv/handlers.html#wp222394

但是,SOAP应用程序通常不应在HTTP状态代码上构建交互,因为它们是特定于传输的。

答案 3 :(得分:1)

另一种选择(java 8):

public class HttpResponseHandler implements SOAPHandler<SOAPMessageContext> {
    private Logger log = Logger.create(HttpResponseHandler.class);

    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        boolean outboundProperty = (boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); // Response
        if(!outboundProperty) {
            int status = (int)context.get(MessageContext.HTTP_RESPONSE_CODE);
            log.debug("HTTP status code = " + status);
        }
        return true;
    }
}

// Usage : building your service

List<Handler> soapHandlers = new ArrayList();
soapHandlers.add(new HttpResponseHandler());

URL wsdlDocumentLocation = this.getClass().getResource("some_url");
Service service = Service.create(wsdlDocumentLocation, new QName("namespace", "servicename"));
service.setHandlerResolver(new HandlerResolver() {
    public List<Handler> getHandlerChain(PortInfo portInfo) {
        return soapHandlers;
    }
});
BindingProvider provider = (BindingProvider)service.getPort(new QName("namespace", "portname"), serviceInterface);
provider.getRequestContext().put("javax.xml.ws.service.endpoint.address", this.endpointAddress);
provider.getRequestContext().put("com.sun.xml.ws.connect.timeout", connectTimeout);
provider.getRequestContext().put("com.sun.xml.ws.request.timeout", requestTimeout);
return provider;

答案 4 :(得分:0)

我确实有类似的要求,业务分析师希望记录与每个入站和出站soap调用相关的每个http响应代码。我的答案对Apache CXF 2.7.5有效。

您可以通过以下代码片段在javax.xml.ws.handler.soap.SoapHandler接口的实现中通过MessageContext接口访问http状态代码。

int status = (( javax.servlet.http.HttpServletResponse)messageContext.get("HTTP.RESPONSE")).getStatus();