如何使用 Spring-ws 客户端从具有无效内容类型的 Web 服务读取响应?
How to read response from web-service with Invalid Content-Type using Spring-ws client?
同学,我调用webservice收到异常:
org.springframework.ws.soap.SoapMessageCreationException: Could not
create message from InputStream: Invalid Content-Type:text/html. Is
this an error message instead of a SOAP response?; nested exception is
com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Invalid
Content-Type:text/html. Is this an error message instead of a SOAP
response?
我读了this and this。
Wireshark 显示我收到响应:
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
Server: Jetty(8.1.13.v20130916)
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://mayacomp/Generic/Ws">
<soapenv:Body>
<ws:response>
<out>
<requestID>6b140165-af79-47a2-9e9f-5b7bba265050</requestID>
<requestTimestamp>2015-12-01T13:04:44.044</requestTimestamp>
</out>
</ws:response>
</soapenv:Body>
</soapenv:Envelope>
我的豆子看起来像:
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.mayacomp.entities");
HashMap<String,Object> properties = new HashMap<String,Object>();
properties.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setMarshallerProperties(properties);
return marshaller;
}
@Bean
public myClient myClient(Jaxb2Marshaller marshaller) {
myClient client = new myClient();
client.setDefaultUri("URL");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
//client.setMessageSender(messageSender);
return client;
}
Class 调用 WS 看起来像:
public class myClient extends WebServiceGatewaySupport {
public Response createApplication(In in) {
Request request = (Request) new Request();
request.setIn(in);
Response response = (Response) getWebServiceTemplate().marshalSendAndReceive(
"URL",
request,
new WebServiceMessageCallback()
{ public void doWithMessage(WebServiceMessage message) {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage)message;
SOAPMessage soapMessage = SOAP.createSOAPMessage(in);
saajSoapMessage.setSaajMessage(soapMessage);
}
}
);
return null;
}
你能帮我阅读网络服务响应吗?
更新
--- maven-dependency-plugin:2.8:tree (default-cli) @ adapter ---
com.comp:adapter:jar:0.0.1-SNAPSHOT
+- junit:junit:jar:4.12:compile
| \- org.hamcrest:hamcrest-core:jar:1.3:compile
+- org.springframework:spring-context:jar:4.2.3.RELEASE:compile
| +- org.springframework:spring-aop:jar:4.2.3.RELEASE:compile
| | \- aopalliance:aopalliance:jar:1.0:compile
| +- org.springframework:spring-beans:jar:4.2.3.RELEASE:compile
| \- org.springframework:spring-expression:jar:4.2.3.RELEASE:compile
+- org.springframework:spring-core:jar:4.2.3.RELEASE:compile
| \- commons-logging:commons-logging:jar:1.2:compile
+- io.codearte.jfairy:jfairy:jar:0.5.1:compile
| +- com.google.guava:guava:jar:19.0-rc2:compile (version selected from constraint [15.0,))
| +- org.yaml:snakeyaml:jar:1.16:compile (version selected from constraint [1.9,2.0))
| +- org.iban4j:iban4j:jar:2.1.1:compile
| +- com.google.inject:guice:jar:4.0:compile
| | \- javax.inject:javax.inject:jar:1:compile
| +- joda-time:joda-time:jar:2.3:compile
| +- com.google.inject.extensions:guice-assistedinject:jar:4.0:compile
| +- org.reflections:reflections:jar:0.9.9:compile
| | +- org.javassist:javassist:jar:3.18.2-GA:compile
| | \- com.google.code.findbugs:annotations:jar:2.0.1:compile
| +- org.apache.commons:commons-lang3:jar:3.3.2:compile
| \- org.slf4j:slf4j-api:jar:1.7.7:compile
+- org.fluttercode.datafactory:datafactory:jar:0.8:compile
+- org.springframework.ws:spring-ws-core:jar:2.2.3.RELEASE:compile
| +- org.springframework.ws:spring-xml:jar:2.2.3.RELEASE:compile
| +- org.springframework:spring-oxm:jar:4.0.9.RELEASE:compile
| +- org.springframework:spring-web:jar:4.0.9.RELEASE:compile
| \- org.springframework:spring-webmvc:jar:4.0.9.RELEASE:compile
+- log4j:log4j:jar:1.2.17:compile
\- org.apache.httpcomponents:httpclient:jar:4.5.1:compile
+- org.apache.httpcomponents:httpcore:jar:4.4.3:compile
\- commons-codec:commons-codec:jar:1.9:compile
查看堆栈跟踪中抛出 org.springframework.ws.soap.SoapMessageCreationException 的位置。根据错误发生的位置,您可以配置 org.springframework.ws.client.core.WebServiceTemplate 以接受 Content-Type:text/html.
我觉得实现的那个方面是不可插入的,您将无法替换它。参见 SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?。基本异常发生在某些 jdk 代码中。
如果是我,我很想使用常规的 http 客户端,进行 http 调用,然后手动解析响应。这里有一些使用 apache 客户端执行此操作的完整示例:
我们的一项供应商服务 returns Content-Type 我遇到了同样的问题,因为 text/html 和 spring Web 服务模板不喜欢这样。
由于没有简单的方法来更改 spring web-service 中的响应 headers。我通过使用自定义 Http 客户端解决了它,然后提供了删除 "Content-Type" headers.
的客户端拦截器
HttpClient httpClient = HttpClients.custom()
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
.addInterceptorFirst(new HttpResponseInterceptor() {
@Override
public void process(HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
boolean htmlResponse = Arrays.stream(httpResponse.getAllHeaders()).anyMatch(header -> header.getName().equalsIgnoreCase("Content-Type") && header.getValue().contains("text/html"));
if (htmlResponse) {
httpResponse.removeHeaders("Content-Type");
}
}
})
.setDefaultRequestConfig(requestConfig)
.build();
我只是删除并没有添加 "Content-Type" header,因为 SOAP 1.1 和 1.2 的 SOAPMessageFactory 在处理消息之前添加了适当的 header。
我遇到了和你一样的内容类型问题:text/html
所以我所有的注意力都集中在尝试将 CT 更改为 text/xml 但这没有用。问题是你的“MyClient”你需要有一个正确的“MessageSender”和我在我的 pom 中添加的依赖项。
@Bean
public HttpComponentsMessageSender defaultMessageSender() {
HttpComponentsMessageSender messageSender = createMessageSenderBasicAuth();
HttpClientBuilder httpClientBuilder = HttpClients.custom()
.useSystemProperties()
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
.setDefaultCredentialsProvider(basicAuthCredentials())
.setDefaultRequestConfig(requestConfigWithDefaultTimeout());
messageSender.setHttpClient(httpClientBuilder.build());
return messageSender;
}
private HttpComponentsMessageSender createMessageSenderBasicAuth() {
return new HttpComponentsMessageSender() {
@Override
protected HttpContext createContext(URI uri) {
HttpHost target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
AuthCache authCache = new BasicAuthCache();
BasicScheme basicAuth = new BasicScheme();
authCache.put(target, basicAuth);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
return localContext;
}
};
}
private RequestConfig requestConfigWithDefaultTimeout() {
return RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(10000) // 10 sec
.setSocketTimeout(10000)
.build();
}
在我添加的pom文件中
pom.xml
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
您的“我的客户”应该如下所示
@Bean
public myClient myClient(@Qualifier("marshaller") Jaxb2Marshaller marshaller) {
myClient client = new myClient();
client.setDefaultUri("URL");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
client.setMessageSender(defaultMessageSender());
return client;
}
打电话给
是个好主意
WebServiceTemplate webServiceTemplate = getWebServiceTemplate();
webServiceTemplate.afterPropertiesSet();
在你的“public class myClient extends WebServiceGatewaySupport” class
同学,我调用webservice收到异常:
org.springframework.ws.soap.SoapMessageCreationException: Could not create message from InputStream: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?; nested exception is com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?
我读了this and this。
Wireshark 显示我收到响应:
HTTP/1.1 200 OK
Content-Type: text/html
Transfer-Encoding: chunked
Server: Jetty(8.1.13.v20130916)
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://mayacomp/Generic/Ws">
<soapenv:Body>
<ws:response>
<out>
<requestID>6b140165-af79-47a2-9e9f-5b7bba265050</requestID>
<requestTimestamp>2015-12-01T13:04:44.044</requestTimestamp>
</out>
</ws:response>
</soapenv:Body>
</soapenv:Envelope>
我的豆子看起来像:
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.mayacomp.entities");
HashMap<String,Object> properties = new HashMap<String,Object>();
properties.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setMarshallerProperties(properties);
return marshaller;
}
@Bean
public myClient myClient(Jaxb2Marshaller marshaller) {
myClient client = new myClient();
client.setDefaultUri("URL");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
//client.setMessageSender(messageSender);
return client;
}
Class 调用 WS 看起来像:
public class myClient extends WebServiceGatewaySupport {
public Response createApplication(In in) {
Request request = (Request) new Request();
request.setIn(in);
Response response = (Response) getWebServiceTemplate().marshalSendAndReceive(
"URL",
request,
new WebServiceMessageCallback()
{ public void doWithMessage(WebServiceMessage message) {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage)message;
SOAPMessage soapMessage = SOAP.createSOAPMessage(in);
saajSoapMessage.setSaajMessage(soapMessage);
}
}
);
return null;
}
你能帮我阅读网络服务响应吗?
更新
--- maven-dependency-plugin:2.8:tree (default-cli) @ adapter ---
com.comp:adapter:jar:0.0.1-SNAPSHOT
+- junit:junit:jar:4.12:compile
| \- org.hamcrest:hamcrest-core:jar:1.3:compile
+- org.springframework:spring-context:jar:4.2.3.RELEASE:compile
| +- org.springframework:spring-aop:jar:4.2.3.RELEASE:compile
| | \- aopalliance:aopalliance:jar:1.0:compile
| +- org.springframework:spring-beans:jar:4.2.3.RELEASE:compile
| \- org.springframework:spring-expression:jar:4.2.3.RELEASE:compile
+- org.springframework:spring-core:jar:4.2.3.RELEASE:compile
| \- commons-logging:commons-logging:jar:1.2:compile
+- io.codearte.jfairy:jfairy:jar:0.5.1:compile
| +- com.google.guava:guava:jar:19.0-rc2:compile (version selected from constraint [15.0,))
| +- org.yaml:snakeyaml:jar:1.16:compile (version selected from constraint [1.9,2.0))
| +- org.iban4j:iban4j:jar:2.1.1:compile
| +- com.google.inject:guice:jar:4.0:compile
| | \- javax.inject:javax.inject:jar:1:compile
| +- joda-time:joda-time:jar:2.3:compile
| +- com.google.inject.extensions:guice-assistedinject:jar:4.0:compile
| +- org.reflections:reflections:jar:0.9.9:compile
| | +- org.javassist:javassist:jar:3.18.2-GA:compile
| | \- com.google.code.findbugs:annotations:jar:2.0.1:compile
| +- org.apache.commons:commons-lang3:jar:3.3.2:compile
| \- org.slf4j:slf4j-api:jar:1.7.7:compile
+- org.fluttercode.datafactory:datafactory:jar:0.8:compile
+- org.springframework.ws:spring-ws-core:jar:2.2.3.RELEASE:compile
| +- org.springframework.ws:spring-xml:jar:2.2.3.RELEASE:compile
| +- org.springframework:spring-oxm:jar:4.0.9.RELEASE:compile
| +- org.springframework:spring-web:jar:4.0.9.RELEASE:compile
| \- org.springframework:spring-webmvc:jar:4.0.9.RELEASE:compile
+- log4j:log4j:jar:1.2.17:compile
\- org.apache.httpcomponents:httpclient:jar:4.5.1:compile
+- org.apache.httpcomponents:httpcore:jar:4.4.3:compile
\- commons-codec:commons-codec:jar:1.9:compile
查看堆栈跟踪中抛出 org.springframework.ws.soap.SoapMessageCreationException 的位置。根据错误发生的位置,您可以配置 org.springframework.ws.client.core.WebServiceTemplate 以接受 Content-Type:text/html.
我觉得实现的那个方面是不可插入的,您将无法替换它。参见 SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?。基本异常发生在某些 jdk 代码中。
如果是我,我很想使用常规的 http 客户端,进行 http 调用,然后手动解析响应。这里有一些使用 apache 客户端执行此操作的完整示例:
我们的一项供应商服务 returns Content-Type 我遇到了同样的问题,因为 text/html 和 spring Web 服务模板不喜欢这样。 由于没有简单的方法来更改 spring web-service 中的响应 headers。我通过使用自定义 Http 客户端解决了它,然后提供了删除 "Content-Type" headers.
的客户端拦截器HttpClient httpClient = HttpClients.custom()
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
.addInterceptorFirst(new HttpResponseInterceptor() {
@Override
public void process(HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
boolean htmlResponse = Arrays.stream(httpResponse.getAllHeaders()).anyMatch(header -> header.getName().equalsIgnoreCase("Content-Type") && header.getValue().contains("text/html"));
if (htmlResponse) {
httpResponse.removeHeaders("Content-Type");
}
}
})
.setDefaultRequestConfig(requestConfig)
.build();
我只是删除并没有添加 "Content-Type" header,因为 SOAP 1.1 和 1.2 的 SOAPMessageFactory 在处理消息之前添加了适当的 header。
我遇到了和你一样的内容类型问题:text/html 所以我所有的注意力都集中在尝试将 CT 更改为 text/xml 但这没有用。问题是你的“MyClient”你需要有一个正确的“MessageSender”和我在我的 pom 中添加的依赖项。
@Bean
public HttpComponentsMessageSender defaultMessageSender() {
HttpComponentsMessageSender messageSender = createMessageSenderBasicAuth();
HttpClientBuilder httpClientBuilder = HttpClients.custom()
.useSystemProperties()
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
.setDefaultCredentialsProvider(basicAuthCredentials())
.setDefaultRequestConfig(requestConfigWithDefaultTimeout());
messageSender.setHttpClient(httpClientBuilder.build());
return messageSender;
}
private HttpComponentsMessageSender createMessageSenderBasicAuth() {
return new HttpComponentsMessageSender() {
@Override
protected HttpContext createContext(URI uri) {
HttpHost target = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
AuthCache authCache = new BasicAuthCache();
BasicScheme basicAuth = new BasicScheme();
authCache.put(target, basicAuth);
HttpClientContext localContext = HttpClientContext.create();
localContext.setAuthCache(authCache);
return localContext;
}
};
}
private RequestConfig requestConfigWithDefaultTimeout() {
return RequestConfig.custom()
.setConnectionRequestTimeout(10000)
.setConnectTimeout(10000) // 10 sec
.setSocketTimeout(10000)
.build();
}
在我添加的pom文件中
pom.xml
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.2</version>
</dependency>
您的“我的客户”应该如下所示
@Bean
public myClient myClient(@Qualifier("marshaller") Jaxb2Marshaller marshaller) {
myClient client = new myClient();
client.setDefaultUri("URL");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
client.setMessageSender(defaultMessageSender());
return client;
}
打电话给
是个好主意WebServiceTemplate webServiceTemplate = getWebServiceTemplate(); webServiceTemplate.afterPropertiesSet(); 在你的“public class myClient extends WebServiceGatewaySupport” class