Hello, I am working on the right way to configure Client Timeout on client side and I am kind of confused by what I read:
- http://cxf.547215.n5.nabble.com/Setting-Http-conduit-using-spring-configuration-file-td2644363.html - https://issues.apache.org/jira/browse/CXF-3011 - http://stackoverflow.com/questions/3012787/connection-details-timeouts-in-a-java-web-service-client - http://stackoverflow.com/questions/3130913/setting-jax-ws-client-timeout/6700210#6700210 - http://stackoverflow.com/questions/2148915/how-do-i-set-the-timeout-for-a-jax-ws-webservice-client/6700216#6700216 So the things that work: 1) Outside of Spring, this one works fine: CustomerServiceService customerService = new CustomerServiceService(new URL("http://localhost:8080/pyxis/services/customerService?wsdl")); CustomerService client = customerService.getCustomerServicePort(); Client cl = ClientProxy.getClient(client); HTTPConduit http = (HTTPConduit) cl.getConduit(); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setConnectionTimeout(5000); httpClientPolicy.setReceiveTimeout(1500); http.setClient(httpClientPolicy); client.myMethod() Question => This would be OK outside of Spring right ? 2) But within Spring, I understand it is not Thread Safe to modify the conduit as the service would be a singleton ? Question => Is it the reason for which it is not fine or did I misunderstand ? 3) So I coded this Interceptor: public class OutTimeoutInterceptor extends AbstractPhaseInterceptor<Message> { private int receiveTimeout; public OutTimeoutInterceptor() { super(Phase.PREPARE_SEND); } public OutTimeoutInterceptor(String phase) { super(phase); } public OutTimeoutInterceptor(String phase, boolean uniqueId) { super(phase, uniqueId); } public OutTimeoutInterceptor(String i, String p, boolean uniqueId) { super(i, p, uniqueId); } public OutTimeoutInterceptor(String i, String p) { super(i, p); } @Override public void handleMessage(Message message) throws Fault { if("{ http://customerservice.example.com/}CustomerServiceServiceSoapBinding".equals(message.getExchange().getBindingOperationInfo().getBinding().getName().toString())) { message.put(Message.RECEIVE_TIMEOUT, getReceiveTimeout()); } } /** * @return the receiveTimeout */ public int getReceiveTimeout() { return receiveTimeout; } /** * @param receiveTimeout the receiveTimeout to set */ public void setReceiveTimeout(int receiveTimeout) { this.receiveTimeout = receiveTimeout; } } Configured this: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws=" http://cxf.apache.org/jaxws" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:http-conf=" http://cxf.apache.org/transports/http/configuration" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd"> <!-- Needed --> <!-- When you don't use the imports, when a Bus is needed, it will create a default bus which would be using it's own spring context. When the Bus looks for configuration, it would just look in that spring context since it wouldn't know about your context. I THINK if you use a jaxws:client thing instead of a spring bean, it MAY wire the current context into the default bus. Not really sure though. However, if you use normal spring beans, not much we can do unless we create spring specific subclasses (which we could) that would be Spring ApplicationContextAware to to wire things. Would be more of a documentation issue of "when to use JaxWsProxyFactoryBean or SpringJaxWsProxyFactoryBean" and such. --> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <http-conf:conduit name="{ http://customerservice.example.com/}CustomerServicePort.http-conduit"> <http-conf:client ReceiveTimeout="30000" /> </http-conf:conduit> <bean id="proxyFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="com.example.customerservice.CustomerService" /> <property name="wsdlLocation" value="classpath:/wsdl/CustomerService.wsdl" /> <property name="address" value="http://localhost:8080/pyxis/services/customerService" /> <property name="inInterceptors"> <list> <ref bean="logIn" /> </list> </property> <property name="outInterceptors"> <list> <ref bean="logOut" /> <!-- Set timeout per operation--> <ref bean="timeoutSetter" /> </list> </property> </bean> <bean id="client" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean" factory-bean="proxyFactory" factory-method="create" /> <bean id="logIn" class="org.apache.cxf.interceptor.LoggingInInterceptor" /> <bean id="logOut" class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> <bean id="timeoutSetter" class="com.adeo.pyxis.poc.cxf.client.OutTimeoutInterceptor"> <property name="receiveTimeout" value="3000" /> </bean> <bean id="factory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean" /> </beans> Question => This works fine but seems to me not that straight, so I wonder if it's the right way ? 4) I thought the JAXWS way would work reading this: http://cxf.apache.org/docs/developing-a-consumer.html *Request context* - on the client side, the request context enables you to set properties that affect outbound messages. Request context properties are applied to a specific port instance and, once set, the properties affect every subsequent operation invocation made on the port, until such time as a property is explicitly cleared. For example, you might use a request context property to set a connection timeout or to initialize data for sending in a header. Service = new Service(); Port = Service.getPort(); ((BindingProvider) Port).getRequestContext().put( BindingProviderProperties.CONNECT_TIMEOUT, 30); ((BindingProvider) Port).getRequestContext().put( BindingProviderProperties.REQUEST_TIMEOUT, 30); But it does not and I am confused by this Open bug: https://issues.apache.org/jira/browse/CXF-3011 Question => Is it supposed to work ? Looking into source code I don't find how but I would like some confirmation ? I will be happy to contribute documentation patch to clarify this as it seems to me kind of difficult to find the right answer. Many thanks for your help and thanks for CXF ! Regards Philippe