You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by gd...@apache.org on 2009/07/02 21:41:20 UTC

svn commit: r790721 - in /webservices/axis2/branches/java/1_5/modules: integration/test/org/apache/axis2/async/ integration/test/org/apache/axis2/engine/ kernel/src/org/apache/axis2/description/ kernel/src/org/apache/axis2/transport/ kernel/src/org/apa...

Author: gdaniels
Date: Thu Jul  2 19:41:19 2009
New Revision: 790721

URL: http://svn.apache.org/viewvc?rev=790721&view=rev
Log:
Hopefully a real fix for AXIS2-935, 3883, 2391, etc...

A lot of these problems were caused by not really enabling reuse of the HTPP connection due to unnecessary recreations of HTTPClients and MultithreadedHttpConnectionManagers.  So the first major change here is in AbstractHTTPSender.getHttpClient(), which now *always* creates and shares a single MultithreadedHttpConnectionManager, and indeed a single HTTPClient, across each ConfigurationContext (i.e. one for the server side replying to dual-channel messages, one for the client side).  This seems to actually allow keep-alive connections, where I wasn't easily able to produce them previously.

Also, there is now NO NEED for the REUSE_HTTP_CLIENT option, since it's done automatically.

Then in HTTPSender.sendViaPost(), we now check to see if we're using a separate listener (i.e. dual-channel).  If so, we always switch on connection auto-release.  This prevents pool starvation.  If we're single-channel, the connection gets cleaned up later as a result of ServiceClient.transportCleanup().

In CommonsHTTPTransportSender.writeMessageWithCommons(), we now switch on AUTO_RELEASE_CONNECTION if the operation is InOut - in other words, if we're here because we're sending a response on a separate channel, we'll auto-release the connection when we're done.

Need to test these changes with Sandesha, and I'll check in a test harness that I built which fails very quickly before these changes, but happily sends over 100,000 requests after them.

Note that this is sort of a patch solution which we can roll out with 1.5.1 - we should do some more thinking about the "real" solution, which I think involves holding on to the HTTPMethod until Axiom lets us know (via a callback mechanism) that it has finished reading the stream.

Modified:
    webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/async/AsyncService2Test.java
    webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/engine/MultipleInvocationTest.java
    webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java
    webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/transport/TransportUtils.java
    webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/util/CallbackReceiver.java
    webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/AbstractHTTPSender.java
    webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/CommonsHTTPTransportSender.java
    webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPSender.java
    webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPWorker.java

Modified: webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/async/AsyncService2Test.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/async/AsyncService2Test.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/async/AsyncService2Test.java (original)
+++ webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/async/AsyncService2Test.java Thu Jul  2 19:41:19 2009
@@ -30,8 +30,7 @@
 import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.client.Options;
 import org.apache.axis2.client.ServiceClient;
-import org.apache.axis2.client.async.AsyncResult;
-import org.apache.axis2.client.async.Callback;
+import org.apache.axis2.client.async.AxisCallback;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.context.ServiceContext;
@@ -39,19 +38,18 @@
 import org.apache.axis2.engine.AxisConfiguration;
 import org.apache.axis2.engine.Echo;
 import org.apache.axis2.engine.util.TestConstants;
-import org.apache.axis2.integration.TestingUtils;
 import org.apache.axis2.integration.UtilServer;
 import org.apache.axis2.integration.UtilServerBasedTestCase;
 import org.apache.axis2.transport.http.HTTPConstants;
 import org.apache.axis2.util.Utils;
 import org.apache.axis2.util.threadpool.ThreadPool;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
-import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import javax.xml.namespace.QName;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 public class AsyncService2Test extends UtilServerBasedTestCase implements TestConstants {
 
@@ -61,13 +59,18 @@
     EndpointReference targetEPR = new EndpointReference(
             "http://127.0.0.1:" + (UtilServer.TESTING_PORT)
 //            "http://127.0.0.1:" + 5556
-                    + "/axis2/services/EchoXMLService/echoOMElement");
++ "/axis2/services/EchoXMLService/echoOMElement");
 
     protected AxisConfiguration engineRegistry;
     protected MessageContext mc;
     protected ServiceContext serviceContext;
     protected AxisService service;
