Spring WS: Why is Spring WS returning WebServiceTransportException instead of a SoapFaultException
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;
}
}
}
Marc
Updated on July 16, 2022Comments
-
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)