12

如何从结果中获取 HTTP 状态SOAPConnection.call()

4

5 回答 5

10

摘自W3C 关于 SOAP 的说明(第 6.2 节)

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

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

并来自API 中有关 SOAPFault 的文档

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

所以,一个可能的答案可能是

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

帮助我创建此答案的一些参考资料是:

于 2013-04-01T19:34:53.003 回答
5

简单的答案是你不能。深入研究HttpSOAPConnection代码,HttpURLConnection 对象的本地实例用于与目标服务进行实际通信。这确实得到了 httpResponse 代码,但它或多或少地对调用者完全隐藏了它。您得出的结论是,如果您没有收到异常但返回的 SOAPMessage 包含 SOAPFault,则返回代码为 HttpURLConnection.HTTP_INTERNAL_ERROR(即 500)。没有例外,没有 SOAPFault 意味着返回代码是 200 到 206,所有这些都是“成功” - 不幸的是,来自 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

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

于 2015-03-19T12:24:27.443 回答
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 状态代码上构建交互,因为它们是特定于传输的。

于 2013-04-01T21:02:43.503 回答
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;
于 2019-10-24T09:28:32.907 回答
0

我确实有与这个问题类似的要求,业务分析师想要记录与每个入站和出站肥皂调用相关的每个 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();
于 2015-07-14T14:13:16.550 回答