web-dev-qa-db-ja.com

JAX-WS Webサービスクライアントのタイムアウトを設定するにはどうすればよいですか?

JAXWS-RI 2.1を使用して、WSDLに基づいてWebサービスのインターフェイスを作成しました。私は問題なくWebサービスと対話できますが、Webサービスに要求を送信するためのタイムアウトを指定できませんでした。何らかの理由で応答しない場合、クライアントはホイールを永遠に回転させているように見えます。

探し回ってみると、おそらく次のようなことをしようとしているはずです。

((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.ws.connect.timeout", 10000);

また、お持ちのJAXWS-RIのバージョンによっては、代わりにこれらのプロパティを設定する必要がある場合があることも発見しました。

((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.internal.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.internal.ws.connect.timeout", 10000);

私が抱えている問題は、上記のどれが正しいかに関係なく、whereがわからないことです。私が持っているのは Service サブクラスだけで、Webサービスへの自動生成されたインターフェースを実装します。プロパティ:

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
soap.sendRequestToMyWebService();

誰かが私を正しい方向に向けることができますか?!

86
ninesided

私はこれが古く、他の場所で答えられていることを知っていますが、うまくいけばこれがこれを閉じます。 WSDLを動的にダウンロードする理由はわかりませんが、システムプロパティは次のとおりです。

Sun.net.client.defaultConnectTimeout (default: -1 (forever))
Sun.net.client.defaultReadTimeout (default: -1 (forever))

jAX-WSが使用するHttpURLConnectionを使用するすべての読み取りと接続に適用する必要があります。これは、リモートの場所からWSDLを取得している場合に問題を解決するはずです-しかし、ローカルディスク上のファイルの方がおそらく良いでしょう!

次に、特定のサービスのタイムアウトを設定する場合、プロキシを作成したら、それをBindingProvider(既に知っている)にキャストし、リクエストコンテキストを取得してプロパティを設定する必要があります。オンラインのJAX-WSドキュメントは間違っています。これらは正しいプロパティ名です(まあ、私にとってはうまくいきます)。

MyInterface myInterface = new MyInterfaceService().getMyInterfaceSOAP();
Map<String, Object> requestContext = ((BindingProvider)myInterface).getRequestContext();
requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 3000); // Timeout in millis
requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, 1000); // Timeout in millis
myInterface.callMyRemoteMethodWith(myParameter);

もちろん、これは物事を行う恐ろしい方法です。必要なタイムアウトを挿入できるこれらのバインディングプロバイダーを生成するためのNiceファクトリを作成します。

83
alpian

おそらく、JAX-WSのJBoss実装を使用しているため、受け入れられた回答のプロパティが機能しませんでしたか?

別のプロパティセット( JBoss JAX-WSユーザーガイド にあります)を使用して機能しました:

//Set timeout until a connection is established
((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000");

//Set timeout until the response is received
((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000");
34
jwaddell

ここに私の作業ソリューションがあります:

// --------------------------
// SOAP Message creation
// --------------------------
SOAPMessage sm = MessageFactory.newInstance().createMessage();
sm.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
sm.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8");

SOAPPart sp = sm.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
se.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
se.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

SOAPBody sb = sm.getSOAPBody();
// 
// Add all input fields here ...
// 

SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
// -----------------------------------
// URL creation with TimeOut connexion
// -----------------------------------
URL endpoint = new URL(null,
                      "http://myDomain/myWebService.php",
                    new URLStreamHandler() { // Anonymous (inline) class
                    @Override
                    protected URLConnection openConnection(URL url) throws IOException {
                    URL clone_url = new URL(url.toString());
                    HttpURLConnection clone_urlconnection = (HttpURLConnection) clone_url.openConnection();
                    // TimeOut settings
                    clone_urlconnection.setConnectTimeout(10000);
                    clone_urlconnection.setReadTimeout(10000);
                    return(clone_urlconnection);
                    }
                });


try {
    // -----------------
    // Send SOAP message
    // -----------------
    SOAPMessage retour = connection.call(sm, endpoint);
}
catch(Exception e) {
    if ((e instanceof com.Sun.xml.internal.messaging.saaj.SOAPExceptionImpl) && (e.getCause()!=null) && (e.getCause().getCause()!=null) && (e.getCause().getCause().getCause()!=null)) {
        System.err.println("[" + e + "] Error sending SOAP message. Initial error cause = " + e.getCause().getCause().getCause());
    }
    else {
        System.err.println("[" + e + "] Error sending SOAP message.");

    }
}
12
vnoel
ProxyWs proxy = (ProxyWs) factory.create();
Client client = ClientProxy.getClient(proxy);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(0);
http.setClient(httpClientPolicy);

これは私のために働いた。

9
Daniel Kaplan

JDK6でJAX-WSを使用している場合は、次のプロパティを使用します。

com.Sun.xml.internal.ws.connect.timeout  
com.Sun.xml.internal.ws.request.timeout
7

アプリサーバーがWebLogic(私にとっては10.3.6)の場合、タイムアウトの原因となるプロパティは次のとおりです。

com.Sun.xml.ws.connect.timeout 
com.Sun.xml.ws.request.timeout
4
E.Egiazarov

これがあなたのコンテキストで役立つかどうかわからない...

SoapオブジェクトをBindingProviderとしてキャストできますか?

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
// set timeouts here
((BindingProvider)soap).getRequestContext().put("com.Sun.xml.internal.ws.request.timeout", 10000);
    soap.sendRequestToMyWebService();

一方、MyWebServiceオブジェクトの初期化でタイムアウトを設定する場合、これは役に立ちません。

これは、個々のWebService呼び出しをタイムアウトさせたいときに役立ちました。

3
Ron Tuffin

sEIをインスタンス化するときにリモートWSDLの取得が遅くならないようにする最も簡単な方法は、実行時にリモートサービスエンドポイントからWSDLを取得しないことです。

これは、サービスプロバイダーが影響を与える変更を行うたびにローカルWSDLコピーを更新する必要があることを意味しますが、サービスプロバイダーが影響を与える変更を行うたびにローカルコピーを更新する必要があることも意味します。

クライアントスタブを生成するとき、JAX-WSランタイムに、クラスパス上の所定の場所からWSDLを読み取るようにSEIに注釈を付けるように指示します。デフォルトでは、場所はService SEIのパッケージの場所に相対的です。


<wsimport
    sourcedestdir="${dao.helter.dir}/build/generated"
    destdir="${dao.helter.dir}/build/bin/generated"
    wsdl="${dao.helter.dir}/src/resources/schema/helter/helterHttpServices.wsdl"
    wsdlLocation="./wsdl/helterHttpServices.wsdl"
    package="com.helter.esp.dao.helter.jaxws"
    >
    <binding dir="${dao.helter.dir}/src/resources/schema/helter" includes="*.xsd"/>
</wsimport>
<copy todir="${dao.helter.dir}/build/bin/generated/com/helter/esp/dao/helter/jaxws/wsdl">
    <fileset dir="${dao.helter.dir}/src/resources/schema/helter" includes="*" />
</copy>

wsldLocation属性はSEIにWSDLを見つけることができる場所を伝え、コピーはwsdl(およびサポートするxsd ..など)が正しい場所にあることを確認します。

場所はSEIのパッケージの場所を基準にしているため、wsdlという新しいサブパッケージ(ディレクトリ)を作成し、そこにすべてのwsdlアーティファクトをコピーします。

この時点で行う必要があるのは、クライアントスタブアーティファクトjarファイルを作成するときに、すべての* .classに加えて、すべての* .wsdl、*。xsdを含めることです。

(好奇心が強い場合、@ webserviceClient注釈は、このwsdlの場所がJavaコードで実際に設定される場所です

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")
2
Helter Scelter