Web Services Spring WS:为什么Spring WS返回WebServiceTransportException而不是SoapFaultException

n3h0vuf2  于 2022-11-15  发布在  Spring
关注(0)|答案(1)|浏览(170)

我在调用Web服务时遇到了问题,Spring WS只返回一个WebServiceTransportException:内部服务器错误而不是预期的SoapFaultException。当我在SOAPUI中触发调用时,我得到了SOAP错误。
WebServiceTransportException还抑制了响应的输出,因此我在日志中看不到问题是什么。
我在一个带有Configuration类的Sping Boot 应用程序中使用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);
    }
}

当请求正确时,一切正常。但是当请求包含错误时,我没有得到soap错误的原因。只有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)
gcmastyq

gcmastyq1#

设定

webServiceTemplate.setCheckConnectionForFault(true);

我做到了,而不是像上面的config类那样将其设置为false。
感谢Reddy在正确方向上的提示。我还错过了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;
    }
}
}

相关问题