Wie stelle ich das Zeitlimit für einen JAX-WS-Webservice-Client ein?

93

Ich habe JAXWS-RI 2.1 verwendet, um eine Schnittstelle für meinen Webdienst basierend auf einer WSDL zu erstellen. Ich kann problemlos mit dem Webdienst interagieren, konnte jedoch kein Zeitlimit für das Senden von Anforderungen an den Webdienst angeben. Wenn es aus irgendeinem Grund nicht reagiert, scheint der Kunde nur für immer die Räder zu drehen.

Das Herumjagen hat gezeigt, dass ich wahrscheinlich versuchen sollte, so etwas zu tun:

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

Ich habe auch festgestellt, dass Sie je nach Version von JAXWS-RI möglicherweise stattdessen folgende Eigenschaften festlegen müssen:

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

Das Problem, das ich habe, ist, dass ich nicht weiß, wo ich das tun kann , unabhängig davon, welche der oben genannten Aussagen richtig ist . Ich habe nur eine ServiceUnterklasse, die die automatisch generierte Schnittstelle zum Webservice implementiert. Wenn die WSDL nicht mehr reagiert, ist es bereits zu spät, die Eigenschaften festzulegen:

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

Kann mich jemand in die richtige Richtung weisen?!

neunseitig
quelle
5
Ich glaube nicht, dass ich eine Antwort für Sie habe, aber Ihre Frage hat mir geholfen, mein Problem zu lösen. Ich wusste von der Eigenschaft com.sun.xml.ws.request.timeout, aber nicht von der Eigenschaft com.sun.xml.internal.ws.request.timeout.
Ron Tuffin

Antworten:

89

Ich weiß, dass dies alt ist und woanders beantwortet wurde, aber hoffentlich schließt dies dies ab. Ich bin nicht sicher, warum Sie die WSDL dynamisch herunterladen möchten, aber die Systemeigenschaften:

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

sollte für alle Lese- und Verbindungsvorgänge mit HttpURLConnection gelten, die JAX-WS verwendet. Dies sollte Ihr Problem lösen, wenn Sie die WSDL von einem Remotestandort erhalten - aber eine Datei auf Ihrer lokalen Festplatte ist wahrscheinlich besser!

Wenn Sie Zeitüberschreitungen für bestimmte Dienste festlegen möchten, müssen Sie Ihren Proxy nach dem Erstellen in einen BindingProvider (den Sie bereits kennen) umwandeln, den Anforderungskontext abrufen und Ihre Eigenschaften festlegen. Die Online-JAX-WS-Dokumentation ist falsch, dies sind die richtigen Eigenschaftsnamen (nun, sie funktionieren für mich).

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

Natürlich ist dies eine schreckliche Art, Dinge zu tun. Ich würde eine schöne Fabrik für die Herstellung dieser Bindungsanbieter schaffen, in die die gewünschten Timeouts injiziert werden können.

alpian
quelle
10
Beachten Sie, dass die Eigenschaften REQUEST_TIMEOUT / CONNECT_TIMEOUT tatsächlich von der SUN-internen Klasse com.sun.xml.internal.ws.developer.JAXWSProperties und (zumindest unter 32-Bit-Linux) javac 1.6.0_27 und javac 1.7.0_03 nicht geerbt werden Kompilieren Sie diesen Code (ähnlich wie bei bugs.sun.com/view_bug.do?bug_id=6544224 ) ... Sie müssen -XDignore.symbol.file an javac übergeben, damit es funktioniert.
JavaGuy
Was funktioniert nicht? Ich habe das nur noch einmal überprüft und es funktioniert für mich.
Alpian
Ich habe nur bestätigt, dass ich dies gerade mit JAX-WS RI 2.2.8 und JDK 1.7 verwendet habe und es hat einwandfrei funktioniert. Danke!
Bconneen
Klassen und Parameter, deren vollständig qualifizierter Name "intern" enthält, sollten nicht verwendet werden, da sie herstellerabhängig sind und daher nicht zwischen verschiedenen JDK-Implementierungen portierbar sind. Im Fall von jax-ws-Parametern sind beispielsweise die entsprechenden nicht internen Eigenschaften in der Klasse com.sun.xml.ws.client.BindingProviderProperties vorhanden.
Polaretto
1
@ Matt1776 Ja, natürlich fehlt es: Während JAX-WS eine API-Spezifikation ist, benötigen Sie eine Bibliotheksimplementierung, in diesem Fall jaxws-ri.jar oder jaxws-rt.jar, die nicht Teil des JDK ist. Sie müssen es nur herunterladen und zu Ihrem Projekt hinzufügen, und diese Eigenschaften stehen zur Verfügung.
Polaretto
38

Die Eigenschaften in der akzeptierten Antwort haben bei mir nicht funktioniert, möglicherweise weil ich die JBoss-Implementierung von JAX-WS verwende.

Die Verwendung eines anderen Satzes von Eigenschaften (im JBoss JAX-WS-Benutzerhandbuch zu finden ) hat funktioniert:

