问题
我正在接管 Java Web 服务客户端的开发工作,为了测试改进,我必须从远程 Web 服务服务器(嵌入在运行在 tomcat 实例中的 Apache Axis2 中)请求一个方法。
首先,我使用服务器提供的 WSDL 通过 SOAP UI 请求该方法。它工作正常。
现在我尝试通过我的 Java Web 服务客户端请求该方法,但我无法连接到服务器,即使使用 SOAP UI 的测试证明一切正常。
Java Web 服务客户端依赖于 Spring-WS。
从客户端调用网络服务
// Setting the kycScoreRequest
...
// Trying to connect and to get the kycScoreResponse
KycScoreResponse kycScoreResponse = (KycScoreResponse) getWebServiceTemplate().marshalSendAndReceive(kycScoreRequest);
产生的错误
[main] DEBUG com.foo.AbstractMain - org.springframework.ws.client.WebServiceIOException: I/O error: Connection timed out: connect; nested exception is java.net.ConnectException: Connection timed out: connect
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:545)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:386)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:380)
at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:372)
at com.foo.MainKycScore.getReturn(MainKycScore.java:37)
at com.foo.MainKycScore.main(MainKycScore.java:244)
Caused by: java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:326)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:610)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:445)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
at org.springframework.ws.transport.http.HttpComponentsConnection.onSendAfterWrite(HttpComponentsConnection.java:119)
at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:47)
at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:624)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:587)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:539)
... 5 more
假设 1:我是否使用了正确的 Web 服务 URL?
我有点确定 Spring 获得了正确的 URL,因为它与我接管代码之前相同,并且 wsdl 和服务器没有任何变化(而且我们的客户从未提示过,它正在为他,但从来没有在我们的机器上工作。所以不要问我在我之前的开发人员如何测试它虽然它不工作,因为 idk):
WebServiceGatewaySupport.setDefaultUri("http://82.36.138.182:8080/axis2/services/KYCService01.KYCService01HttpSoap11Endpoint/")
我在 WSDL 中有以下内容:
<wsdl:service name="KYCService01">
<wsdl:port name="KYCService01HttpSoap11Endpoint" binding="ns:KYCService01Soap11Binding">
<soap:address location="http://82.36.138.182:8080/axis2/services/KYCService01.KYCService01HttpSoap11Endpoint/"/>
</wsdl:port>
</wsdl:service>
我也尝试将 EPR 作为 url,但它没有改变任何东西:
WebServiceGatewaySupport.setDefaultUri("http://82.36.138.182:8080/axis2/services/KYCService01")
假设 2:是我支持的代理吗?
然后,我认为错误一定是因为我落后的代理造成的。事实上,当我尝试编写一小段代码来连接到 wsdl url 时,起初我做不到,并得到了“连接超时”的提示。为了解决这个问题,我将代理设置为 java 系统属性,允许我现在从 Web 服务客户端访问 wsdl。
设置代理
System.setProperty("http.proxyHost", "<my_proxy_hostname>");
System.setProperty("http.proxyPort", "<my_proxy_port>");
连接到 WSDL URL
URL wsdlAddress = null;
HttpURLConnection connection = null;
wsdlAdress = new URL("<wsdl_url>");
connection = (HttpURLConnection) wsdlAdress.openConnection();
connection.connect(); // It works if the proxy is set as System properties
不幸的是,当我尝试使用我的代理集调用 Web 服务服务器时,我仍然遇到与上述完全相同的错误。现在我已经没主意了。 我的 Java 客户端怎么可能访问 Web 服务 WSDL 但不能访问它的方法?
(edit) 假设 3:是 http header 吗?
感谢膜拦截器,我拦截了来自 SOAP UI 和 WS 客户端的 HTTP 消息。查看标题:
SOAP 用户界面
POST http://82.36.138.182:8080/axis2/services/KYCService01.KYCService01HttpSoap11Endpoint/ HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "urn:kycScore"
Content-Length: 1301
Host: 84.37.138.182:8080
Proxy-Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
WS 客户端(目标 URL 是一个 SOAP UI 模拟服务器,因为很明显,如果我使用我真正尝试连接的 URL,则不会发送任何内容,因此也不会拦截任何内容)
POST /mock HTTP/1.1
Accept-Encoding: gzip
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml; charset=utf-8
Content-Length: 1032
Host: localhost:8088
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_101)
我对 http header 一无所知,但主要区别似乎是 SOAPAction。我将 ws 客户端消息的 SOAPAction 属性设置为与 SOAP UI 相同的值,但它没有改变任何东西。
public Object marshalWithSoapActionHeader(KycScore o) {
return getWebServiceTemplate().marshalSendAndReceive(o, new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) {
((SoapMessage) message).setSoapAction("urn:kycScore");
}
});
}
否则,我们在 User-Agent 属性中看到的 java 版本是否可能很重要? (编辑)我不这么认为,因为我尝试使用 1.6 jre,并且版本在 User-Agent 属性中确实发生了变化,但我仍然有同样的错误。
最佳答案
总结故障排除技巧,尝试在评论中总结冗长的讨论:
- 尝试检查您是否缺少任何必需的 header 。
- 尝试访问一个易于连接的健康检查或 ping 服务端点。
- 如果您不断遇到连接超时,请尝试减少连接超时。
- 如果无法连接,请检查防火墙规则。
- 使用内部开发的自定义客户端库时,请尝试向了解该库的开发人员寻求帮助。
- 使用自定义客户端库时,附加源以进行调试。
- 尝试复制类似 myKong's SOAP Web Service example 的模板如果你能逃脱惩罚。
关于java - 尝试使用 Spring-WS - "Connection timed out"访问 WS 服务器,但服务器在使用 SOAP UI 测试时响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48539678/