8

私は、JAXRPC-RI (参照実装) ライブラリを使用して構築されたいくつかのクライアント コードを使用して、SOAP Web サービス (私が絶対に、積極的に嫌うテクノロジ) と対話する、少し古いコンポーネントを使用しています。

スタブでタイムアウトを設定して、Web サービス サーバーが X 秒以内に応答しない場合に、アプリケーションが永遠に応答を待機するように設定しないことに興味があります。

私はApache Axisによって生成されたクライアント/スタブを操作することに慣れています。これを使用org.apache.axis.client.Stub.setTimeout()して、タイムアウトを設定するだけです。

私の人生では、JAXRPC-RI で作成されたスタブを使用するときにタイムアウトを設定する方法がわかりません。

  • インスタンス化するポート クラスは、 and を拡張com.sun.xml.rpc.client.StubBaseして実装javax.xml.rpc.Stubcom.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

JAXRPC-RI クライアントを使用するときにタイムアウトを設定/強制する方法について誰か考えがありますか? それは可能ですか?

4

8 に答える 8

4

sun.net.client.defaultConnectTimeoutまたはなどのプロパティを設定するsun.net.client.defaultReadTimeoutと、システム全体のタイムアウトが発生する可能性があります。

コードでは、プロパティ値は文字列を使用して設定されます。

System.setProperty("sun.net.client.defaultConnectTimeout", "1000");
System.setProperty("sun.net.client.defaultReadTimeout", "1000");

簡単なテストを行うには、環境変数を設定するJAVA_OPTSか、コマンド ラインを使用する方が簡単な場合があります。

java -Dsun.net.client.defaultConnectTimeout="1000" ...
于 2009-06-07T15:45:49.120 に答える
2

この特定の JAXRPC 実装が、タイムアウトの設定を困難にするために、なぜ道に迷っているのか、私にはわかりません。おそらく、それには正当な理由があります。Axis や JAX-WS などの他の実装では、スタブで setTimeout() メソッドを呼び出すだけです。苦労の末、この解決策を思いつくことができました。うまくいけば、それは役に立ちます。基になる URLConnection でタイムアウトを設定するには、次の手順を実行する必要があります。

  1. 新しい ClientTransport クラスを作成します。com.sun.xml.rpc.client.http.HttpClientTransport クラスを拡張する必要があります。createHttpConnection(String, SOAPMessageContext) メソッドをオーバーライドします。HttpURLConnection オブジェクトを返す super.createHttpConnection() を呼び出します。HttpURLConnection オブジェクトで setReadTimeout() を呼び出すと、クライアント側のタイムアウトを X ミリ秒単位で強制できます。それが完了したら、変更された HttpURLConnection オブジェクトを返します。
  2. クライアント側の Stub クラスを独自のもので拡張します。_getTransport() メソッドをオーバーライドして、手順 (1) で作成した ClientTransport クラスの新しいインスタンスを返します。
  3. クライアント側の _Impl クラスを独自のもので拡張します。get...Port() メソッドをオーバーライドして、生成されたスタブではなく、手順 (2) で作成したスタブを使用するようにします。
  4. 手順 (2) で作成した Stub と手順 (3) で作成した _Impl を使用するように、Web サービスを呼び出すように記述したクライアント コードを変更します。

注: wscompile (Ant スクリプト?) を介してスタブを生成するために呼び出しているものが何であれ、作成/変更したばかりの 3 つの Java クラスを上書きしないことを確認してください。それらが上書きされないように、それらを別のパッケージに移動することはおそらく理にかなっています。

于 2010-11-04T17:08:50.537 に答える
1

あなたが Axis を使用していることは知っていますが、Weblogic について同じ答えを見つけるのに苦労しました。質問のタイトルとタグは一般的なものなので、ここに私の解決策があります。

生成された 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;
}

Oracle のドキュメントはhttp://docs.oracle.com/cd/E12840_01/wls/docs103/webserv_rpc/client.html#wp241849にありますが、タイムアウトが秒単位であると誤って記載されています。実際にはミリ秒単位です。

于 2012-07-31T09:20:17.440 に答える
1

Yevgeniy Treyvus の回答は非常に優れていますが、SOAP 呼び出しごとに新しい HTTPUrlConnection が作成されます。彼のアプローチをテストしているときに、ClientTransportFactory を設定できることがわかりました。ここで CustomClientTransportFactory を使用し、それをスタブに設定します ( StubBase にキャストします)。その場合、ステップ 2 と 3 は必要ありません。

ステップ 4 で、新しい ClientTransportFactory を次のように設定します。 ((StubBase) myPort)._setTransportFactory(new CustomClientTransportFactory());

于 2010-11-25T12:03:13.610 に答える
0

私はただ恩恵を享受しようとしているので、私が完全に間違った方向に進んでいる場合は私を撃たないでください:)アプリケーションが「応答を待って永遠にそこに設定されている」場合は、別のリクエストを行うことができますスレッドとスポーン後、次の呼び出しでrequestThreadがまだ生きているかどうかを確認し、生きている場合は強制終了しようとするとrequestThread言うことができます。requestThread.join(max_time_to_wait);

あなたのアプリケーションはタイムアウト後に進みます、そしてそれは最もエレガントでない解決策ではありません...

于 2009-06-02T15:10:16.943 に答える
0

レイ、

ご意見ありがとうございます。いくつかの無関係な手順を回避できるため、あなたのアプローチは優れているように思えます。私は見てみる必要があります。ただし、何かが欠けていない限り、 YourClientTransport.createHttpConnection(String s, SOAPMessageContext ctx) が HttpClientTransport をオーバーライドする必要があるため、追加の HttpConnection が作成されているとは思いません。

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;
   }
}
于 2010-12-07T16:49:48.630 に答える