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

Reply via email to