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 2011/08/16 17:09:35 UTC

svn commit: r1158314 - in /httpcomponents/httpclient/trunk/httpclient/src: main/java/org/apache/http/client/ main/java/org/apache/http/impl/client/ test/java/org/apache/http/impl/client/

Author: olegk
Date: Tue Aug 16 15:09:34 2011
New Revision: 1158314

URL: http://svn.apache.org/viewvc?rev=1158314&view=rev
Log:
Simplified ServiceUnavailableRetryStrategy interface; made DefaultServiceUnavailableRetryStrategy immutable; updated javadocs

Modified:
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/AutoRetryHttpClient.java
    httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java
    httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestAutoRetryHttpClient.java

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java?rev=1158314&r1=1158313&r2=1158314&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/client/ServiceUnavailableRetryStrategy.java Tue Aug 16 15:09:34 2011
@@ -35,6 +35,7 @@ import org.apache.http.protocol.HttpCont
  * control whether or not a retry should automatically be done, how many times
  * it should be retried and so on.
  *
+ * @since 4.2
  */
 public interface ServiceUnavailableRetryStrategy {
 
@@ -56,11 +57,4 @@ public interface ServiceUnavailableRetry
      */
     long getRetryInterval();
 
-    /**
-     * @return the multiplying factor for continuous errors situations returned
-     *         by the server-side. Each retry attempt will multiply this factor
-     *         with the retry interval.
-     */
-    int getRetryFactor();
-
 }
\ No newline at end of file

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/AutoRetryHttpClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/AutoRetryHttpClient.java?rev=1158314&r1=1158313&r2=1158314&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/AutoRetryHttpClient.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/AutoRetryHttpClient.java Tue Aug 16 15:09:34 2011
@@ -43,6 +43,12 @@ import org.apache.http.params.HttpParams
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.client.*;
 
