You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Marc Giger <gi...@gmx.ch> on 2009/02/06 19:17:55 UTC

HttpConduit thread safety

Hi,

Is the following code (copied from the user-docs) thread safe?

import org.apache.cxf.endpoint.Client;
  import org.apache.cxf.frontend.ClientProxy;
  import org.apache.cxf.transport.http.HTTPConduit;
  import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
  ...

  URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
  SOAPService service = new SOAPService(wsdl, serviceName);
  Greeter greeter = service.getPort(portName, Greeter.class);

  // Okay, are you sick of configuration files ?
  // This will show you how to configure the http conduit dynamically
  Client client = ClientProxy.getClient(greeter);
  HTTPConduit http = (HTTPConduit) client.getConduit();

  HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();

  httpClientPolicy.setConnectionTimeout(36000);
  httpClientPolicy.setAllowChunking(false);
  httpClientPolicy.setReceiveTimeout(32000);

  http.setClient(httpClientPolicy);

  ...
  greeter.sayHi("Hello");


Not that I have found any issue with it, but I want to
be sure that it's intended to be.

The requirement is to invoke multiple Endpoints in parallel where
every EP has its own configuration (SSL-Client-Authentication,
timeouts, url, expect-100-continue, etc). The whole configuration
must be made at runtime, because the EP aren't known at startup time.

Thank you!

Marc

Re: HttpConduit thread safety

Posted by Marc Giger <gi...@gmx.ch>.
Hi Dan

On Mon, 9 Feb 2009 16:43:35 -0500
Daniel Kulp <dk...@apache.org> wrote:

> 
> Basically, if you set all the conduit properties ONCE up front and also don't 
> use http sessions and all use either http or https, but not both, then you can 
> do this.   Do:
> 
> ((BindingProvider)proxy).getRequestContext().put("thread.local.request.context", 
> "true");
> 
> as part of the setup.   That will make the RequestContext thread local.  Then, 
> each thread can do:
> 
> 
> ((BindingProvider)proxy).getRequestContext().put(
>     BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
>     "http://my.url.to.somplace");
> 
> and that will be fine.
> 
> If you need to setup unique valued per request other than just the URL, then I 
> suggest using a pool of client proxies.   Create a few and pool them.
> 
> Dan

Performance is a secondary goal. First everything has to work absolutely correctly
with an unknown number of endpoints and its configuration.

The following test-code seems to do what I want (debugger verified). Also it seems to be possible to
use http AND https with it:

public class TestHttpConduit {

    private static final QName serviceName = new QName(
            "http://www.swissdec.ch/schema/sd/20051002/SalaryDeclarationService", "SalaryDeclarationService");
    private static final QName portName = new QName(
            "http://www.swissdec.ch/schema/sd/20051002/SalaryDeclarationService", "SalaryDeclaration");

    private URL wsdl = getClass().getResource("/wsdl/wsdl/SalaryDeclarationService.wsdl");
    private SalaryDeclarationService salaryDeclarationService = new SalaryDeclarationService(wsdl);

    public TestHttpConduit() {

        SalaryDeclarationPort salaryDeclarationPort = salaryDeclarationService.getSalaryDeclaration();
        System.out.println("Port: " + salaryDeclarationPort.hashCode());
        Client client = ClientProxy.getClient(salaryDeclarationPort);
        System.out.println("Client: " + client.hashCode());
        //((ClientImpl)client).setSynchronousTimeout(1000);
        HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
        System.out.println("Conduit: " + httpConduit.hashCode());

        HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
        //httpClientPolicy.setConnectionTimeout(1);
        //httpClientPolicy.setReceiveTimeout(1);

        httpConduit.setClient(httpClientPolicy);

        try {
            Map context = new HashMap();
            Map requestContext = new HashMap();
            context.put(Client.REQUEST_CONTEXT, requestContext);
            requestContext.put(Message.ENDPOINT_ADDRESS, "http://localhost:9001/refapps-receiver/SalaryDeclarationService");
            PingType pingType = new PingType();
            pingType.setEcho("HAAAAAAALLLLLLLLLLLOOOOOOOOOOO");

            QName qName = new QName(SalaryDeclarationService.SERVICE.getNamespaceURI(), Constants20051002.Operation.Ping.name());
            BindingOperationInfo op = client.getEndpoint().getEndpointInfo().getBinding().getOperation(qName);

            PingType pingresponseType = (PingType) client.invoke(op, new Object[]{pingType}, context)[0];
            System.out.println(pingresponseType.getEcho());

            salaryDeclarationPort.ping(pingType);
        } catch (SoapFault soapFault) {
            System.out.println(soapFault);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++){
            new TestHttpConduit();
        }
    }
}

For every iteration I get a new client, httpConduit and port. Any objections?

Unfortunately I came to the conclusion that a very important feature is missing:
Expect: 100-continue

How do others handle e.g. the case with two-way-ssl (mutual-authentication) on a Apache <Location> ?

So thats the killer criteria. It seems I have to stick with XFire and commons-http.

Dan, any ideas?

Thanks a lot!

Marc


