Java 使用 JAXRPC-RI Web 服务客户端时如何设置连接超时?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/808487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set a connection timeout when using JAXRPC-RI web services client?
提问by matt b
I'm working with a bit of a legacy component in which we interact with a SOAP web service (a technology which I absolutely, positively abhor) using some client code built using the JAXRPC-RI (reference implementation) library.
我正在使用一些遗留组件,在该组件中我们使用一些使用 JAXRPC-RI(参考实现)库构建的客户端代码与 SOAP Web 服务(我绝对非常厌恶的一种技术)进行交互。
I'm interested in being able to set a timeout with the stubs so that in case the web services server does not reply within X seconds, the application isn't setting there forever waiting for a response.
我对能够使用存根设置超时很感兴趣,以便万一 Web 服务服务器没有在 X 秒内回复,应用程序不会在那里设置永远等待响应。
I'm using to working with clients/stubs generated by Apache Axis, in which you can simply use org.apache.axis.client.Stub.setTimeout()
to set a timeout.
我习惯于使用由 Apache Axis 生成的客户端/存根,您可以在其中简单org.apache.axis.client.Stub.setTimeout()
地设置超时。
For the life of me I can't figure out how to set a timeout when using Stubs created with JAXRPC-RI:
在我的一生中,我无法弄清楚在使用使用 JAXRPC-RI 创建的存根时如何设置超时:
- The port class I am instantiating extends
com.sun.xml.rpc.client.StubBase
and implementsjavax.xml.rpc.Stub
andcom.sun.xml.rpc.spi.runtime.StubBase
. - The JavaDocs for none of these classes mention any sort of timeout or method to do this.
- Trying code like
stub._setProperty("axis.connection.timeout", 1000);
results in an exception at runtime:javax.xml.rpc.JAXRPCException: Stub does not recognize property: axis.connection.timeout
- 我实例的端口类扩展
com.sun.xml.rpc.client.StubBase
并实现javax.xml.rpc.Stub
和com.sun.xml.rpc.spi.runtime.StubBase
。 - 这些类的 JavaDocs 都没有提到任何类型的超时或执行此操作的方法。
stub._setProperty("axis.connection.timeout", 1000);
在运行时尝试类似的代码会导致异常:javax.xml.rpc.JAXRPCException: Stub does not recognize property: axis.connection.timeout
Does anyone have any ideas on how to set/enforce a timeout when using a JAXRPC-RI client? Is it even possible?
有没有人对使用 JAXRPC-RI 客户端时如何设置/强制超时有任何想法?甚至有可能吗?
回答by Peter Perhá?
I'm just going to try to reap the bounty, so don't shoot me if I am completely on the wrong track :) If your application is "setting there forever waiting for a response" than you could do the request in a separate thread and after spawning your requestThread
you could just say requestThread.join(max_time_to_wait);
the next call would check if the requestThread is still alive and if it this then try to kill it.
我只是想获得赏金,所以如果我完全走错了路,请不要向我开枪:) 如果您的应用程序“设置在那里永远等待响应”,那么您可以单独执行请求线程,在产生你之后,requestThread
你可以说requestThread.join(max_time_to_wait);
下一次调用将检查 requestThread 是否还活着,如果它然后尝试杀死它。
You application will move on after a time-out and it's not the most inelegant solution...
您的应用程序将在超时后继续前进,这不是最不优雅的解决方案......
回答by Arjan
You may have luck setting properties such as sun.net.client.defaultConnectTimeout
or sun.net.client.defaultReadTimeout
, though that would then introduce a system-wide timeout.
您可能幸运地设置了诸如sun.net.client.defaultConnectTimeout
或 之类的属性sun.net.client.defaultReadTimeout
,尽管这会引入系统范围的超时。
In code the properties values are set using Strings:
在代码中,属性值是使用字符串设置的:
System.setProperty("sun.net.client.defaultConnectTimeout", "1000");
System.setProperty("sun.net.client.defaultReadTimeout", "1000");
For a quick test, it might be easier to set the environment variable JAVA_OPTS
or use the command line:
为了快速测试,设置环境变量JAVA_OPTS
或使用命令行可能更容易:
java -Dsun.net.client.defaultConnectTimeout="1000" ...
回答by Yevgeniy Treyvus
I am not sure why this particular JAXRPC implementation goes out of its way to make it difficult to set the timeout. Perhaps, there's a good reason for it. Other implementations such as Axis and, I believe JAX-WS, let you simply call the setTimeout() method on the Stub. After some pains, I was able to come up with this solution. Hopefully, it will be helpful. You will need to do the following in order to set the timeout on the underlying URLConnection:
我不确定为什么这个特定的 JAXRPC 实现会导致设置超时变得困难。也许,有一个很好的理由。其他实现,例如 Axis,我相信 JAX-WS,让您只需调用 Stub 上的 setTimeout() 方法。经过一些痛苦,我能够想出这个解决方案。希望它会有所帮助。您需要执行以下操作才能在底层 URLConnection 上设置超时:
- Create a new ClientTransport class. It should extend the com.sun.xml.rpc.client.http.HttpClientTransport class. Override the createHttpConnection(String, SOAPMessageContext) method. Call super.createHttpConnection() which will return HttpURLConnection object. On the HttpURLConnection object you can call setReadTimeout() which will force client-side timeout in X number of milliseconds. Once that's done, return the modified HttpURLConnection object.
- Extend the client-side Stub class with your own. Override the _getTransport() method to return a new instance of the ClientTransport class that you created in step (1).
- Extend the client-side _Impl class with your own. Override the get...Port() method so that it uses the Stub you created in step (2) instead of the generated one.
- Modify the client code you wrote to call the Web Service so that it uses the Stub you created in step (2) and the _Impl that you created in step (3).
- 创建一个新的 ClientTransport 类。它应该扩展 com.sun.xml.rpc.client.http.HttpClientTransport 类。覆盖 createHttpConnection(String, SOAPMessageContext) 方法。调用 super.createHttpConnection() 将返回 HttpURLConnection 对象。在 HttpURLConnection 对象上,您可以调用 setReadTimeout() 这将强制客户端超时 X 毫秒。完成后,返回修改后的 HttpURLConnection 对象。
- 使用您自己的扩展客户端 Stub 类。覆盖 _getTransport() 方法以返回您在步骤 (1) 中创建的 ClientTransport 类的新实例。
- 使用您自己的扩展客户端 _Impl 类。覆盖 get...Port() 方法,以便它使用您在步骤 (2) 中创建的存根而不是生成的存根。
- 修改您编写的客户端代码以调用 Web 服务,以便它使用您在步骤 (2) 中创建的 Stub 和您在步骤 (3) 中创建的 _Impl。
Note: Make sure that whatever it is that you're calling to generate the Stubs via wscompile (Ant script?) does not overwrite the 3 Java classes you just created/modified. It probably makes sense to move them to a different package so that they don't end up being overwritten.
注意:确保您通过 wscompile(Ant 脚本?)调用生成存根的任何内容都不会覆盖您刚刚创建/修改的 3 个 Java 类。将它们移动到不同的包以便它们最终不会被覆盖可能是有意义的。
回答by Ray
Yevgeniy Treyvus answer is very good, but results in a new HTTPUrlConnection being created for every SOAP call. I found out while testing his approach, that one can set a ClientTransportFactory. I now use a CustomClientTransportFactory and set it on the Stub ( casting it to StubBase ). Then one doesn't need step 2 and 3.
Yevgeniy Treyvus 的回答非常好,但会导致为每个 SOAP 调用创建一个新的 HTTPUrlConnection。我在测试他的方法时发现,可以设置一个 ClientTransportFactory。我现在使用 CustomClientTransportFactory 并将其设置在 Stub 上(将其转换为 StubBase )。那么一个不需要步骤2和3。
In step 4 one then sets his new ClientTransportFactory like so: ((StubBase) myPort)._setTransportFactory(new CustomClientTransportFactory());
在步骤 4 中,然后像这样设置他的新 ClientTransportFactory: ((StubBase) myPort)._setTransportFactory(new CustomClientTransportFactory());
回答by Yevgeniy Treyvus
Ray,
射线,
Thanks for your input. Sounds like your approach is superior since it will avoid a couple of extraneous steps. I will have to take a look. However, unless I am missing something I do not believe an additional HttpConnection is being created as the YourClientTransport.createHttpConnection(String s, SOAPMessageContext ctx) should override the HttpClientTransport one:
感谢您的输入。听起来你的方法更胜一筹,因为它可以避免几个无关的步骤。我得看看。但是,除非我遗漏了一些东西,否则我不相信正在创建额外的 HttpConnection,因为 YourClientTransport.createHttpConnection(String s, SOAPMessageContext ctx) 应该覆盖 HttpClientTransport 一个:
public class YourClientTransport extends HttpClientTransport {
@Override
protected HttpUrlConnection createHttpConnection(String s, SOAPMessageContext ctx) throws IOException {
HttpURLConnection httpURLConnection = super.createHttpConnection(s, ctx);
httpURLConnection.setReadTimeout(1000);
httpURLConnection.setConnectTimeout(1000);
return httpURLConnection;
}
}
回答by Eric Darchis
I know that you are using Axis but I struggled to find the same answer for Weblogic and since your question title and tags are generic, here is my solution.
我知道您正在使用 Axis,但我很难为 Weblogic 找到相同的答案,并且由于您的问题标题和标签是通用的,这是我的解决方案。
In my client class that implements the generated MyObject interface, I have adapted the getServicePort() as follows (note that I also have security here).
在实现生成的 MyObject 接口的客户端类中,我对 getServicePort() 进行了如下调整(请注意,我在这里也有安全性)。
protected MyObject getServicePort() throws java.rmi.RemoteException {
if (port == null) {
synchronized(this) {
if (port == null) {
try {
final MyObject_Impl service = new MyObject_Impl(wsdlURL);
// using a local variable until the object is completelly initialized
final MyObject localPort = service.getMyObjectPort();
// if username and password are provided: building a client which will include the
// username and token
if (username != null && pwd != null) {
Stub localStub = ((Stub) localPort);
// We have UsernameToken Authentication too
localStub._setProperty(
WSSecurityContext.CREDENTIAL_PROVIDER_LIST,
Collections.singletonList(
new ClientUNTCredentialProvider(username.getBytes(), pwd.getBytes())));
if (timeout != null) {
log.debug("Setting timeout to " + timeout + " milliseconds");
localStub._setProperty("weblogic.wsee.transport.read.timeout", timeout);
localStub._setProperty("weblogic.wsee.transport.connection.timeout", timeout);
}
}
port = localPort;
} catch (ServiceException e) {
throw new RemoteException("Could not initialize client to MyObject service", e);
}
}
}
}
return port;
}
The Oracle documentation is here: http://docs.oracle.com/cd/E12840_01/wls/docs103/webserv_rpc/client.html#wp241849but it incorrectly states that the timeout is in seconds. It actually is in milliseconds !
Oracle 文档在这里:http: //docs.oracle.com/cd/E12840_01/wls/docs103/webserv_rpc/client.html#wp241849但它错误地指出超时以秒为单位。它实际上以毫秒为单位!
回答by user2718349
You should use:
你应该使用:
import javax.xml.rpc.Stub;
...
int timeout = <number of milliseconds>;
((Stub) port)._setProperty(
"axis.connection.timeout",
timeout);
回答by Marwin
Maybe a little bit late for this question but I came to this problem today. Based on a solution proposed by Yevgeniy Treyvus (thank for it!) I came up with the following:
这个问题可能有点晚了,但我今天遇到了这个问题。基于 Yevgeniy Treyvus 提出的解决方案(谢谢!)我想出了以下内容:
((com.sun.xml.rpc.client.StubBase)myRemoteStub)._setTransportFactory(new ClientTransportFactory() {
@Override
public ClientTransport create() {
return new HttpClientTransport() {
@Override
protected HttpURLConnection createHttpConnection(String endpoint, SOAPMessageContext context) throws IOException {
HttpURLConnection conn = super.createHttpConnection(endpoint, context);
conn.setConnectTimeout(2000);
conn.setReadTimeout(2000);
return conn;
}
};
}
});
It is basically the same as Yevgeniy proposed but with a little less overriding (with the help of a connection factory).
它与 Yevgeniy 提出的基本相同,但覆盖较少(在连接工厂的帮助下)。