//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");
jwaddell
quelle
2
Ich verwende JBoss nicht, aber nur die Eigenschaften in diesem Kommentar haben für mich funktioniert, sonst nichts.
PaulP
2
Die Eigenschaftsnamen hängen von der JAX-WS-Implementierung ab. Eine Liste finden Sie hier: java.net/jira/browse/JAX_WS-1166
fabstab
3
java.net Link ist defekt. github.com/javaee/metro-jax-ws/issues/1166
trunkc
12

Hier ist meine Arbeitslösung:

// --------------------------
// 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.");

    }
}
vnoel
quelle
3
Entsprechen diese Konfigurationen "javax.xml.ws.client.connectionTimeout" und "javax.xml.ws.client.receiveTimeout"?
Jose Tepedino
11
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);

Das hat bei mir funktioniert.

Daniel Kaplan
quelle
Vielen Dank! Auch für mich ist es ein sehr einfacher Weg
Kosm
4
Dies verwendet jedoch Apache CXF-Klassen. Es ist möglicherweise am besten, dies in der Antwort hinzuzufügen. Ein Link, zu dem CXF-Gläser sie enthalten, würde ebenfalls viel helfen.
JBert
@JBert Ich stimme zu. Ich habe vor Jahren geantwortet und kann mich nicht erinnern. Fühlen Sie sich frei, die Antwort zu bearbeiten.
Daniel Kaplan
8

Wenn Sie JAX-WS unter JDK6 verwenden, verwenden Sie die folgenden Eigenschaften:

com.sun.xml.internal.ws.connect.timeout  
com.sun.xml.internal.ws.request.timeout
Domenico Briganti
quelle
System.setProperty ("com.sun.xml.internal.ws.connect.timeout", "300"); System.setProperty ("com.sun.xml.internal.ws.request.timeout", "300") hat bei mir funktioniert.
2787184
2
In einigen Kontexten wissen Sie nicht, in welcher Programmierzeit die JAXWS-Version (intern oder eigenständig) zur Laufzeit verwendet wird. Die beiden sind bis auf diese Timeout-Funktion recht kompatibel. Die Schlüssel unterscheiden sich ( com.sun.xml.internal.ws.connect.timeoutvs com.sun.xml.ws.connect.timeout) auch von der Klasse (oder Schnittstelle), die sie definiert ( com.sun.xml.internal.ws.developer.JAXWSProperties/ com.sun.xml.internal.ws.client.BindingProviderPropertiesvs com.sun.xml.ws.developer.JAXWSProperties/ com.sun.xml.ws.client.BindingProviderProperties). Meine beste Idee ist es, beides festzulegen und Literalwerte als Schlüssel zu verwenden.
Lorinczy Zsigmond
5

Wenn Ihr App-Server WebLogic ist (für mich war es 10.3.6), sind folgende Eigenschaften für Zeitüberschreitungen verantwortlich:

com.sun.xml.ws.connect.timeout 
com.sun.xml.ws.request.timeout
E. Egiazarov
quelle
3

Ich bin mir nicht sicher, ob dies in Ihrem Kontext hilfreich ist ...

Kann das Seifenobjekt als BindingProvider gegossen werden?

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();

Wenn Sie andererseits das Zeitlimit für die Initialisierung des MyWebService-Objekts festlegen möchten, hilft dies nicht.

Dies funktionierte für mich, als ich die einzelnen WebService-Aufrufe zeitlich festlegen wollte.

Ron Tuffin
quelle
2

Der einfachste Weg, um ein langsames Abrufen der Remote-WSDL zu vermeiden, wenn Sie Ihre SEI instanziieren, besteht darin, die WSDL zur Laufzeit nicht vom Remote-Service-Endpunkt abzurufen.

Dies bedeutet, dass Sie Ihre lokale WSDL-Kopie jedes Mal aktualisieren müssen, wenn der Dienstanbieter eine Änderung vornimmt, aber auch, wenn Sie Ihre lokale Kopie jedes Mal aktualisieren müssen, wenn der Dienstanbieter eine Änderung vornimmt.

Wenn ich meine Client-Stubs generiere, weise ich die JAX-WS-Laufzeit an, die SEI so zu kommentieren, dass sie die WSDL von einem vorgegebenen Speicherort im Klassenpfad liest. Standardmäßig ist der Speicherort relativ zum Paketspeicherort der 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>

Das wsldLocation-Attribut teilt der SEI mit, wo sich die WSDL befindet, und die Kopie stellt sicher, dass sich die wsdl (und die unterstützende xsd .. etc ..) an der richtigen Position befindet.

Da der Speicherort relativ zum Speicherort des SEI-Pakets ist, erstellen wir ein neues Unterpaket (Verzeichnis) mit dem Namen wsdl und kopieren dort alle wsdl-Artefakte.

Alles, was Sie an dieser Stelle tun müssen, ist sicherzustellen, dass Sie alle * .wsdl, * .xsd zusätzlich zu allen * .class einschließen, wenn Sie Ihre Client-Stub-Artefakt-JAR-Datei erstellen.

(Falls Sie neugierig sind, befindet sich in der Annotation @webserviceClient dieser wsdl-Speicherort tatsächlich im Java-Code

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