HTTPASYNC-160: HttpAsyncClient in INACTIVE or STOPPED state throws a IllegalStateException causing the current thread to terminate
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java
index eb92d14..3ab0947 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/AbstractHttpAsyncClientBase.java
@@ -81,13 +81,8 @@
pushConsumerRegistry.register(hostname, uriPattern, supplier);
}
- void ensureRunning() {
- switch (status.get()) {
- case READY:
- throw new IllegalStateException("Client is not running");
- case TERMINATED:
- throw new IllegalStateException("Client has been terminated");
- }
+ boolean isRunning() {
+ return status.get() == Status.RUNNING;
}
ConnectionInitiator getConnectionInitiator() {
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
index e16a1a4..c010523 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalAbstractHttpAsyncClient.java
@@ -30,6 +30,7 @@
import java.io.IOException;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
@@ -150,9 +151,11 @@
final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
final HttpContext context,
final FutureCallback<T> callback) {
- ensureRunning();
final ComplexFuture<T> future = new ComplexFuture<>(callback);
try {
+ if (!isRunning()) {
+ throw new CancellationException("Request execution cancelled");
+ }
final HttpClientContext clientContext = context != null ? HttpClientContext.adapt(context) : HttpClientContext.create();
requestProducer.sendRequest(new RequestChannel() {
@@ -316,7 +319,7 @@
}
}, context);
- } catch (final HttpException | IOException ex) {
+ } catch (final HttpException | IOException | IllegalStateException ex) {
future.failed(ex);
}
return future;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java
index dc23b62..411fb85 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalH2AsyncClient.java
@@ -30,6 +30,7 @@
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.List;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
@@ -134,10 +135,12 @@
final AsyncClientExchangeHandler exchangeHandler,
final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
final HttpContext context) {
- ensureRunning();
final ComplexCancellable cancellable = new ComplexCancellable();
- final HttpClientContext clientContext = context != null ? HttpClientContext.adapt(context) : HttpClientContext.create();
try {
+ if (!isRunning()) {
+ throw new CancellationException("Request execution cancelled");
+ }
+ final HttpClientContext clientContext = context != null ? HttpClientContext.adapt(context) : HttpClientContext.create();
exchangeHandler.produceRequest(new RequestChannel() {
@Override
@@ -270,7 +273,7 @@
}
}, context);
- } catch (final HttpException | IOException ex) {
+ } catch (final HttpException | IOException | IllegalStateException ex) {
exchangeHandler.failed(ex);
}
return cancellable;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java
index d4e95d2..b3a340d 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/MinimalHttpAsyncClient.java
@@ -29,6 +29,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -209,12 +210,15 @@
final FutureCallback<AsyncClientEndpoint> callback) {
Args.notNull(host, "Host");
Args.notNull(context, "HTTP context");
- ensureRunning();
+ final BasicFuture<AsyncClientEndpoint> future = new BasicFuture<>(callback);
+ if (!isRunning()) {
+ future.failed(new CancellationException("Connection lease cancelled"));
+ return future;
+ }
final HttpClientContext clientContext = HttpClientContext.adapt(context);
final RequestConfig requestConfig = clientContext.getRequestConfig();
final Timeout connectionRequestTimeout = requestConfig.getConnectionRequestTimeout();
final Timeout connectTimeout = requestConfig.getConnectTimeout();
- final BasicFuture<AsyncClientEndpoint> future = new BasicFuture<>(callback);
leaseEndpoint(
host,
connectionRequestTimeout,
@@ -246,10 +250,12 @@
final AsyncClientExchangeHandler exchangeHandler,
final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
final HttpContext context) {
- ensureRunning();
final ComplexCancellable cancellable = new ComplexCancellable();
- final HttpClientContext clientContext = context != null ? HttpClientContext.adapt(context) : HttpClientContext.create();
try {
+ if (!isRunning()) {
+ throw new CancellationException("Request execution cancelled");
+ }
+ final HttpClientContext clientContext = context != null ? HttpClientContext.adapt(context) : HttpClientContext.create();
exchangeHandler.produceRequest(new RequestChannel() {
@Override
@@ -426,7 +432,7 @@
}
}, context);
- } catch (final HttpException | IOException ex) {
+ } catch (final HttpException | IOException | IllegalStateException ex) {
exchangeHandler.failed(ex);
}
return cancellable;