You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Philippe Mouawad <pm...@apache.org> on 2013/06/07 20:46:17 UTC

Fwd: What is the proper way of setting client Timeout per Webservice method ?

Hello,
Forwarding to mailing list as it contains the definite answer.

Thanks Daniel.
Didn't have time yet, will try to update wiki.

Pegards
Philippe

---------- Forwarded message ----------
From: *Daniel Kulp*
Date: Wednesday, May 8, 2013
Subject: What is the proper way of setting client Timeout per Webservice
method ?
To: Philippe Mouawad <pm...@apache.org>



On May 8, 2013, at 1:40 AM, Philippe Mouawad
<pmouawad@apache.org<javascript:_e({}, 'cvml',
'pmouawad@apache.org');>>
wrote:

Hello Daniel,
Thanks for this.
Regarding mu question on timeout I wanted to know if I was issing something
in your proposed solution as it does not work to have different timeouts
for 2 operations.


It would need to be specifically set on the request context prior to each
call.  Thus, not something that is "automatic" depending on the operation.
  At this point, the interceptor is likely the only option for handling it
automatically.

Regardinh ICLA I have already signed one for JMeter project, do I need one
for CXF ? Where are the docs located in subversion ?


It's not in subversion.   We use confluence:

https://cwiki.apache.org/confluence/display/CXF/Index
https://cwiki.apache.org/confluence/display/CXF20DOC/Index


If you create an account in confluence and send me the ID, I'll add you to
the group that is marked as having submitted an ICLA and you can edit away.
  I *THINK* you have an id of:
p.mouawad@ubik-ingenierie.com<ht...@ubik-ingenierie.com>

as that looks like you, but I want to confirm first.


Dan



Thanks
Regards
Philippe

On Wednesday, May 8, 2013, Daniel Kulp wrote:

>
> On May 7, 2013, at 10:14 AM, Philippe Mouawad <pm...@apache.org> wrote:
>
> > Hello,
> > Any update on this ?
> >
> > If we want to contribute some docs patches, what is the way for it ? I
> > don't see docs in source code of project. I've read this
> > http://cxf.apache.org/getting-involved.html.
>
> You would need to submit an ICLA to apache.  See:
> http://www.apache.org/dev/new-committers-guide.html#cla
>
> Once that is submitted and processed, we can actually grant your account
> in confluence to have write access and you can make any doc updates you
> need/want.
>
>
> >
> >
> > Thanks
> > Regards
> > Philippe
> >
> > On Mon, May 6, 2013 at 6:53 PM, Philippe Mouawad <pmouawad@apache.org
> >wrote:
> >
> >> 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 <pm...@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 <pm...@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 <pm...@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
> >>>>>>> dkulp@apache.org - http://dankulp.com/blog
> >>>>>>> Talend Community Coder - http://coders.talend.com
> >>>>>>>
> >>>>>>>
> >>>>>>
> >>>>>> --
> >>>>>> Daniel Kulp
> >>>>>> dkulp@apache.org - http://dankulp.com/blog
> >>>>>> Talend Community Coder - http://coders.talend.com
> >>>>>>
> >>>>>>
> >>>>>
> >>>
> >>> --
> >>> Daniel Kulp
> >>> dkulp@apache.org - http://dankulp.com/blog
> >>> Talend Community Coder - http://coders.talend.com
> >>>
> >>>
> >>
>
> --
> Daniel Kulp
> dkulp@apache.org - http://dankulp.com/blog
> Talend Community Coder - http://coders.talend.com
>
>
-- 
Daniel Kulp
dkulp@apache.org <javascript:_e({}, 'cvml', 'dkulp@apache.org');> -
http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com