Spring WS: Why is Spring WS returning WebServiceTransportException instead of a SoapFaultException

10,487

Setting

webServiceTemplate.setCheckConnectionForFault(true);

did the trick, instead of setting it to false like in the config class above.

Thanks Reddy for the hint in the right direction. I also missed to implement the handleFault method, so I couldn't see the response in the log. For all who want to see an example for an LoggingInterceptor:

public class SoapLoggingInterceptor implements ClientInterceptor {

private static Logger log = LoggerFactory.getLogger(SoapLoggingInterceptor.class);

@Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
    ByteArrayTransportOutputStream os = new ByteArrayTransportOutputStream();
    try {
        messageContext.getRequest().writeTo(os);
    } catch (IOException e) {
        throw new WebServiceIOException(e.getMessage(), e);
    }
    String request = new String(os.toByteArray()).replaceAll("\n", "");
    log.info("Soap request\n----------------------------\n" + request + "\n----------------------------\n");
    return true;
}

@Override
public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {
    logMessageContext(messageContext);
    return true;
}

@Override
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
    logMessageContext(messageContext);
    return true;
}

private void logMessageContext(MessageContext messageContext) {
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    try {
        messageContext.getResponse().writeTo(os);
    } catch (IOException e) {
        throw new WebServiceIOException(e.getMessage(), e);
    }
    String response = new String(os.toByteArray());
    log.info("Soap response\n----------------------------\n" + response + "\n----------------------------\n");
}

@Override
public void afterCompletion(MessageContext messageContext, Exception e) throws WebServiceClientException {

}

class ByteArrayTransportOutputStream extends TransportOutputStream {

    private ByteArrayOutputStream outputStream;

    @Override
    public void addHeader(String name, String value) throws IOException {
        createOutputStream();
        String header = name + ": " + value + "\n";
        outputStream.write(header.getBytes());
    }

    public byte[] toByteArray() {
        return outputStream.toByteArray();
    }

    @Override
    protected OutputStream createOutputStream() throws IOException {
        if (outputStream == null) {
            outputStream = new ByteArrayOutputStream();
        }
        return outputStream;
    }
}
}
Share:
10,487
Marc
Author by

Marc

Updated on July 16, 2022

Comments

  • Marc
    Marc almost 2 years

    I have the problem when calling my webservice, that Spring WS is returning just a WebServiceTransportException: Internal Server Error instead of the expected SoapFaultException. When I trigger the call in SOAPUI I get the soap fault.

    The WebServiceTransportException surpresses also the output of the response, so I don't see in the logs what the problem was.

    I use Spring WS in a spring boot application with Configuration classes.

    public class SoapClientConfig {
    
    private static Logger log = LoggerFactory.getLogger(SoapClientConfig.class);
    
    private static final int DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS = 60000;
    private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60000;
    private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2;
    
    public static final int CONNECTION_REQUEST_TIMEOUT = 30000;
    
    @Value("${soap.client.proxy.host}")
    protected String proxyHost;
    @Value("${soap.client.proxy.port}")
    protected String proxyPort;
    @Value("${soap.client.max.connections}")
    private int maxConnections;
    
    public Jaxb2Marshaller createMarshaller(String packageName) throws Exception {
        Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
        jaxb2Marshaller.setContextPath(packageName);
        jaxb2Marshaller.afterPropertiesSet();
        return jaxb2Marshaller;
    }
    
    public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, ClientInterceptor securityInterceptor, WebServiceMessageSender messageSender) {
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setMarshaller(marshaller);
        webServiceTemplate.setUnmarshaller(marshaller);
        webServiceTemplate.setMessageSender(messageSender);
        if(securityInterceptor != null) {
            webServiceTemplate.setInterceptors((ClientInterceptor[]) Arrays.asList(securityInterceptor, createLoggingInterceptor()).toArray());
        } else {
            webServiceTemplate.setInterceptors((ClientInterceptor[]) Arrays.asList(createLoggingInterceptor()).toArray());
        }
        webServiceTemplate.setCheckConnectionForFault(false);
        webServiceTemplate.afterPropertiesSet();
        return webServiceTemplate;
    }
    
    private ClientInterceptor createLoggingInterceptor() {
        return new SoapLoggingInterceptor();
    }
    
    public Wss4jSecurityInterceptor createSecurityInterceptor(String username, String password) throws Exception {
        Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();
        wss4jSecurityInterceptor.setSecurementUsername(username);
        wss4jSecurityInterceptor.setSecurementPassword(password);
        wss4jSecurityInterceptor.setSecurementActions("UsernameToken");
        wss4jSecurityInterceptor.setSecurementPasswordType("PasswordText");
        wss4jSecurityInterceptor.afterPropertiesSet();
        return wss4jSecurityInterceptor;
    }
    
    public HttpComponentsMessageSender createMessageSender() {
        return new HttpComponentsMessageSender(createHttpClient());
    }
    
    private HttpClient createHttpClient() {
        RequestConfig.Builder configBuilder = RequestConfig.custom()
                .setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT_MILLISECONDS)
                .setSocketTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS)
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT);
        addProxySettings(configBuilder);
    
        HttpClientBuilder clientBuilder = HttpClients.custom().setDefaultRequestConfig(configBuilder.build());
        addInterceptor(clientBuilder);
        addConnectionManager(clientBuilder);
    
        return clientBuilder.build();
    }
    
    private void addProxySettings(RequestConfig.Builder configBuilder) {
        if (StringUtils.isNotBlank(proxyHost)) {
            configBuilder.setProxy(new HttpHost(proxyHost, Integer.valueOf(proxyPort)));
        }
    }
    
    private void addInterceptor(HttpClientBuilder clientBuilder) {
        clientBuilder.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor());
    }
    
    private void addConnectionManager(HttpClientBuilder clientBuilder) {
        if (maxConnections > DEFAULT_MAX_CONNECTIONS_PER_ROUTE) {
            PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
            cm.setMaxTotal(maxConnections);
            cm.setDefaultMaxPerRoute(maxConnections);
            clientBuilder.setConnectionManager(cm);
        }
    }
    

    When the request is correct everything works fine. But when the request contains errors I don't get the reason as the soap fault. Only the WebServiceTransportException.

    Caused by: org.springframework.ws.client.WebServiceTransportException: Internal Server Error [500]
        at org.springframework.ws.client.core.WebServiceTemplate.handleError(WebServiceTemplate.java:699)
        at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:609)
        at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
        at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
        at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:378)