2016-09-28 126 views
0

我在调用web服务时遇到问题,Spring WS正在返回一个WebServiceTransportException:Internal Server Error,而不是预期的SoapFaultException。当我在SOAPUI中触发这个调用时,我得到了肥皂故障。Spring WS:为什么Spring WS返回WebServiceTransportException而不是SoapFaultException

WebServiceTransportException也压倒了响应的输出,所以我没有在日志中看到问题是什么。

我在配置类的spring引导应用程序中使用Spring WS。

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); 
    } 
} 

当请求正确时,一切正常。但是当请求包含错误时,我不会将其作为肥皂错误的原因。只有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) 
+0

WebServiceTransportExceptin在连接到服务器时出现问题时引发。那么,你在这里期待的错误是什么?你怎么知道这个异常吞噬了soap fault异常?我认为spring会进行区分并抛出IO异常,而不是将所有内容都包含在soap错误中。 – Veeram

+0

当我用正确的参数调用服务时,它返回一个有效的响应。但是当我发送带有错误参数的请求(这会导致soapfault)时(例如,在soapui中执行相同的请求时),我只会得到WebServiceTransportException。这不能成为连接问题,因为我使用正确的参数得到了有效的结果。 (使用参数我的意思是输入的网络服务) – Marc

+0

你可以添加一个示例,它在哪里工作,它在哪里不会?我只是想看看是什么触发了内部服务器错误。您还可以检查返回的xml响应,看它是否在春季有负载,否则,Spring会将其作为传输错误包装。 – Veeram

回答

0

设置

webServiceTemplate.setCheckConnectionForFault(true); 

的伎俩,而不是像在上面的配置类将其设置为false。

感谢雷迪提供了正确的方向。我也错过了实现handleFault方法,所以我看不到日志中的响应。对于所有想要查看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; 
    } 
} 
}