You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2007/05/07 11:07:47 UTC

svn commit: r535794 - in /jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client: AbstractHttpClient.java DefaultClientRequestDirector.java DefaultHttpClient.java

Author: olegk
Date: Mon May  7 02:07:44 2007
New Revision: 535794

URL: http://svn.apache.org/viewvc?view=rev&rev=535794
Log:
Implemented HTTP request retry handling

Modified:
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java?view=diff&rev=535794&r1=535793&r2=535794
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/AbstractHttpClient.java Mon May  7 02:07:44 2007
@@ -44,6 +44,7 @@
 import org.apache.http.auth.AuthSchemeRegistry;
 import org.apache.http.client.ClientRequestDirector;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.HttpState;
 import org.apache.http.client.RoutedRequest;
 import org.apache.http.conn.ClientConnectionManager;
@@ -93,6 +94,9 @@
     /** The HTTP processor. */
     private BasicHttpProcessor httpProcessor;
 
+    /** The request retry handler. */
+    private HttpRequestRetryHandler retryHandler;
+
     /** The default HTTP state. */
     private HttpState defaultState;
 
@@ -131,6 +135,9 @@
     protected abstract BasicHttpProcessor createHttpProcessor();
 
     
+    protected abstract HttpRequestRetryHandler createHttpRequestRetryHandler();
+
+    
     protected abstract HttpState createHttpState();
     
     
@@ -209,6 +216,19 @@
     }
 
 
+    public synchronized final HttpRequestRetryHandler getHttpRequestRetryHandler() {
+        if (retryHandler == null) {
+            retryHandler = createHttpRequestRetryHandler();
+        }
+        return retryHandler;
+    }
+
+
+    public synchronized void setHttpRequestRetryHandler(final HttpRequestRetryHandler retryHandler) {
+        this.retryHandler = retryHandler;
+    }
+
+
     public synchronized final HttpState getState() {
         if (defaultState == null) {
             defaultState = createHttpState();
@@ -367,6 +387,7 @@
                     getConnectionManager(),
                     getConnectionReuseStrategy(),
                     getHttpProcessor().copy(),
+                    getHttpRequestRetryHandler(),
                     getParams());
         }
 

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java?view=diff&rev=535794&r1=535793&r2=535794
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java Mon May  7 02:07:44 2007
@@ -33,6 +33,8 @@
 
 import java.io.IOException;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.http.ConnectionReuseStrategy;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpException;
@@ -40,22 +42,23 @@
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpVersion;
 import org.apache.http.client.ClientRequestDirector;
+import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.RoutedRequest;
 import org.apache.http.client.methods.AbortableHttpRequest;
+import org.apache.http.client.params.HttpClientParams;
 import org.apache.http.conn.BasicManagedEntity;
 import org.apache.http.conn.ClientConnectionManager;
 import org.apache.http.conn.HttpRoute;
 import org.apache.http.conn.ManagedClientConnection;
 import org.apache.http.conn.RouteDirector;
 import org.apache.http.message.BasicHttpRequest;
+import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.protocol.HttpExecutionContext;
 import org.apache.http.protocol.HttpProcessor;
 import org.apache.http.protocol.HttpRequestExecutor;
 
-
-
 /**
  * Default implementation of a client-side request director.
  * <br/>
@@ -72,6 +75,8 @@
 public class DefaultClientRequestDirector
     implements ClientRequestDirector {
 
+    private static final Log LOG = LogFactory.getLog(DefaultClientRequestDirector.class);
+    
     /** The connection manager. */
     protected final ClientConnectionManager connManager;
 
@@ -84,19 +89,45 @@
     /** The HTTP protocol processor. */
     protected final HttpProcessor httpProcessor;
     
+    /** The request retry handler. */
+    protected final HttpRequestRetryHandler retryHandler;
+    
+    /** The HTTP parameters. */
+    protected final HttpParams params;
+    
     /** The currently allocated connection. */
     protected ManagedClientConnection managedConn;
 
 
