2016-09-28 127 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; 
    } 
} 
}