+/**
+ * {@link HttpClient} implementation that can automatically retry the request in case of 
+ * a non-2xx response using the {@link ServiceUnavailableRetryStrategy} interface.
+ *
+ * @since 4.2
+ */
 @ThreadSafe
 public class AutoRetryHttpClient implements HttpClient {
 
@@ -147,7 +153,7 @@ public class AutoRetryHttpClient impleme
         for (int c = 1;; c++) {
             HttpResponse response = backend.execute(target, request, context);
             if (retryStrategy.retryRequest(response, c, context)) {
-                long nextInterval = retryStrategy.getRetryInterval() * retryStrategy.getRetryFactor();
+                long nextInterval = retryStrategy.getRetryInterval();
                 try {
                     log.trace("Wait for " + nextInterval);
                     Thread.sleep(nextInterval);

Modified: httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java?rev=1158314&r1=1158313&r2=1158314&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/main/java/org/apache/http/impl/client/DefaultServiceUnavailableRetryStrategy.java Tue Aug 16 15:09:34 2011
@@ -27,103 +27,57 @@
 
 package org.apache.http.impl.client;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.annotation.Immutable;
 import org.apache.http.client.ServiceUnavailableRetryStrategy;
 import org.apache.http.protocol.HttpContext;
 
 /**
- * Default implementation for the <code>ServiceUnavailableRetryStrategy</code>
- * interface.
- *
+ * Default implementation of the {@link ServiceUnavailableRetryStrategy} interface.
+ * that retries <code>503</code> (Service Unavailable) responses for a fixed number of times
+ * at a fixed interval.
+ * 
+ * @since 4.2
  */
+@Immutable
 public class DefaultServiceUnavailableRetryStrategy implements ServiceUnavailableRetryStrategy {
 
-    private List<Integer> retryResponseCodes = new ArrayList<Integer>();
-
     /**
      * Maximum number of allowed retries if the server responds with a HTTP code
      * in our retry code list. Default value is 1.
      */
-    private int maxRetries = 1;
+    private final int maxRetries;
 
     /**
      * Retry interval between subsequent requests, in milliseconds. Default
      * value is 1 second.
      */
-    private long retryInterval = 1000;
-
-    /**
-     * Multiplying factor for continuous errors situations returned by the
-     * server-side. Each retry attempt will multiply this factor with the retry
-     * interval. Default value is 1, which means each retry interval will be
-     * constant.
-     */
-    private int retryFactor = 1;
-
-    public void addResponseCodeForRetry(int responseCode) {
-        retryResponseCodes.add(responseCode);
-    }
-
-    public boolean retryRequest(final HttpResponse response, int executionCount, final HttpContext context) {
-        return executionCount <= maxRetries && retryResponseCodes.contains(
-                response.getStatusLine().getStatusCode());
-    }
-
-    /**
-     * @return The maximum number of allowed auto-retries in case the server
-     *         response code is contained in this retry strategy. Default value
-     *         is 1, meaning no-retry.
-     */
-    public int getMaxRetries() {
-        return maxRetries;
-    }
+    private final long retryInterval;
 
-    public void setMaxRetries(int maxRetries) {
+    public DefaultServiceUnavailableRetryStrategy(int maxRetries, int retryInterval) {
+        super();
         if (maxRetries < 1) {
-            throw new IllegalArgumentException(
-                    "MaxRetries should be greater than 1");
+            throw new IllegalArgumentException("MaxRetries must be greater than 1");
         }
-        this.maxRetries = maxRetries;
-    }
-
-    /**
-     * @return The interval between the subsequent auto-retries. Default value
-     *         is 1000 ms, meaning there is 1 second X
-     *         <code>getRetryFactor()</code> between the subsequent auto
-     *         retries.
-     *
-     */
-    public long getRetryInterval() {
-        return retryInterval;
-    }
-
-    public void setRetryInterval(long retryInterval) {
         if (retryInterval < 1) {
-            throw new IllegalArgumentException(
-                    "Retry interval should be greater than 1");
+            throw new IllegalArgumentException("Retry interval must be greater than 1");
         }
+        this.maxRetries = maxRetries;
         this.retryInterval = retryInterval;
     }
 
-    /**
-     * @return the multiplying factor for continuous errors situations returned
-     *         by the server-side. Each retry attempt will multiply this factor
-     *         with the retry interval. default value is 1, meaning the retry
-     *         intervals are constant.
-     */
-    public int getRetryFactor() {
-        return retryFactor;
+    public DefaultServiceUnavailableRetryStrategy() {
+        this(1, 1000);
     }
 
-    public void setRetryFactor(int factor) {
-        if (factor < 1) {
-            throw new IllegalArgumentException(
-                    "Retry factor should be greater than 1");
-        }
-        this.retryFactor = factor;
+    public boolean retryRequest(final HttpResponse response, int executionCount, final HttpContext context) {
+        return executionCount <= maxRetries &&
+            response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE;
+    }
+
+    public long getRetryInterval() {
+        return retryInterval;
     }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestAutoRetryHttpClient.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestAutoRetryHttpClient.java?rev=1158314&r1=1158313&r2=1158314&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestAutoRetryHttpClient.java (original)
+++ httpcomponents/httpclient/trunk/httpclient/src/test/java/org/apache/http/impl/client/TestAutoRetryHttpClient.java Tue Aug 16 15:09:34 2011
@@ -35,20 +35,12 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Date;
-import java.util.Random;
-
-import org.apache.http.HttpEntity;
 import org.apache.http.HttpHost;
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.HttpVersion;
 import org.apache.http.client.HttpClient;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.impl.client.AutoRetryHttpClient;
-import org.apache.http.impl.client.DefaultServiceUnavailableRetryStrategy;
-import org.apache.http.impl.cookie.DateUtils;
 import org.apache.http.message.BasicHttpRequest;
 import org.apache.http.message.BasicHttpResponse;
 import org.apache.http.protocol.BasicHttpContext;
@@ -70,85 +62,28 @@ public class TestAutoRetryHttpClient{
         host = new HttpHost("foo.example.com");
     }
 
-    static HttpResponse make200Response() {
-        HttpResponse out = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
-        out.setHeader("Date", DateUtils.formatDate(new Date()));
-        out.setHeader("Server", "MockOrigin/1.0");
-        out.setHeader("Content-Length", "128");
-        out.setEntity(makeBody(128));
-        return out;
-    }
-
-
-    static HttpRequest makeDefaultRequest() {
-        return new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
-    }
-
-    static HttpResponse make500Response() {
-        return new BasicHttpResponse(HttpVersion.HTTP_1_1,
-                HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
-    }
-
-    static HttpResponse make503Response() {
-        return new BasicHttpResponse(HttpVersion.HTTP_1_1,
-                HttpStatus.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
-    }
-
-    static HttpResponse make502Response() {
-        return new BasicHttpResponse(HttpVersion.HTTP_1_1,
-                HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
-    }
-
-    /** Generates a response body with random content.
-     *  @param nbytes length of the desired response body
-     *  @return an {@link HttpEntity}
-     */
-    static HttpEntity makeBody(int nbytes) {
-        return new ByteArrayEntity(getRandomBytes(nbytes));
-    }
-
-    static byte[] getRandomBytes(int nbytes) {
-        byte[] bytes = new byte[nbytes];
-        (new Random()).nextBytes(bytes);
-        return bytes;
-    }
-
     @Test
-    public void testAddOneStatusInRetryConfig(){
+    public void testDefaultRetryConfig(){
         DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy();
-        retryStrategy.addResponseCodeForRetry(503);
         HttpContext context = new BasicHttpContext();
         HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
         assertTrue(retryStrategy.retryRequest(response1, 1, context));
         HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 502, "Oppsie");
         assertFalse(retryStrategy.retryRequest(response2, 1, context));
-    }
-
-    @Test
-    public void testAddMultipleStatusesInRetryConfig(){
-        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy();
-        retryStrategy.addResponseCodeForRetry(503);
-        retryStrategy.addResponseCodeForRetry(502);
-        HttpContext context = new BasicHttpContext();
-        HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 503, "Oppsie");
-        assertTrue(retryStrategy.retryRequest(response1, 1, context));
-        HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 502, "Oppsie");
-        assertTrue(retryStrategy.retryRequest(response2, 1, context));
-        HttpResponse response3 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 500, "Oppsie");
-        assertFalse(retryStrategy.retryRequest(response3, 1, context));
+        assertEquals(1000, retryStrategy.getRetryInterval());
     }
 
     @Test
     public void testNoAutoRetry() throws java.io.IOException{
-        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy();
-        retryStrategy.setMaxRetries(2);
-        retryStrategy.setRetryInterval(100);
+        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy(2, 100);
 
         impl = new AutoRetryHttpClient(mockBackend,retryStrategy);
 
-        HttpRequest req1 = makeDefaultRequest();
-        HttpResponse resp1 = make500Response();
-        HttpResponse resp2 = make200Response();
+        HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
+        HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1,
+                HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
+        HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1,
+                HttpStatus.SC_OK, "OK");
 
         when(mockBackend.execute(host, req1,(HttpContext)null)).thenReturn(resp1).thenReturn(resp2);
 
@@ -162,18 +97,17 @@ public class TestAutoRetryHttpClient{
 
     @Test
     public void testMultipleAutoRetry() throws java.io.IOException{
-        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy();
-        retryStrategy.addResponseCodeForRetry(503);
-        retryStrategy.addResponseCodeForRetry(502);
-        retryStrategy.setMaxRetries(5);
-        retryStrategy.setRetryInterval(100);
+        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy(5, 100);
 
         impl = new AutoRetryHttpClient(mockBackend,retryStrategy);
 
-        HttpRequest req1 = makeDefaultRequest();
-        HttpResponse resp1 = make503Response();
-        HttpResponse resp2 = make502Response();
-        HttpResponse resp3 = make200Response();
+        HttpRequest req1 = new BasicHttpRequest("GET","/",HttpVersion.HTTP_1_1);
+        HttpResponse resp1 = new BasicHttpResponse(HttpVersion.HTTP_1_1,
+                HttpStatus.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
+        HttpResponse resp2 = new BasicHttpResponse(HttpVersion.HTTP_1_1,
+                HttpStatus.SC_SERVICE_UNAVAILABLE, "Service Unavailable");
+        HttpResponse resp3 = new BasicHttpResponse(HttpVersion.HTTP_1_1,
+                HttpStatus.SC_OK, "OK");
 
         when(mockBackend.execute(host, req1,(HttpContext)null)).thenReturn(resp1).thenReturn(resp2).thenReturn(resp3);
 
@@ -185,57 +119,4 @@ public class TestAutoRetryHttpClient{
         assertEquals(200,result.getStatusLine().getStatusCode());
     }
 
-    @Test
-    public void test503SingleAutoRetry() throws java.io.IOException{
-        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy();
-        retryStrategy.addResponseCodeForRetry(503);
-        retryStrategy.setMaxRetries(5);
-        retryStrategy.setRetryInterval(100);
-
-        impl = new AutoRetryHttpClient(mockBackend,retryStrategy);
-
-        HttpRequest req1 = makeDefaultRequest();
-        HttpResponse resp1 = make503Response();
-        HttpResponse resp2 = make200Response();
-
-        when(mockBackend.execute(host, req1,(HttpContext)null)).thenReturn(resp1).thenReturn(resp2);
-
-        HttpResponse result =  impl.execute(host, req1);
-
-        verify(mockBackend,times(2)).execute(host, req1,(HttpContext)null);
-
-        assertEquals(resp2,result);
-        assertEquals(200,result.getStatusLine().getStatusCode());
-    }
-
-    @Test
-    public void testRetryInterval() throws java.io.IOException{
-        DefaultServiceUnavailableRetryStrategy retryStrategy = new DefaultServiceUnavailableRetryStrategy();
-        retryStrategy.addResponseCodeForRetry(503);
-        retryStrategy.setMaxRetries(5);
-        retryStrategy.setRetryFactor(2);
-        retryStrategy.setRetryInterval(100); // 0.1 seconds
-
-        impl = new AutoRetryHttpClient(mockBackend,retryStrategy);
-
-        HttpRequest req1 = makeDefaultRequest();
-        HttpResponse resp1 = make503Response();
-        HttpResponse resp2 = make200Response();
-
-        when(mockBackend.execute(host, req1,(HttpContext)null)).thenReturn(resp1).thenReturn(resp2);
-
-        long currentTime = System.currentTimeMillis();
-        HttpResponse result =  impl.execute(host, req1);
-
-        long elapsedTime = System.currentTimeMillis();
-
-        verify(mockBackend,times(2)).execute(host, req1,(HttpContext)null);
-
-        assertEquals(resp2,result);
-        assertEquals(200,result.getStatusLine().getStatusCode());
-        assertTrue((elapsedTime - currentTime) > 100);
-    }
-
-
-
 }