Question:
Is there a way to shorten the timeout in CXF? (http://incubator.apache.org/cxf/)
Answer:
After looking through the CXF documentation, they state that you through Spring (www.springframework.org) can set a timout.
This is done like this (on the client side):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd">
<http-conf:conduit name="*.http-conduit">>
<http-conf:client ReceiveTimeout="100" />
</http-conf:conduit>
</beans>
I use name=”*.http-conduit” to make my life more simple
This example is from a larger example about ssl configuration on the client connection. It was found here: http://cwiki.apache.org/CXF20DOC/client-http-transport-including-ssl-support.html
There are some additional information in their javadoc, about the HTTPConduit we are setting through spring.: http://incubator.apache.org/cxf/javadoc/latest/org/apache/cxf/transport/http/HTTPConduit.html
The Tests:
When testing this, I implemented the small “HelloWorld” webservice from the CXF User’s guide (http://cwiki.apache.org/CXF20DOC/a-simple-jax-ws-service.html), which can receive a text through a sayHi service, and sends back the response: “Hello “+text-you’ve-sent
In order to test this, i’ve made a dynamical client (just to try, and their guides show an example of doing this).
In the project at work, we are using a generated client, so I made this also.
The dynamical client was made as follows:
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost/HelloWorld/HelloWorld?wsdl");
Object[] results = client.invoke("sayHi", "tester");
System.out.println("response from ws: "+results[0]);
The generated client was made as follows, using wsdl2java:
wsdl2java -impl -p test.webservice.client http://localhost/HelloWorld/HelloWorld?wsdl
I then wrote a test for the dynamic client and the generated client, just to see if it all worked.
package test;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.webservice.client.HelloWorld;
import test.webservice.client.HelloWorldImplService;
public class TestClient extends TestCase {
protected void setUp() throws Exception {
super.setUp();
}
public void testHelloWorldDynamically() throws Exception {
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost/HelloWorld/HelloWorld?wsdl");
Object[] results = client.invoke("sayHi", "tester");
System.out.println("response from ws: "+results[0]);
}
public void testHelloWorldGenerated() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"client-beans.xml"});
HelloWorldImplService service = new HelloWorldImplService();
HelloWorld port = service.getHelloWorldImplPort();
String result = port.sayHi("tester2");
System.out.println(result);
}
}
I then altered the sayHi() method on the webservice, to have a Thread.sleep(5000) in it. This was done, so I could simulate a long service call.
package test.webservice;
import javax.jws.WebService;
@WebService(endpointInterface = "test.webservice.HelloWorld")
public class HelloWorldImpl implements HelloWorld {
public String sayHi(String text) {
try {
Thread.sleep(5000);
}
catch(InterruptedException ie) {
}
return "Hello " + text;
}
}
After some testing, I discovered that the spring configuration didn’t work. According to http://issues.apache.org/jira/browse/CXF-922 the issue with spring configurations where closed and submitted in cxf-2.0.3
Even after upgrading to cxf-2.0.4 it didn’t work.
I then decided to try and set the configuration manually on the dynamically generated client. Based on the information about the spring configuration, I was looking for a “http conduit” in their javadoc.
Their javadoc states that, the HTTPConduit has a method called getClient(), which returns a HTTPClientPolicy. On this HTTPClientPolicy I can set the ReceiveTimeout manually.
So i’ve made a some changes to the JUnit test to see if it all worked.
package test;
import junit.framework.TestCase;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.webservice.client.HelloWorld;
import test.webservice.client.HelloWorldImplService;
public class HelloWorldClientTest extends TestCase {
protected void setUp() throws Exception {
super.setUp();
}
public void testHelloWorldDynamically() throws Exception {
// creating the client
DynamicClientFactory dcf = DynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost/HelloWorld/HelloWorld?wsdl");
// Testing the current values
HTTPConduit httpConduit = (HTTPConduit)client.getConduit();
System.out.println("ReceiveTimeout: "+httpConduit.getClient().getReceiveTimeout());
// setting the new values
httpConduit.getClient().setReceiveTimeout(100);
System.out.println("ReceiveTimeout: "+httpConduit.getClient().getReceiveTimeout());
Object[] results = client.invoke("sayHi", "tester");
System.out.println("response from ws: "+results[0]);
}
public void testHelloWorldGenerated() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"client-beans.xml"});
HelloWorldImplService service = new HelloWorldImplService();
HelloWorld port = service.getHelloWorldImplPort();
// setting the timeout
Client c = ClientProxy.getClient(port);
HTTPConduit httpConduit = (HTTPConduit) c.getConduit();
httpConduit.getClient().setReceiveTimeout(100);
String result = port.sayHi("tester2");
System.out.println(result);
}
}
The tests now throws two java.net.SocketTimeoutException, which means that my changes are now working. Cheers!