Thanks Daniel, That fixes the concurrent access but In my understanding and tests it does not allow setting a different timeout depending on method, right ? Maybe I am not clear enought, here is the call sequence I have where I want a timeout of 3 secondes for getCustomersByName and default one for getCustomersById:
CustomerService service = getService(); long t = System.currentTimeMillis(); System.out.println("Start time-->" + t); try { HTTPClientPolicy policy = new HTTPClientPolicy(); policy.setReceiveTimeout(3000); ((BindingProvider)service).getRequestContext().put("thread.local.request.context", "true"); ((BindingProvider)service).getRequestContext().put(HTTPClientPolicy.class.getName(), policy); // Dirty code for demo System.out.println(service.getCustomersByName("timeout")); } catch (Exception e) { // Dirty code for demo e.printStackTrace(); } org.apache.cxf.endpoint.Client client = ClientProxy.getClient(service); HTTPConduit conduit = (HTTPConduit) client.getConduit(); // Dirty code for demo System.out.println(conduit); service = getService(); // THIS ONE IS IMPACTED BY PREVIOUS SETTING AS IT'S IN SAME THREAD service.getCustomerById("timeout"); Thanks On Mon, May 6, 2013 at 6:32 PM, Daniel Kulp <dk...@apache.org> wrote: > > On May 6, 2013, at 10:48 AM, Philippe Mouawad <pmoua...@apache.org> wrote: > > > Hello Daniel > > > > Many thanks for clarifications but what I don't understand is how this > one > > would not impact other methods of Webservice. > > - ((BindingProvider)proxy) > > getRequestContext().put(HTTPClientPolicy.class.getName(), policy); > > I made a little test and it seems the second operation getCustomerById is > > impacted, which seems to me regular as the service is a Spring Bean. Am I > > missing something ? > > Oh.. forgot to mention you would have to flip the request context over to > be threadsafe/threadlocal first: > > From: > http://cxf.apache.org/faq.html#FAQ-AreJAXWSclientproxiesthreadsafe%3F > > ((BindingProvider)proxy).getRequestContext().put("thread.local.request.context", > "true"); > > that would then start using a thread local for the context which would > keep the operations separate. > > Dan > > > > > > > > Regards > > Philippe > > > >> > >> On Mon, May 6, 2013 at 4:09 PM, Daniel Kulp <dk...@apache.org> wrote: > >> > >>> > >>> On May 6, 2013, at 10:06 AM, Philippe Mouawad <pmoua...@apache.org> > >>> wrote: > >>> > >>> Many Thanks Daniel for your clarification. > >>> And what about the described ways, are they OK to you ? > >>> > >>> > >>> 1&2 is correct. It would work outside of spring, but would not be > >>> thread safe. A pool of client would work though. > >>> > >> Great > >> > >>> > >>> 3: I don't think the interceptor setting the Message.RECEIVE_TIMEOUT > >>> will work as I don't think that affects the HTTP level timeout, just > the > >>> timeout used for the async calls. I could be wrong though. > >>> > >>> It works I tested it and debugged to be sure it does. It follows one of > >> your explanations ;-) : > >> > >> - > >> > http://cxf.547215.n5.nabble.com/Setting-Http-conduit-using-spring-configuration-file-td2644363.html > >> > >> I changed it to be this to only affect one operation: > >> > >> @Override > >> public void handleMessage(Message message) throws Fault { > >> if("{ > >> http://customerservice.example.com/}CustomerServiceServiceSoapBinding > >> ".equals( > >> > >> > message.getExchange().getBindingOperationInfo().getBinding().getName().toString()) > >> && > >> "{http://customerservice.example.com/}getCustomersByName > >> > ".equals(message.getExchange().getBindingOperationInfo().getOperationInfo().getName().toString()) > >> ) { > >> > >> message.put(Message.RECEIVE_TIMEOUT, > >> getReceiveTimeout()); > >> } > >> } > >> > >> > >> > >>> 4: As you mention, it's an open bug. Likely should work, but not > >>> implemented yet. > >>> > >>> Great > >> > >>> > >>> Dan > >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> Thanks > >>> Regards > >>> Philippe > >>> > >>> On Mon, May 6, 2013 at 3:57 PM, Daniel Kulp <dk...@apache.org> wrote: > >>> > >>>> > >>>> I think the only way to do it right now is to create a specific > >>>> HTTPClientPolicy object for your operation and do something like; > >>>> > >>>> > ((BindingProvider)proxy).getRequestContext().put(HTTPClientPolicy.class.getName(), > >>>> policy); > >>>> > >>>> The conduit should pick that up and intersect it with anything > >>>> configured at the conduit level and then use that. That should at > least > >>>> work with 2.7.x. > >>>> > >>>> > >>>> Dan > >>>> > >>>> > >>>> > >>>> > >>>> On May 3, 2013, at 3:57 AM, Philippe Mouawad <pmoua...@apache.org> > >>>> wrote: > >>>> > >>>>> 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 > >>>> > >>>> -- > >>>> Daniel Kulp > >>>> dk...@apache.org - http://dankulp.com/blog > >>>> Talend Community Coder - http://coders.talend.com > >>>> > >>>> > >>> > >>> -- > >>> Daniel Kulp > >>> dk...@apache.org - http://dankulp.com/blog > >>> Talend Community Coder - http://coders.talend.com > >>> > >>> > >> > > -- > Daniel Kulp > dk...@apache.org - http://dankulp.com/blog > Talend Community Coder - http://coders.talend.com > >