How do I set the timeout for a JAX-WS webservice client?

JavaWeb ServicesSoapTimeoutJax Ws

Java Problem Overview


I've used JAXWS-RI 2.1 to create an interface for my web service, based on a WSDL. I can interact with the web service no problems, but haven't been able to specify a timeout for sending requests to the web service. If for some reason it does not respond the client just seems to spin it's wheels forever.

Hunting around has revealed that I should probably be trying to do something like this:

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

I also discovered that, depending on which version of JAXWS-RI you have, you may need to set these properties instead:

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

The problem I have is that, regardless of which of the above is correct, I don't know where I can do this. All I've got is a Service subclass that implements the auto-generated interface to the webservice and at the point that this is getting instanciated, if the WSDL is non-responsive then it's already too late to set the properties:

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

Can anyone point me in the right direction?!

Java Solutions


Solution 1 - Java

I know this is old and answered elsewhere but hopefully this closes this down. I'm not sure why you would want to download the WSDL dynamically but the system properties:

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

should apply to all reads and connects using HttpURLConnection which JAX-WS uses. This should solve your problem if you are getting the WSDL from a remote location - but a file on your local disk is probably better!

Next, if you want to set timeouts for specific services, once you've created your proxy you need to cast it to a BindingProvider (which you know already), get the request context and set your properties. The online JAX-WS documentation is wrong, these are the correct property names (well, they work for me).

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

Of course, this is a horrible way to do things, I would create a nice factory for producing these binding providers that can be injected with the timeouts you want.

Solution 2 - Java

The properties in the accepted answer did not work for me, possibly because I'm using the JBoss implementation of JAX-WS?

Using a different set of properties (found in the JBoss JAX-WS User Guide) made it work:

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

Solution 3 - Java

Here is my working solution :

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

	}
}

Solution 4 - Java

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

This worked for me.

Solution 5 - Java

If you are using JAX-WS on JDK6, use the following properties:

com.sun.xml.internal.ws.connect.timeout  
com.sun.xml.internal.ws.request.timeout

Solution 6 - Java

In case your appserver is WebLogic (for me it was 10.3.6) then properties responsible for timeouts are:

com.sun.xml.ws.connect.timeout 
com.sun.xml.ws.request.timeout

Solution 7 - Java

Not sure if this will help in your context...

Can the soap object be cast as a 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();

On the other hand if you are wanting to set the timeout on the initialization of the MyWebService object then this will not help.

This worked for me when wanting to timeout the individual WebService calls.

Solution 8 - Java

the easiest way to avoid slow retrieval of the remote WSDL when you instantiate your SEI is to not retrieve the WSDL from the remote service endpoint at runtime.

this means that you have to update your local WSDL copy any time the service provider makes an impacting change, but it also means that you have to update your local copy any time the service provider makes an impacting change.

When I generate my client stubs, I tell the JAX-WS runtime to annotate the SEI in such a way that it will read the WSDL from a pre-determined location on the classpath. by default the location is relative to the package location of the 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>

the wsldLocation attribute tells the SEI where is can find the WSDL, and the copy makes sure that the wsdl (and supporting xsd.. etc..) is in the correct location.

since the location is relative to the SEI's package location, we create a new sub-package (directory) called wsdl, and copy all the wsdl artifacts there.

all you have to do at this point is make sure you include all *.wsdl, *.xsd in addition to all *.class when you create your client-stub artifact jar file.

(in case your curious, the @webserviceClient annotation is where this wsdl location is actually set in the java code

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionninesidedView Question on Stackoverflow
Solution 1 - JavaalpianView Answer on Stackoverflow
Solution 2 - JavajwaddellView Answer on Stackoverflow
Solution 3 - JavavnoelView Answer on Stackoverflow
Solution 4 - JavaDaniel KaplanView Answer on Stackoverflow
Solution 5 - JavaDomenico BrigantiView Answer on Stackoverflow
Solution 6 - JavaE.EgiazarovView Answer on Stackoverflow
Solution 7 - JavaRon TuffinView Answer on Stackoverflow
Solution 8 - JavaHelter ScelterView Answer on Stackoverflow