-    public DefaultClientRequestDirector(ClientConnectionManager conman,
-                                        ConnectionReuseStrategy reustrat,
-                                        HttpProcessor httpProcessor,
-                                        HttpParams params) {
+    public DefaultClientRequestDirector(
+            final ClientConnectionManager conman,
+            final ConnectionReuseStrategy reustrat,
+            final HttpProcessor httpProcessor,
+            final HttpRequestRetryHandler retryHandler,
+            final HttpParams params) {
 
+        if (conman == null) {
+            throw new IllegalArgumentException("Client connection manager may not be null");
+        }
+        if (reustrat == null) {
+            throw new IllegalArgumentException("Connection reuse strategy may not be null");
+        }
+        if (httpProcessor == null) {
+            throw new IllegalArgumentException("HTTP protocol processor may not be null");
+        }
+        if (retryHandler == null) {
+            throw new IllegalArgumentException("HTTP request retry handler may not be null");
+        }
+        if (params == null) {
+            throw new IllegalArgumentException("HTTP parameters may not be null");
+        }
         this.connManager   = conman;
         this.reuseStrategy = reustrat;
-        this.requestExec   = new HttpRequestExecutor(params);
         this.httpProcessor = httpProcessor;
+        this.retryHandler  = retryHandler;
+        this.params        = params;
+        this.requestExec   = new HttpRequestExecutor(params);
+
         this.managedConn   = null;
 
         //@@@ authentication?
@@ -126,6 +157,7 @@
         //@@@ if redirects are followed, or for the whole sequence?
 
         try {
+            int execCount = 0;
             while (!done) {
                 allocateConnection(roureq.getRoute());
                 establishRoute(roureq.getRoute(), context);
@@ -145,7 +177,40 @@
                 context.setAttribute(HttpExecutionContext.HTTP_REQUEST,
                         prepreq);
                 
-                response = requestExec.execute(prepreq, managedConn, context);
+                execCount++;
+                try {
+                    if (LOG.isDebugEnabled()) {
+                        LOG.debug("Attempt number " + execCount + " to execute request");
+                    }
+
+                    if (HttpConnectionParams.isStaleCheckingEnabled(params)) {
+                        // validate connection
+                        LOG.debug("Stale connection check");
+                        if (managedConn.isStale()) {
+                            LOG.debug("Stale connection detected");
+                            managedConn.close();
+                        }
+                    }
+                    
+                    response = requestExec.execute(prepreq, managedConn, context);
+                    
+                } catch (IOException ex) {
+                    LOG.debug("Closing the connection.");
+                    managedConn.close();
+                    if (retryHandler.retryRequest(ex, execCount, context)) {
+                        if (LOG.isInfoEnabled()) {
+                            LOG.info("I/O exception ("+ ex.getClass().getName() + 
+                                    ") caught when processing request: "
+                                    + ex.getMessage());
+                        }
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug(ex.getMessage(), ex);
+                        }
+                        LOG.info("Retrying request");
+                        continue;
+                    }
+                    throw ex;
+                }
 
                 finalizeResponse(response, context);
                 
@@ -184,15 +249,16 @@
      * @throws HttpException    in case of a problem
      */
     protected void allocateConnection(HttpRoute route)
-        throws HttpException {
+        throws HttpException, IOException {
 
         // we assume that the connection would have been released
         // if it was not appropriate for the route of the followup
-        if (managedConn != null)
+        if (managedConn != null) {
             return;
+        }
 
-        //@@@ use connection manager timeout
-        managedConn = connManager.getConnection(route);
+        long timeout = HttpClientParams.getConnectionManagerTimeout(params);
+        managedConn = connManager.getConnection(route, timeout);
 
     } // allocateConnection
 
@@ -439,9 +505,7 @@
         if (success) {
             // Not in exception handling, there probably is a response.
             // The connection is in or can be brought to a re-usable state.
-            boolean reuse = false;
-            if (reuseStrategy != null)
-                reuse = reuseStrategy.keepAlive(response, context);
+            boolean reuse = reuseStrategy.keepAlive(response, context);
 
             // check for entity, release connection if possible
             if ((response == null) || (response.getEntity() == null) ||
@@ -462,9 +526,10 @@
             //@@@ for now, just shut it down
             try {
                 mcc.abortConnection();
-            } catch (IOException ignore) {
-                // can't allow exception while handling exception
-                //@@@ log as debug or warning?
+            } catch (IOException ex) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(ex.getMessage(), ex);
+                }
             }
         }
     } // cleanupConnection

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java?view=diff&rev=535794&r1=535793&r2=535794
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultHttpClient.java Mon May  7 02:07:44 2007
@@ -37,6 +37,7 @@
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpVersion;
 import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.HttpState;
 import org.apache.http.client.RoutedRequest;
 import org.apache.http.client.params.AuthPolicy;
@@ -202,6 +203,11 @@
         httpproc.addInterceptor(new RequestAddCookies());
         httpproc.addInterceptor(new ResponseProcessCookies());
         return httpproc;
+    }
+
+
+    protected HttpRequestRetryHandler createHttpRequestRetryHandler() {
+        return new DefaultHttpRequestRetryHandler();
     }