Getting the HTTP status code from the SOAP response

The simple answer is you can't. Burrowing into the HttpSOAPConnection code, a local instance of an HttpURLConnection object is used to do the actual communication with the target service. This does get the httpResponse code but it more or less completely hides it from the caller. All you conclude is that if you don't get an exception but the returned SOAPMessage contains a SOAPFault, then the return code was HttpURLConnection.HTTP_INTERNAL_ERROR (i.e. 500). No exception and no SOAPFault means the return code was 200 to 206, all of which are "SUCCESS" - unfortunately the status entry from the HTTP headers in the HttpURLConnection object is explicitly not copied to the MIMEHeaders in the returned SOAPMessage ...

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

Anything else will raise an exception and the code will start after the open bracket in the message field of the exception and is probably three digits, it's hard to be precise because someone forgot the close bracket or any other separator before the message...

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

For example:

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

It's horrible relying on the formatting of a text message in an exception, but the response code isn't exposed anywhere else.


Another alternative (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;

You can get access to the HTTP headers through the MessageContext interface.

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

The most straight forward way is probably to implement a SOAPHandler which will give you access to the MessageContext:

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

However, SOAP applications are generally not supposed to build the interaction on the HTTP status codes as those are transport specific.


Taken from W3C note on SOAP (Section 6.2)

SOAP HTTP follows the semantics of the HTTP Status codes for communicating status information in HTTP. For example, a 2xx status code indicates that the client's request including the SOAP component was successfully received, understood, and accepted etc.

In case of a SOAP error while processing the request, the SOAP HTTP server MUST issue an HTTP 500 "Internal Server Error" response and include a SOAP message in the response containing a SOAP Fault element (see section 4.4) indicating the SOAP processing error.

And from documentation on SOAPFault in the API

An element in the SOAPBody object that contains error and/or status information. This information may relate to errors in the SOAPMessage object or to problems that are not related to the content in the message itself.

So, a possible answer could be

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

Some references which helped me create this answer are:

  • http://forums.devshed.com/java-help-9/java-httpstatus-code-59166.html
  • Apache Axis2 SAAP SoapConnectionImpl

Tags:

Java

Http

Soap