-    private boolean finish = false;
+    Exception error;
+    // A (synchronized) place to hold the responses
+    final Map<String, String> responses =
+            Collections.synchronizedMap(new HashMap<String, String>());
+
+    protected final String PREFIX_TEXT = "Request number ";
 
     public static Test suite() {
         return getTestSetup(new TestSuite(AsyncService2Test.class));
@@ -87,10 +90,8 @@
     }
 
     private static final int MILLISECONDS = 1000;
-    private static final Integer TIMEOUT = new Integer(
-            200 * MILLISECONDS);
-    private int counter = 0;
-    private static final int MAX_REQUESTS = 10;
+    private static final Integer TIMEOUT = 200 * MILLISECONDS;
+    private static final int MAX_REQUESTS = 9;
 
     public void testEchoXMLCompleteASyncWithLimitedNumberOfConnections() throws Exception {
         AxisService service =
@@ -98,26 +99,10 @@
                                                    Echo.class.getName(),
                                                    operationName);
 
-        MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
-        HttpConnectionManagerParams connectionManagerParams = new HttpConnectionManagerParams();
-        // Maximum one socket connection to a specific host
-        connectionManagerParams.setDefaultMaxConnectionsPerHost(1);
-        connectionManagerParams.setTcpNoDelay(true);
-        connectionManagerParams.setStaleCheckingEnabled(true);
-        connectionManagerParams.setLinger(0);
-        connectionManager.setParams(connectionManagerParams);
-
-        HttpClient httpClient = new HttpClient(connectionManager);
-
         ConfigurationContext configcontext = UtilServer.createClientConfigurationContext();
 
         // Use max of 3 threads for the async thread pool
         configcontext.setThreadPool(new ThreadPool(1, 3));
-        configcontext.setProperty(HTTPConstants.REUSE_HTTP_CLIENT,
-                Boolean.TRUE);
-        configcontext.setProperty(HTTPConstants.CACHED_HTTP_CLIENT,
-                httpClient);
-
 
         OMFactory fac = OMAbstractFactory.getOMFactory();
         ServiceClient sender = null;
@@ -133,24 +118,49 @@
             options.setProperty(HTTPConstants.SO_TIMEOUT, TIMEOUT);
             options.setProperty(HTTPConstants.CONNECTION_TIMEOUT, TIMEOUT);
             options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT,
-                    Boolean.TRUE);
+                                Boolean.TRUE);
             options.setProperty(HTTPConstants.AUTO_RELEASE_CONNECTION,
-                    Boolean.TRUE);
+                                Boolean.TRUE);
+//            options.setProperty(ServiceClient.AUTO_OPERATION_CLEANUP, true);
 
