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?!
This question is related to
java
web-services
soap
timeout
jax-ws
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
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
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.
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.
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.");
}
}
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")
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");
Source: Stackoverflow.com