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);
- }
-
-
-
}