如何从结果中获取 HTTP 状态SOAPConnection.call()
?
5 回答
SOAP HTTP 遵循 HTTP 状态代码的语义,用于在 HTTP 中传递状态信息。例如,2xx 状态码表示客户端的包含 SOAP 组件的请求被成功接收、理解和接受等。
如果在处理请求时出现 SOAP 错误,SOAP HTTP 服务器必须发出 HTTP 500“内部服务器错误”响应,并在响应中包含 SOAP 消息,其中包含指示 SOAP 处理错误的 SOAP Fault 元素(参见第 4.4 节)。
SOAPBody 对象中包含错误和/或状态信息的元素。此信息可能与 SOAPMessage 对象中的错误或与消息本身的内容无关的问题有关。
所以,一个可能的答案可能是
SoapMessage soapMessage = null;
soapMessage = MySOAPConnection.call(...);
soapMessage.getSOAPPart().getEnvelope().getBody().getFault().getFaultCode();
帮助我创建此答案的一些参考资料是:
简单的答案是你不能。深入研究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
在异常中依赖文本消息的格式是很可怕的,但是响应代码不会在其他任何地方公开。
您可以通过 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 状态代码上构建交互,因为它们是特定于传输的。
另一种选择(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;
我确实有与这个问题类似的要求,业务分析师想要记录与每个入站和出站肥皂调用相关的每个 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();