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 2013/01/24 12:05:36 UTC

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

Author: olegk
Date: Thu Jan 24 11:05:36 2013
New Revision: 1437952

URL: http://svn.apache.org/viewvc?rev=1437952&view=rev
Log:
HTTPCLIENT-1298: Add AsynchronousValidator in HttpClientBuilder's list of closeable objects
Contributed by Martin Meinhold <mmeinhold at atlassian.com>

* Resolve constructor dependency between CachingExec and AsynchronousValidator
* AsynchronousValidator implements Closeable interface

Modified:
    httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
    httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java
    httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java
    httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClientBuilder.java
    httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java

Modified: httpcomponents/httpclient/trunk/RELEASE_NOTES.txt
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/RELEASE_NOTES.txt?rev=1437952&r1=1437951&r2=1437952&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/RELEASE_NOTES.txt (original)
+++ httpcomponents/httpclient/trunk/RELEASE_NOTES.txt Thu Jan 24 11:05:36 2013
@@ -1,3 +1,11 @@
+Changes since 4.3 ALPHA1
+-------------------
+
+* [HTTPCLIENT-1298] Add AsynchronousValidator in HttpClientBuilder's list of closeable objects.
+  Contributed by Martin Meinhold <mmeinhold at atlassian.com>
+
+
+
 Release 4.3 ALPHA1
 -------------------
 

Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java?rev=1437952&r1=1437951&r2=1437952&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/AsynchronousValidator.java Thu Jan 24 11:05:36 2013
@@ -26,6 +26,8 @@
  */
 package org.apache.http.impl.client.cache;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
@@ -47,8 +49,7 @@ import org.apache.http.conn.routing.Http
  * Class used for asynchronous revalidations to be used when the "stale-
  * while-revalidate" directive is present
  */
