# JAX-WS Client Timeout Problem



## Nowoline (19. Okt 2010)

Hallo Zusammen!

Ich habe ein Problem mit unserem JAX-WS Web Service:

- Eine Anfrage wird vom Client verschickt
- Der Web Service durchläuft die angesprochene Methode und führt über eine Prozedur eine mehr als 5 minütige Berechnung auf unserem SQL-Server aus.
- Nach ca. 300 Sekunden (= Standard Client Timeout?) wird die WebService Methode (void, also kein Rückgabewert, aber Client wartet gewollt ab, bis Methode ausgeführt wurde) einmalig erneut ausgeführt: Die Berechnung wird also zeitversetzt doppelt durchgeführt. Wir haben verschiedene Tools, bei denen jeweils mehrere Methoden mehr als 5min für die Ausführung brauchen -> großes Problem!

Ich habe jetzt bereits seit Tagen das Internet nach Lösungen durchforstet und komme einfach nicht weiter. Folgende Properties für den WS-Port habe ich schon in allen Variationen implementiert und getestet:


```
System.setProperty("sun.net.client.defaultReadTimeout","5000000");
System.setProperty("sun.net.client.defaultConnectTimeout","5000000");
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("com.sun.xml.ws.request.timeout", 3000000);	
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("com.sun.xml.ws.connect.timeout", 3000000);		
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("com.sun.xml.internal.ws.request.timeout", 3000000);		
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("com.sun.xml.internal.ws.connect.timeout", 3000000);		
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("sun.net.client.defaultConnectTimeout", 3000000);		
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("sun.net.client.defaultReadTimeout", 3000000);		
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put(BindingProviderProperties.CONNECT_TIMEOUT, 3000000);		
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT, 3000000);
```

Welche Zeit in Millisekunden ich dabei eingebe, ist unerheblich: Der Timeout bleibt gleich und die Methode wird unverändert nach 5min ungewollt ein zweites Mal ausgeführt. Es ist zum Haare raufen :-/

Weiterhin wurde das Tool mittlerweile auf mehreren Servern mit verschiedenen WebServices getestet – immer mit dem gleichen Ergebnis. Einzige Ausnahme: Ich habe zu Hause einen 64bit Vista Rechner, von dem aus die WebService-Methode wie gewünscht nur einmal ausgeführt wurde. Als Property wurde da gesetzt:


```
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("sun.net.client.defaultConnectTimeout", -1);
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put("sun.net.client.defaultReadTimeout", -1);
```

Diese Einstellungen führen aber auf unseren XP-Rechnern nicht zum identischen Ergebnis.
Die von uns genutzte JRE/JDK Version ist 1.6.0_22.

Ich wäre für hilfreiche Ratschläge sehr sehr dankbar!

Grüße,
Chris


----------



## Nowoline (20. Okt 2010)

Ein erhebliches Stück weiter hat mich der Beitrag aus einem anderen Forum gebracht. Es handelt sich anscheinend um einen Java-Bug, siehe Bug ID: 6382788 URLConnection is silently retrying POST request. Durch Einfügen der Zeile

```
System.setProperty("sun.net.http.retryPost","false");
```
lässt sich dieses Problem beheben...

Gruß,
Chris


----------



## Nowoline (20. Okt 2010)

Hallo,

ich habe mich anscheinend zu früh gefreut. Die Methode wird nun wie gewollt auf dem WebService nur einmalig ausgeführt - das führt allerdings dazu, dass nach ca. 5min (also wieder eine Timeout-Einstellung würde ich vermuten) ein Fehler auf Client-Seite entsteht:


```
Exception in thread "Thread-8" javax.xml.ws.WebServiceException: java.net.SocketException: Unexpected end of file from server
	at com.sun.xml.internal.ws.transport.http.client.HttpClientTransport.readResponseCodeAndMessage(HttpClientTransport.java:201)
	at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:151)
	at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:83)
	at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:105)
	at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
	at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
	at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
	at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
	at com.sun.xml.internal.ws.client.Stub.process(Stub.java:211)
	at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:124)
	at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:98)
	at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
	at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
	at $Proxy27.setBerechnung(Unknown Source)
```

Offensichtlich wird die Methode zwar nur einmal ausgeführt, dafür aber die Verbindung zum Client nach 5min unterbrochen. Das wiederholte Setzen der BindingProvider-Eigenschaften (s.o.) hat keinen Effekt. Ich habe den Eindruck, dass keine der von mir gesetzten Timeout-Einstellungen tatsächlich angenommen und umgesetzt wird. Wie kommt das? Mittlerweile benutze ich folgende BindingProvider-Einstellung:


```
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put(BindingProviderProperties.CONNECT_TIMEOUT, -1);       
((BindingProvider)this.getPOSServiceImplPort()).getRequestContext().put(BindingProviderProperties.REQUEST_TIMEOUT, -1);
```

Wie kann ich o.a. "Unexpected end of file"-Fehler unterbinden?

Gruß,
Chris


----------



## Nowoline (20. Okt 2010)

Hallo,

funktioniert jetzt, einzige Änderung:


```
System.setProperty("sun.net.httpserver.idleInterval", "3600");
```

, wobei "3600" = Zeit in sek = 1h. Diese Einstellung habe ich auf der WebService-Seite in die Main-Methode implementiert - funktioniert!  Die Client-Timeout Einstellungen müssen nicht beachtet werden, es handelt sich in diesem Fall um ein serverseitiges Problem.

Vielen Dank fürs *nicht* helfen...

Gruß,
Chris


----------



## JohannisderKaeufer (20. Okt 2010)

Eine andere Möglichkeit wäre es, aus dem synchronen ein asynchrones System zu machen.
Wenn der Server nur damit Beschäftigt ist Verbindungen aufrecht zu halten, ist das der Gesamtperformance auch nicht immer dienlich.

Eine Webservicemethode nimmt den Input entgegen schuppst deine Berechnung an und liefert eine Adresse zum Abholen des Ergebnisses zurück.

Der Client prüft nun alle 10 Sekunden oder jede Minute, ob es unter der angegebenen Adresse was zum Abholen gibt.

Alternativ wird clientseitig ein Callbackhandler mitgegeben(Adresse unter der der Client das Ergebnis erwartet), der nach Beenden der Berechnung aufgerufen wird. Hier würde der Client einen zusätzlichen Webserviceendpoint bereitstellen, der Ergebnisse entgegen nimmt.


----------

