Java 如何在使用JAXRPC-RI web服务客户端时设置连接超时?

Java 如何在使用JAXRPC-RI web服务客户端时设置连接超时?,java,web-services,jakarta-ee,soap,jax-rpc,Java,Web Services,Jakarta Ee,Soap,Jax Rpc,我正在使用一个遗留组件,其中我们使用一些使用JAXRPC-RI(参考实现)库构建的客户机代码与SOAPWeb服务(我绝对非常讨厌这种技术)交互 我感兴趣的是能够设置存根的超时,以便在web服务服务器在X秒内没有响应的情况下,应用程序不会永远在那里等待响应 我习惯于使用ApacheAxis生成的客户机/存根,您只需使用org.Apache.Axis.client.Stub.setTimeout()设置超时 就我个人而言,在使用JAXRPC-RI创建的存根时,我不知道如何设置超时: 我正在实例化的

我正在使用一个遗留组件,其中我们使用一些使用JAXRPC-RI(参考实现)库构建的客户机代码与SOAPWeb服务(我绝对非常讨厌这种技术)交互

我感兴趣的是能够设置存根的超时,以便在web服务服务器在X秒内没有响应的情况下,应用程序不会永远在那里等待响应

我习惯于使用ApacheAxis生成的客户机/存根,您只需使用
org.Apache.Axis.client.Stub.setTimeout()
设置超时

就我个人而言,在使用JAXRPC-RI创建的存根时,我不知道如何设置超时:

  • 我正在实例化的端口类扩展了
    com.sun.xml.rpc.client.StubBase
    ,并实现了
    javax.xml.rpc.Stub
    com.sun.xml.rpc.spi.runtime.StubBase
  • 这些类的JavaDocs都没有提到任何类型的超时或执行此操作的方法
  • 正在尝试类似stub.\u setProperty(“axis.connection.timeout”,1000)的代码在运行时导致异常:
    javax.xml.rpc.JAXRPCException:Stub无法识别属性:axis.connection.timeout

有人知道如何在使用JAXRPC-RI客户端时设置/强制超时吗?有可能吗?

我只是想获得赏金,所以如果我完全走错了方向,不要开枪打我:)如果你的应用程序“设置在那里永远等待响应”,那么你可以在单独的线程中执行请求,在生成
requestThread
后,你可以说
requestThread.join(max_time_to_wait);
下一次调用将检查requestThread是否仍处于活动状态,如果仍然处于活动状态,则尝试将其杀死


您的应用程序将在超时后继续运行,这并不是最不雅观的解决方案…

您可能会幸运地设置属性,例如
sun.net.client.defaultConnectTimeout
sun.net.client.defaultReadTimeout
,尽管这样会引入系统范围的超时

在代码中,使用字符串设置属性值:

System.setProperty("sun.net.client.defaultConnectTimeout", "1000");
System.setProperty("sun.net.client.defaultReadTimeout", "1000");
对于快速测试,设置环境变量
JAVA\u OPTS
或使用命令行可能更容易:

java -Dsun.net.client.defaultConnectTimeout="1000" ...

我不知道为什么这个特定的JAXRPC实现会让设置超时变得非常困难。也许,这有一个很好的理由。其他实现,比如Axis,我相信JAX-WS,让您只需调用setTimeout()方法。经过一些努力,我终于想出了这个解决方案。希望它会有所帮助。您需要执行以下操作才能设置基础URLConnection上的超时:

  • 创建新的ClientTransport类。它应该扩展com.sun.xml.rpc.client.http.HttpClientTransport类。重写createHttpConnection(String,SOAPMessageContext)方法。调用super.createHttpConnection()将返回HttpURLConnection对象。在HttpURLConnection对象上,可以调用setReadTimeout()这将强制客户端超时,以X毫秒为单位。完成后,返回修改后的HttpURLConnection对象
  • 使用自己的方法扩展客户端存根类。重写_getTransport()方法以返回在步骤(1)中创建的ClientTransport类的新实例
  • 使用您自己的方法扩展客户端_Impl类。重写get…Port()方法,以便它使用您在步骤(2)中创建的存根,而不是生成的存根
  • 修改您为调用Web服务而编写的客户端代码,以便它使用您在步骤(2)中创建的存根和您在步骤(3)中创建的_Impl

  • 注意:确保通过wscompile(Ant脚本?)不会覆盖您刚刚创建/修改的3个Java类。将它们移动到另一个包中可能是有意义的,这样它们就不会被覆盖。

    Yevgeniy Treyvus回答非常好,但会为每个SOAP调用创建一个新的HTTPUrlConnection。 我在测试他的方法时发现,可以设置ClientTransportFactory。 我现在使用CustomClientTransportFactory并将其设置在存根上(将其转换为StubBase)。 那么就不需要第二步和第三步了

    在步骤4中,一个人将他的新客户TransportFactory设置为: ((StubBase)myPort)。\u setTransportFactory(新的CustomClientTransportFactory());

    Ray

    谢谢你的输入。听起来你的方法很好,因为它可以避免一些无关的步骤。我必须看一看。但是,除非我遗漏了什么,否则我不相信会创建一个额外的HttpConnection作为YourClientTransport.createHttpConnection(字符串s,SOAPMessageContext ctx)应覆盖HttpClientTransport 1:

    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;
       }
    }
    

    我知道您使用的是Axis,但我很难为Weblogic找到相同的答案,因为您的问题标题和标签都是通用的,下面是我的解决方案

    在实现生成的MyObject接口的客户机类中,我对getServicePort()进行了如下调整(注意,这里还有安全性)

    Oracle文档在这里:但它错误地指出超时时间是以秒为单位的。它实际上是以毫秒为单位的!

    您应该使用:

    import javax.xml.rpc.Stub;
    
    ...
    
    
    int timeout = <number of milliseconds>;
    
    ((Stub) port)._setProperty(
                    "axis.connection.timeout",
                    timeout);
    
    import javax.xml.rpc.Stub;
    ...
    int超时=;
    ((存根)端口)。\u setProperty(
    “axis.connection.timeout”,
    超时);
    
    这个问题可能有点晚了,但我今天才谈到这个问题。 基于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;
                }
            };
        }
    });
    

    它基本上与Yevgeniy提出的相同,但覆盖性稍低(在连接工厂的帮助下)。

    这是一个选项,但我真的希望在web服务的范围内这样做
    ((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;
                }
            };
        }
    });