Decoding 202 Accepted response with Spring SOAP

Viewed 576

I'm trying to write a Spring-WS client for a preexisting service. The endpoint offers two very similar actions, they both consume my data and respond with a simple object status; I need to use both. The difference is, one of them responds with HTTP status code 200 and the other with 202. In the first case the status object is decoded correctly and returned from WebServiceTemplate.marshallSendAndReceive(), but in the second case it's not decoded at all, and the method returns null.

According to the HTTP spec, the HTTP status 202 is Accepted, and its purpose is to indicate that the request has been received but not yet acted upon. However, the response may still contain useful information, like current request status or a completion estimate. I want to get this response.

I tried to debug the exact process and noticed my program executing the following code in the org.springframework.ws.transport.http.AbstractHttpSenderConnection.hasResponse() method:

    protected final boolean hasResponse() throws IOException {
        int responseCode = getResponseCode();
        if (HttpTransportConstants.STATUS_ACCEPTED == responseCode ||
                HttpTransportConstants.STATUS_NO_CONTENT == responseCode) {
            return false;
        }
        ...
}

This code fragment seems responsible for never getting the status object from the 202 Accepted response. (Or a 204 No Content response, but that's obviously acceptable.)

Is there a way around this? It doesn't seem possible to override this method in a bean, it's marked final.

The closest thing to an answer I could find was the following SWS JIRA ticket. It's marked "Resolved" since August 2012, but it's really not, as the comment from 2015 says.

1 Answers

my workaround: Implement a custom HttpResponseInterceptor to handle a HTTP202:

public class MyInterceptor implements HttpResponseInterceptor {

    @Override
    public void process(HttpResponse httpResponse, HttpContext arg1) throws HttpException, IOException {
        if (202 == httpResponse.getStatusLine().getStatusCode()) { 
            httpResponse.setStatusLine(new BasicStatusLine(httpResponse.getStatusLine().getProtocolVersion(),200,httpResponse.getStatusLine().getReasonPhrase()));
        }
    }

}

Now, add the interceptor to my http client builder when creating the webServiceTemplate

 public CloseableHttpClient httpClient() throws Exception {

     return HttpClientBuilder.create().addInterceptorLast(new MyInterceptor()).setSSLSocketFactory(sslConnectionSocketFactory()).build();
  }
Related