+            AxisCallback callback = new AxisCallback() {
+
+                public void onMessage(MessageContext msgContext) {
+                    final OMElement responseElement =
+                            msgContext.getEnvelope().getBody().getFirstElement();
+                    assertNotNull(responseElement);
+                    String textValue = responseElement.getFirstElement().getText();
+                    assertTrue(textValue.startsWith(PREFIX_TEXT));
+                    String whichOne = textValue.substring(PREFIX_TEXT.length());
+                    assertNull(responses.get(whichOne));
+                    responses.put(whichOne, textValue);
+                    synchronized (responses) {
+                        if (responses.size() == MAX_REQUESTS) {
+                            // All done!
+                            responses.notifyAll();
+                        }
+                    }
+                }
+
+                public void onFault(MessageContext msgContext) {
+                    // Whoops.
+                    synchronized (responses) {
+                        if (error != null) return; // Only take first error
+                        error = msgContext.getEnvelope().getBody().getFault().getException();
+                        responses.notify();
+                    }
+                }
 
-            Callback callback = new Callback() {
-                public void onComplete(AsyncResult result) {
-                    TestingUtils.compareWithCreatedOMElement(
-                            result.getResponseEnvelope().getBody()
-                                    .getFirstElement());
-                    System.out.println("result = " + result.getResponseEnvelope().getBody()
-                            .getFirstElement());
-                    counter++;
+                public void onComplete() {
                 }
 
                 public void onError(Exception e) {
                     log.info(e.getMessage());
-                    counter++;
+                    synchronized (responses) {
+                        if (error != null) return; // Only take first error
+                        error = e;
+                        responses.notify();
+                    }
                 }
             };
 
@@ -160,20 +170,19 @@
                 OMNamespace omNs = fac.createOMNamespace("http://localhost/my", "my");
                 OMElement method = fac.createOMElement("echoOMElement", omNs);
                 OMElement value = fac.createOMElement("myValue", omNs);
-                value.setText("Isaac Asimov, The Foundation Trilogy");
+                value.setText(PREFIX_TEXT + i);
                 method.addChild(value);
                 sender.sendReceiveNonBlocking(operationName, method, callback);
-                System.out.println("sent the request # : " + i);
+                log.trace("sent the request # : " + i);
             }
-            System.out.print("waiting");
-            int index = 0;
-            while (counter < MAX_REQUESTS) {
-                System.out.print('.');
-                Thread.sleep(1000);
-                index++;
-                if (index > 60) {
-                    throw new AxisFault(
-                            "Server was shutdown as the async response take too long to complete");
+            log.trace("waiting (max 1min)");
+            synchronized (responses) {
+                responses.wait(60 * 1000);
+                // Someone kicked us, so either we have a problem
+                if (responses.size() < MAX_REQUESTS) {
+                    if (error != null)
+                        throw error;
+                    throw new AxisFault("Timeout, did not receive all responses.");
                 }
             }
         } finally {

Modified: webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/engine/MultipleInvocationTest.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/engine/MultipleInvocationTest.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/engine/MultipleInvocationTest.java (original)
+++ webservices/axis2/branches/java/1_5/modules/integration/test/org/apache/axis2/engine/MultipleInvocationTest.java Thu Jul  2 19:41:19 2009
@@ -78,6 +78,7 @@
         options.setTo(targetEPR);
         options.setSoapVersionURI(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
         options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
+        options.setCallTransportCleanup(true);
 
         ConfigurationContext configContext =
                 ConfigurationContextFactory.createConfigurationContextFromFileSystem(

Modified: webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java (original)
+++ webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java Thu Jul  2 19:41:19 2009
@@ -520,6 +520,8 @@
             // method. Have to build the whole envelope including the
             // attachments at this stage. Data might get lost if the input
             // stream gets closed before building the whole envelope.
+
+            // TODO: Shouldn't need to do this - need to hook up stream closure to Axiom completion
             this.envelope = msgContext.getEnvelope();
             this.envelope.buildWithAttachments();
         }
@@ -530,7 +532,7 @@
          * @param msgContext the MessageContext containing the fault.
          */
         public void onFault(MessageContext msgContext) {
-           error =Utils.getInboundFaultFromMessageContext(msgContext);
+           error = Utils.getInboundFaultFromMessageContext(msgContext);
         }
 
         /**

Modified: webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/transport/TransportUtils.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/transport/TransportUtils.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/transport/TransportUtils.java (original)
+++ webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/transport/TransportUtils.java Thu Jul  2 19:41:19 2009
@@ -76,6 +76,11 @@
      */
     public static SOAPEnvelope createSOAPMessage(MessageContext msgContext,
                                                  boolean detach) throws AxisFault {
+//        final SOAPEnvelope envelope = msgContext.getEnvelope();
+//        if (envelope != null) {
+//            if (envelope.isComplete())
+//                return envelope;
+//        }
         try {
             InputStream inStream = (InputStream) msgContext
                     .getProperty(MessageContext.TRANSPORT_IN);

Modified: webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/util/CallbackReceiver.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/util/CallbackReceiver.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/util/CallbackReceiver.java (original)
+++ webservices/axis2/branches/java/1_5/modules/kernel/src/org/apache/axis2/util/CallbackReceiver.java Thu Jul  2 19:41:19 2009
@@ -66,7 +66,7 @@
      * @param callback The callback object.
      * @throws AxisFault If the message id was a duplicate.
      */
-    private final void putIfAbsent(String msgID, Object callback) throws AxisFault {
+    private void putIfAbsent(String msgID, Object callback) throws AxisFault {
     	if (callbackStore.putIfAbsent(msgID, callback) == null) {
     		if (log.isDebugEnabled()) {
                 log.debug("CallbackReceiver: add callback " + msgID + ", " + callback + " ," + this);

Modified: webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/AbstractHTTPSender.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/AbstractHTTPSender.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/AbstractHTTPSender.java (original)
+++ webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/AbstractHTTPSender.java Thu Jul  2 19:41:19 2009
@@ -26,6 +26,7 @@
 import org.apache.axis2.Constants;
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.context.OperationContext;
+import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.description.TransportOutDescription;
 import org.apache.axis2.i18n.Messages;
 import org.apache.axis2.transport.MessageFormatter;
@@ -48,6 +49,7 @@
 import org.apache.commons.httpclient.auth.AuthPolicy;
 import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
 import org.apache.commons.httpclient.protocol.Protocol;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -477,51 +479,36 @@
 
     protected HttpClient getHttpClient(MessageContext msgContext) {
         HttpClient httpClient;
-        Object reuse = msgContext.getOptions().getProperty(HTTPConstants.REUSE_HTTP_CLIENT);
-        if (reuse == null) {
-            reuse = msgContext.getConfigurationContext().getProperty(HTTPConstants.REUSE_HTTP_CLIENT);
-        }
-        if (reuse != null && JavaUtils.isTrueExplicitly(reuse)) {
-            httpClient = (HttpClient) msgContext.getOptions().getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
+        final ConfigurationContext configContext = msgContext.getConfigurationContext();
+        synchronized (lock) {
+            httpClient = (HttpClient) configContext.getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
             if (httpClient == null) {
-                httpClient = (HttpClient) msgContext.getConfigurationContext()
-                        .getProperty(HTTPConstants.CACHED_HTTP_CLIENT);
-            }
-            if (httpClient != null)
-                return httpClient;
-            MultiThreadedHttpConnectionManager connectionManager =
-                new MultiThreadedHttpConnectionManager();
-            httpClient = new HttpClient(connectionManager);
-            msgContext.getConfigurationContext()
-                .setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
-        } else {
-            HttpConnectionManager connManager =
-                    (HttpConnectionManager) msgContext.getProperty(
-                            HTTPConstants.MULTITHREAD_HTTP_CONNECTION_MANAGER);
-            if (connManager == null) {
-                connManager =
-                        (HttpConnectionManager) msgContext.getProperty(
-                                HTTPConstants.MUTTITHREAD_HTTP_CONNECTION_MANAGER);
-            }
-            if(connManager != null){
-                httpClient = new HttpClient(connManager);
-            } else {
-                //Multi threaded http connection manager has set as the default 
-                connManager = new MultiThreadedHttpConnectionManager();
+                log.trace("Making new ConnectionManager");
+                HttpConnectionManager connManager = new MultiThreadedHttpConnectionManager();
+
+                // In case we need to set any params, do it here, but for now use defaults.
+//                HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+//                params.setMaxConnectionsPerHost(HostConfiguration.ANY_HOST_CONFIGURATION, 200);
+//                etc...
+//                connManager.setParams(params);
+
                 httpClient = new HttpClient(connManager);
+                configContext.setProperty(HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
             }
-        }
 
-        // Get the timeout values set in the runtime
-        initializeTimeouts(msgContext, httpClient);
+            // Get the timeout values set in the runtime
+            initializeTimeouts(msgContext, httpClient);
+        }
         return httpClient;
     }
 
+    static final Object lock = new Object();
     protected void executeMethod(HttpClient httpClient, MessageContext msgContext, URL url,
                                  HttpMethod method) throws IOException {
         HostConfiguration config = this.getHostConfiguration(httpClient, msgContext, url);
 
-        msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
+        if (!msgContext.getOptions().isUseSeparateListener())
+            msgContext.setProperty(HTTPConstants.HTTP_METHOD, method);
 
         // set the custom headers, if available
         addCustomHeaders(method, msgContext);

Modified: webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/CommonsHTTPTransportSender.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/CommonsHTTPTransportSender.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/CommonsHTTPTransportSender.java (original)
+++ webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/CommonsHTTPTransportSender.java Thu Jul  2 19:41:19 2009
@@ -25,8 +25,10 @@
 import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.context.OperationContext;
 import org.apache.axis2.description.Parameter;
 import org.apache.axis2.description.TransportOutDescription;
+import org.apache.axis2.description.InOutAxisOperation;
 import org.apache.axis2.handlers.AbstractHandler;
 import org.apache.axis2.transport.MessageFormatter;
 import org.apache.axis2.transport.OutTransportInfo;
@@ -75,11 +77,12 @@
     int connectionTimeout = HTTPConstants.DEFAULT_CONNECTION_TIMEOUT;
 
     public void cleanup(MessageContext msgContext) throws AxisFault {
-        HttpMethod httpMethod = (HttpMethod) msgContext
-                .getProperty(HTTPConstants.HTTP_METHOD);
+        HttpMethod httpMethod = (HttpMethod) msgContext.getProperty(HTTPConstants.HTTP_METHOD);
 
         if (httpMethod != null) {
+            // TODO : Don't do this if we're not on the right thread! Can we confirm?
             httpMethod.releaseConnection();
+            msgContext.removeProperty(HTTPConstants.HTTP_METHOD); // guard against multiple calls
         }
     }
 
@@ -386,6 +389,14 @@
             sender.setHttpVersion(httpVersion);
             sender.setFormat(format);
 
+            final OperationContext opContext = messageContext.getOperationContext();
+            if (opContext.getAxisOperation() instanceof InOutAxisOperation) {
+                // TODO: Kludge to make sure async reply connections get cleaned up. Fix for real?
+
+                // If we're using this sender to send a dual-channel reply, we don't care about
+                // reading the response for now, so make sure we clean up the HTTPMethod.
+                messageContext.setProperty(HTTPConstants.AUTO_RELEASE_CONNECTION, true);
+            }
             sender.send(messageContext, url, findSOAPAction(messageContext));
         } catch (MalformedURLException e) {
             log.debug(e);

Modified: webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPSender.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPSender.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPSender.java (original)
+++ webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPSender.java Thu Jul  2 19:41:19 2009
@@ -111,6 +111,7 @@
 
     private void cleanup(MessageContext msgContext, HttpMethod method) {
         if (msgContext.isPropertyTrue(HTTPConstants.AUTO_RELEASE_CONNECTION)) {
+            log.trace("AutoReleasing " + method);
             method.releaseConnection();
         }
     }
@@ -165,6 +166,9 @@
 */
 
         PostMethod postMethod = new PostMethod();
+        if (log.isTraceEnabled()) {
+            log.trace(Thread.currentThread() + " PostMethod " + postMethod + " / " + httpClient);
+        }
         MessageFormatter messageFormatter =
                 populateCommonProperties(msgContext, url, postMethod, httpClient, soapActionString);
 
@@ -192,6 +196,11 @@
             log.info("Unable to sendViaPost to url[" + url + "]", e);
             throw AxisFault.makeFault(e);
         } finally {
+            // If we're a dual-channel request, just auto-release the connection so it gets
+            // cleaned up and avoids starvation problems.
+            // TODO: Confirm this is OK with WS-RM, fix if not!
+            if (msgContext.getOptions().isUseSeparateListener())
+                msgContext.setProperty(HTTPConstants.AUTO_RELEASE_CONNECTION, true);
             cleanup(msgContext, postMethod);
         }
     }
@@ -259,8 +268,8 @@
      */
     private void handleResponse(MessageContext msgContext,
                                 HttpMethodBase method) throws IOException {
-
         int statusCode = method.getStatusCode();
+        log.trace("Handling response - " + statusCode);
         if (statusCode == HttpStatus.SC_OK) {
             processResponse(method, msgContext);
         } else if (statusCode == HttpStatus.SC_ACCEPTED) {

Modified: webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPWorker.java
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPWorker.java?rev=790721&r1=790720&r2=790721&view=diff
==============================================================================
--- webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPWorker.java (original)
+++ webservices/axis2/branches/java/1_5/modules/transport/http/src/org/apache/axis2/transport/http/HTTPWorker.java Thu Jul  2 19:41:19 2009
@@ -59,7 +59,6 @@
             final AxisHttpRequest request,
             final AxisHttpResponse response,
             final MessageContext msgContext) throws HttpException, IOException {
-
         ConfigurationContext configurationContext = msgContext.getConfigurationContext();
         final String servicePath = configurationContext.getServiceContextPath();
         final String contextPath =