> 
> 
> 
> 
> On Fri February 6 2009 1:17:55 pm Marc Giger wrote:
> > Hi,
> >
> > Is the following code (copied from the user-docs) thread safe?
> >
> > import org.apache.cxf.endpoint.Client;
> >   import org.apache.cxf.frontend.ClientProxy;
> >   import org.apache.cxf.transport.http.HTTPConduit;
> >   import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
> >   ...
> >
> >   URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
> >   SOAPService service = new SOAPService(wsdl, serviceName);
> >   Greeter greeter = service.getPort(portName, Greeter.class);
> >
> >   // Okay, are you sick of configuration files ?
> >   // This will show you how to configure the http conduit dynamically
> >   Client client = ClientProxy.getClient(greeter);
> >   HTTPConduit http = (HTTPConduit) client.getConduit();
> >
> >   HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
> >
> >   httpClientPolicy.setConnectionTimeout(36000);
> >   httpClientPolicy.setAllowChunking(false);
> >   httpClientPolicy.setReceiveTimeout(32000);
> >
> >   http.setClient(httpClientPolicy);
> >
> >   ...
> >   greeter.sayHi("Hello");
> >
> >
> > Not that I have found any issue with it, but I want to
> > be sure that it's intended to be.
> >
> > The requirement is to invoke multiple Endpoints in parallel where
> > every EP has its own configuration (SSL-Client-Authentication,
> > timeouts, url, expect-100-continue, etc). The whole configuration
> > must be made at runtime, because the EP aren't known at startup time.
> >
> > Thank you!
> >
> > Marc
> 
> -- 
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog


-- 

itServe AG
Marc Giger
Länggassstrasse 26
3000 Bern 9
Tel.: +41 31 305 16 16
Fax:  +41 31 305 16 17

Direkt +41 31 305 43 27
Email marc.giger@itserve.ch

http://www.itserve.ch

Re: HttpConduit thread safety

Posted by Daniel Kulp <dk...@apache.org>.
Basically, if you set all the conduit properties ONCE up front and also don't 
use http sessions and all use either http or https, but not both, then you can 
do this.   Do:

((BindingProvider)proxy).getRequestContext().put("thread.local.request.context", 
"true");

as part of the setup.   That will make the RequestContext thread local.  Then, 
each thread can do:


((BindingProvider)proxy).getRequestContext().put(
    BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
    "http://my.url.to.somplace");

and that will be fine.

If you need to setup unique valued per request other than just the URL, then I 
suggest using a pool of client proxies.   Create a few and pool them.

Dan




On Fri February 6 2009 1:17:55 pm Marc Giger wrote:
> Hi,
>
> Is the following code (copied from the user-docs) thread safe?
>
> import org.apache.cxf.endpoint.Client;
>   import org.apache.cxf.frontend.ClientProxy;
>   import org.apache.cxf.transport.http.HTTPConduit;
>   import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
>   ...
>
>   URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
>   SOAPService service = new SOAPService(wsdl, serviceName);
>   Greeter greeter = service.getPort(portName, Greeter.class);
>
>   // Okay, are you sick of configuration files ?
>   // This will show you how to configure the http conduit dynamically
>   Client client = ClientProxy.getClient(greeter);
>   HTTPConduit http = (HTTPConduit) client.getConduit();
>
>   HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
>
>   httpClientPolicy.setConnectionTimeout(36000);
>   httpClientPolicy.setAllowChunking(false);
>   httpClientPolicy.setReceiveTimeout(32000);
>
>   http.setClient(httpClientPolicy);
>
>   ...
>   greeter.sayHi("Hello");
>
>
> Not that I have found any issue with it, but I want to
> be sure that it's intended to be.
>
> The requirement is to invoke multiple Endpoints in parallel where
> every EP has its own configuration (SSL-Client-Authentication,
> timeouts, url, expect-100-continue, etc). The whole configuration
> must be made at runtime, because the EP aren't known at startup time.
>
> Thank you!
>
> Marc

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

Re: HttpConduit thread safety

Posted by Jaroslav Libak <ja...@seznam.cz>.
Hello

I have done some investigation a while ago, and found out the HTTPConduit object
is the same for all clients. I avoid changing conduit configuration on the fly.
Switching between SSL/non SSL connection factory is built in HTTPConduit via
custom patch posted in this mailinglist.

Just have a look at http.setClient(httpClientPolicy); internal code, if it uses
thread local anywhere. If not then its not thread safe.

Jaro

Marc Giger schrieb:
> Hi,
> 
> Is the following code (copied from the user-docs) thread safe?
> 
> import org.apache.cxf.endpoint.Client;
>   import org.apache.cxf.frontend.ClientProxy;
>   import org.apache.cxf.transport.http.HTTPConduit;
>   import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
>   ...
> 
>   URL wsdl = getClass().getResource("wsdl/greeting.wsdl");
>   SOAPService service = new SOAPService(wsdl, serviceName);
>   Greeter greeter = service.getPort(portName, Greeter.class);
> 
>   // Okay, are you sick of configuration files ?
>   // This will show you how to configure the http conduit dynamically
>   Client client = ClientProxy.getClient(greeter);
>   HTTPConduit http = (HTTPConduit) client.getConduit();
> 
>   HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
> 
>   httpClientPolicy.setConnectionTimeout(36000);
>   httpClientPolicy.setAllowChunking(false);
>   httpClientPolicy.setReceiveTimeout(32000);
> 
>   http.setClient(httpClientPolicy);
> 
>   ...
>   greeter.sayHi("Hello");
> 
> 
> Not that I have found any issue with it, but I want to
> be sure that it's intended to be.
> 
> The requirement is to invoke multiple Endpoints in parallel where
> every EP has its own configuration (SSL-Client-Authentication,
> timeouts, url, expect-100-continue, etc). The whole configuration
> must be made at runtime, because the EP aren't known at startup time.
> 
> Thank you!
> 
> Marc
>