Q: How do I configure the Axis client to pool connections with Apache Jakarta Commons-HttpClient?
A: You'll need to add the Jakarta Commons Http Client jar in your CLASSPATH or WEB-INF/lib (for web applications).
Note that if you are building Axis from source, you will also need to put commons-httpclient jar in Axis dependencies directory so that the CommonsHTTPSender class is built.
Next, you'll need to install a client-config.wsdd (sample here) that tells Axis to use CommonsHTTPSender instead of the standard HTTPSender when sending/receiving messages via HTTP. Here's an example:
<?xml version="1.0" encoding="UTF-8"?> <deployment name="commonsHTTPConfig" xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <!-- use CommonsHTTPSender instead of the default HTTPSender --> <transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender" /> <transport name="local" pivot = "java:org.apache.axis.transport.local.LocalSender" /> <transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender" /> </deployment>
Finally, you will almost certainly want to adjust the default settings for the connection pool (pool size, timeout, and so forth). Those are defined in the org.apache.axis.components.net.CommonsHTTPClientProperties interface and can be set using the AxisProperties API that is used by all of the pluggable components in Axis. You can also provide your own implementation of the interface if you need to do some special adjustments to those settings. For that you would use the commons-discovery API. (Note this requires Axis 1.2).
Sample of configuration with AxisProperties :
// "Total Connections" Pool size AxisProperties.setProperty( DefaultCommonsHTTPClientProperties.MAXIMUM_TOTAL_CONNECTIONS_PROPERTY_KEY, maxTotalConnections); // "Connections per host" pool size AxisProperties.setProperty( DefaultCommonsHTTPClientProperties.MAXIMUM_CONNECTIONS_PER_HOST_PROPERTY_KEY, maxConnectionsPerHost); // max duration to wait for a connection from the pool AxisProperties.setProperty( DefaultCommonsHTTPClientProperties.CONNECTION_POOL_TIMEOUT_KEY, connectionPoolTimeout); // Timeout to establish connection in millis AxisProperties.setProperty( DefaultCommonsHTTPClientProperties.CONNECTION_DEFAULT_CONNECTION_TIMEOUT_KEY, connectionTimeout); // Timeout "waiting for data" (read timeout) AxisProperties.setProperty( DefaultCommonsHTTPClientProperties.CONNECTION_DEFAULT_SO_TIMEOUT_KEY, soTimeout); // Instantiate the ServiceLocator only ONCE !!! HelloWorldServiceLocator helloWorldServiceLocator = new HelloWorldServiceLocator(); ... // reuse the same ServiceLocator to instantiate all your bindings !! HelloWorldBindingStub bindingUserTic = (HelloWorldBindingStub) helloWorldServiceLocator .gethelloWorldBinding();
ServiceLocator MUST be instantiated only once. This single instance must be used to instantiate all the stubs.
This requirement is due to the fact that it is the ServiceLocator that in in charge of pooling the http connections : it holds the MultiThreadedHttpConnectionManager via the reference to the CommonsHTTPSender.
Stubs are NOT thread safe, in most cases, one stub can be instantiated for each call.
- In very special cases (very complex WSDLs, ...), the cost of instantiating Stubs will worth pooling them.
As stated before, Stubs are reusable. This is the common scenario to maintain a session (see FrontPage/Axis/SessionSupport). It can also be used to gain performances (with a pool) but it should only be efficient in very special cases (see above).
If you do not want to use file-based configuration, you can alternatively configure it programatically. Here is an example (for only conifiguring CommonsHTTPSender):
... // get a modifiable configuration and instantiate it with a basic client configuration SimpleProvider config = new SimpleProvider(new BasicClientConfig()); // create a new simple targeted chain SimpleTargetedChain c = new SimpleTargetedChain(new CommonsHTTPSender()); // and add it to the configuration config.deployTransport("http", c); ... // instantiate the service locator with the configuration HelloWorldServiceLocator helloWorldServiceLocator = new HelloWorldServiceLocator(config);
Take attention to the notes above concerning the instantiation of the service locator.
Q: Can I share the same http connections (ie MultiThreadedHttpConnectionManager) between Web Services ?
In Axis 1.3, the MultiThreadedHttpConnectionManager is an internal of the ServiceLocator and thus, it is not possible to share the same MultiThreadedHttpConnectionManager between several ServiceLocators (i.e. between several web services).
Q: How do I enable Http Keep Alive with CommonsHTTPSender ?
Http keep-alive is enabled by default with CommonsHTTPSender : there is no special configuration nor coding instruction to add.
This is due to the fact that, by default, CommonsHTTPSender uses HTTP 1.1 and HTTP 1.1 specification states that, by default, http connections are persistent (i.e. use keep-alive).
Extract from RFC 2616 : HTTP/1.1 - Persistent Connection :
An HTTP/1.1 server MAY assume that a HTTP/1.1 client intends to maintain a persistent connection unless a Connection header including the connection-token "close" was sent in the request
CommonsHTTPSender relies on the MultiThreadedHttpConnectionManager of Jakarta Commons Http Client. MultiThreadedHttpConnectionManager is documented here