-class AsynchronousValidator {
-    private final CachingExec cachingExec;
+class AsynchronousValidator implements Closeable {
     private final ExecutorService executor;
     private final Set<String> queued;
     private final CacheKeyGenerator cacheKeyGenerator;
@@ -57,20 +58,16 @@ class AsynchronousValidator {
 
     /**
      * Create AsynchronousValidator which will make revalidation requests
-     * using the supplied {@link CachingHttpClient}, and
-     * a {@link ThreadPoolExecutor} generated according to the thread
+     * using a {@link ThreadPoolExecutor} generated according to the thread
      * pool settings provided in the given {@link CacheConfig}.
-     * @param cachingExect used to execute asynchronous requests
      * @param config specifies thread pool settings. See
      * {@link CacheConfig#getAsynchronousWorkersMax()},
      * {@link CacheConfig#getAsynchronousWorkersCore()},
      * {@link CacheConfig#getAsynchronousWorkerIdleLifetimeSecs()},
      * and {@link CacheConfig#getRevalidationQueueSize()}.
      */
-    public AsynchronousValidator(final CachingExec cachingExect,
-            final CacheConfig config) {
-        this(cachingExect,
-                new ThreadPoolExecutor(config.getAsynchronousWorkersCore(),
+    public AsynchronousValidator(final CacheConfig config) {
+        this(new ThreadPoolExecutor(config.getAsynchronousWorkersCore(),
                         config.getAsynchronousWorkersMax(),
                         config.getAsynchronousWorkerIdleLifetimeSecs(),
                         TimeUnit.SECONDS,
@@ -82,20 +79,24 @@ class AsynchronousValidator {
      * Create AsynchronousValidator which will make revalidation requests
      * using the supplied {@link CachingHttpClient} and
      * {@link ExecutorService}.
-     * @param cachingExect used to execute asynchronous requests
      * @param executor used to manage a thread pool of revalidation workers
      */
-    AsynchronousValidator(final CachingExec cachingExec, final ExecutorService executor) {
-        this.cachingExec = cachingExec;
+    AsynchronousValidator(final ExecutorService executor) {
         this.executor = executor;
         this.queued = new HashSet<String>();
         this.cacheKeyGenerator = new CacheKeyGenerator();
     }
 
+    @Override
+    public void close() throws IOException {
+        executor.shutdown();
+    }
+
     /**
      * Schedules an asynchronous revalidation
      */
     public synchronized void revalidateCacheEntry(
+            final CachingExec cachingExec,
             final HttpRoute route,
             final HttpRequestWrapper request,
             final HttpClientContext context,

Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java?rev=1437952&r1=1437951&r2=1437952&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingExec.java Thu Jan 24 11:05:36 2013
@@ -119,6 +119,14 @@ public class CachingExec implements Clie
             final ClientExecChain backend,
             final HttpCache cache,
             final CacheConfig config) {
+        this(backend, cache, config, null);
+    }
+
+    public CachingExec(
+            final ClientExecChain backend,
+            final HttpCache cache,
+            final CacheConfig config,
+            final AsynchronousValidator asynchRevalidator) {
         super();
         Args.notNull(backend, "HTTP backend");
         Args.notNull(cache, "HttpCache");
@@ -135,7 +143,7 @@ public class CachingExec implements Clie
         this.responseCachingPolicy = new ResponseCachingPolicy(
                 this.cacheConfig.getMaxObjectSize(), this.cacheConfig.isSharedCache(),
                 this.cacheConfig.isNeverCacheHTTP10ResponsesWithQuery());
-        this.asynchRevalidator = makeAsynchronousValidator(config);
+        this.asynchRevalidator = asynchRevalidator != null ? asynchRevalidator : makeAsynchronousValidator(config);
     }
 
     public CachingExec(
@@ -179,7 +187,7 @@ public class CachingExec implements Clie
     private AsynchronousValidator makeAsynchronousValidator(
             final CacheConfig config) {
         if (config.getAsynchronousWorkersMax() > 0) {
-            return new AsynchronousValidator(this, config);
+            return new AsynchronousValidator(config);
         }
         return null;
     }
@@ -312,7 +320,7 @@ public class CachingExec implements Clie
                 && validityPolicy.mayReturnStaleWhileRevalidating(entry, now)) {
                 log.trace("Serving stale with asynchronous revalidation");
                 final HttpResponse resp = generateCachedResponse(request, context, entry, now);
-                asynchRevalidator.revalidateCacheEntry(route, request, context, execAware, entry);
+                asynchRevalidator.revalidateCacheEntry(this, route, request, context, execAware, entry);
                 return Proxies.enhanceResponse(resp);
             }
             return revalidateCacheEntry(route, request, context, execAware, entry);

Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClientBuilder.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClientBuilder.java?rev=1437952&r1=1437951&r2=1437952&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClientBuilder.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClientBuilder.java Thu Jan 24 11:05:36 2013
@@ -97,8 +97,15 @@ public class CachingHttpClientBuilder ex
             }
             storage = new BasicHttpCacheStorage(cacheConfig);
         }
+        final AsynchronousValidator revalidator = createAsynchronousRevalidator(config);
         return new CachingExec(mainExec,
-                new BasicHttpCache(resourceFactory, storage, config), config);
+                new BasicHttpCache(resourceFactory, storage, config), config, revalidator);
+    }
+
+    private AsynchronousValidator createAsynchronousRevalidator(final CacheConfig config) {
+        final AsynchronousValidator revalidator = new AsynchronousValidator(config);
+        addCloseable(revalidator);
+        return revalidator;
     }
 
 }

Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java?rev=1437952&r1=1437951&r2=1437952&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java (original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestAsynchronousValidator.java Thu Jan 24 11:05:36 2013
@@ -26,6 +26,7 @@
  */
 package org.apache.http.impl.client.cache;
 
+import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeUnit;
@@ -74,13 +75,13 @@ public class TestAsynchronousValidator {
 
     @Test
     public void testRevalidateCacheEntrySchedulesExecutionAndPopulatesIdentifier() {
-        impl = new AsynchronousValidator(mockClient, mockExecutor);
+        impl = new AsynchronousValidator(mockExecutor);
 
         EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
         mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
 
         replayMocks();
-        impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry);
         verifyMocks();
 
         Assert.assertEquals(1, impl.getScheduledIdentifiers().size());
@@ -88,14 +89,14 @@ public class TestAsynchronousValidator {
 
     @Test
     public void testMarkCompleteRemovesIdentifier() {
-        impl = new AsynchronousValidator(mockClient, mockExecutor);
+        impl = new AsynchronousValidator(mockExecutor);
 
         EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
         final Capture<AsynchronousValidationRequest> cap = new Capture<AsynchronousValidationRequest>();
         mockExecutor.execute(EasyMock.capture(cap));
 
         replayMocks();
-        impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry);
         verifyMocks();
 
         Assert.assertEquals(1, impl.getScheduledIdentifiers().size());
@@ -107,14 +108,14 @@ public class TestAsynchronousValidator {
 
     @Test
     public void testRevalidateCacheEntryDoesNotPopulateIdentifierOnRejectedExecutionException() {
-        impl = new AsynchronousValidator(mockClient, mockExecutor);
+        impl = new AsynchronousValidator(mockExecutor);
 
         EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
         mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
         EasyMock.expectLastCall().andThrow(new RejectedExecutionException());
 
         replayMocks();
-        impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry);
         verifyMocks();
 
         Assert.assertEquals(0, impl.getScheduledIdentifiers().size());
@@ -122,7 +123,7 @@ public class TestAsynchronousValidator {
 
     @Test
     public void testRevalidateCacheEntryProperlyCollapsesRequest() {
-        impl = new AsynchronousValidator(mockClient, mockExecutor);
+        impl = new AsynchronousValidator(mockExecutor);
 
         EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
         mockExecutor.execute(EasyMock.isA(AsynchronousValidationRequest.class));
@@ -130,8 +131,8 @@ public class TestAsynchronousValidator {
         EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
 
         replayMocks();
-        impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry);
-        impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry);
         verifyMocks();
 
         Assert.assertEquals(1, impl.getScheduledIdentifiers().size());
@@ -139,7 +140,7 @@ public class TestAsynchronousValidator {
 
     @Test
     public void testVariantsBothRevalidated() {
-        impl = new AsynchronousValidator(mockClient, mockExecutor);
+        impl = new AsynchronousValidator(mockExecutor);
 
         final HttpRequest req1 = new HttpGet("/");
         req1.addHeader(new BasicHeader("Accept-Encoding", "identity"));
@@ -157,8 +158,8 @@ public class TestAsynchronousValidator {
         EasyMock.expectLastCall().times(2);
 
         replayMocks();
-        impl.revalidateCacheEntry(route, HttpRequestWrapper.wrap(req1), context, mockExecAware, mockCacheEntry);
-        impl.revalidateCacheEntry(route, HttpRequestWrapper.wrap(req2), context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, HttpRequestWrapper.wrap(req1), context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, HttpRequestWrapper.wrap(req2), context, mockExecAware, mockCacheEntry);
         verifyMocks();
 
         Assert.assertEquals(2, impl.getScheduledIdentifiers().size());
@@ -171,14 +172,14 @@ public class TestAsynchronousValidator {
             .setAsynchronousWorkersMax(1)
             .setAsynchronousWorkersCore(1)
             .build();
-        impl = new AsynchronousValidator(mockClient, config);
+        impl = new AsynchronousValidator(config);
 
         EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(false);
         EasyMock.expect(mockClient.revalidateCacheEntry(
                 route, request, context, mockExecAware, mockCacheEntry)).andReturn(null);
 
         replayMocks();
-        impl.revalidateCacheEntry(route, request, context, mockExecAware, mockCacheEntry);
+        impl.revalidateCacheEntry(mockClient, route, request, context, mockExecAware, mockCacheEntry);
 
         try {
             // shut down backend executor and make sure all finishes properly, 1 second should be sufficient
@@ -194,6 +195,17 @@ public class TestAsynchronousValidator {
         }
     }
 
+    @Test
+    public void testExecutorShutdownOnClose() throws IOException {
+        impl = new AsynchronousValidator(mockExecutor);
+
+        mockExecutor.shutdown();
+
+        replayMocks();
+        impl.close();
+        verifyMocks();
+    }
+
     public void replayMocks() {
         EasyMock.replay(mockExecutor);
         EasyMock.replay(mockClient);