Skip to content

Commit bbc3ac3

Browse files
Fix NPE in connection evictor setup (#774)
Builders computed evictor sleep time from maxIdleTime even when only evictExpiredConnections() was enabled, causing an NPE.
1 parent 80622f5 commit bbc3ac3

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/HttpAsyncClientBuilder.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -864,7 +864,7 @@ public final HttpAsyncClientBuilder evictExpiredConnections() {
864864
*/
865865
public final HttpAsyncClientBuilder evictIdleConnections(final TimeValue maxIdleTime) {
866866
this.evictIdleConnections = true;
867-
this.maxIdleTime = maxIdleTime;
867+
this.maxIdleTime = Args.notNull(maxIdleTime, "Max idle time");
868868
return this;
869869
}
870870

@@ -1144,10 +1144,11 @@ public CloseableHttpAsyncClient build() {
11441144
}
11451145
if (evictExpiredConnections || evictIdleConnections) {
11461146
if (connManagerCopy instanceof ConnPoolControl) {
1147-
TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS);
1147+
final TimeValue maxIdleTimeCopy = evictIdleConnections ? maxIdleTime : null;
1148+
TimeValue sleepTime = maxIdleTimeCopy != null ? maxIdleTimeCopy.divide(10, TimeUnit.NANOSECONDS) : ONE_SECOND;
11481149
sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime;
11491150
final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl<?>) connManagerCopy,
1150-
sleepTime, maxIdleTime);
1151+
sleepTime, maxIdleTimeCopy);
11511152
closeablesCopy.add(connectionEvictor::shutdown);
11521153
connectionEvictor.start();
11531154
}

httpclient5/src/main/java/org/apache/hc/client5/http/impl/classic/HttpClientBuilder.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ public final HttpClientBuilder evictExpiredConnections() {
778778
*/
779779
public final HttpClientBuilder evictIdleConnections(final TimeValue maxIdleTime) {
780780
this.evictIdleConnections = true;
781-
this.maxIdleTime = maxIdleTime;
781+
this.maxIdleTime = Args.notNull(maxIdleTime, "Max idle time");
782782
return this;
783783
}
784784

@@ -1113,10 +1113,11 @@ public CloseableHttpClient build() {
11131113
}
11141114
if (evictExpiredConnections || evictIdleConnections) {
11151115
if (connManagerCopy instanceof ConnPoolControl) {
1116-
TimeValue sleepTime = maxIdleTime.divide(10, TimeUnit.NANOSECONDS);
1116+
final TimeValue maxIdleTimeCopy = evictIdleConnections ? maxIdleTime : null;
1117+
TimeValue sleepTime = maxIdleTimeCopy != null ? maxIdleTimeCopy.divide(10, TimeUnit.NANOSECONDS) : ONE_SECOND;
11171118
sleepTime = sleepTime.compareTo(ONE_SECOND) < 0 ? ONE_SECOND : sleepTime;
11181119
final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor((ConnPoolControl<?>) connManagerCopy,
1119-
sleepTime, maxIdleTime);
1120+
sleepTime, maxIdleTimeCopy);
11201121
closeablesCopy.add(() -> {
11211122
connectionEvictor.shutdown();
11221123
try {

httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpAsyncClientBuilder.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@
3131
import org.apache.hc.client5.http.async.AsyncExecCallback;
3232
import org.apache.hc.client5.http.async.AsyncExecChain;
3333
import org.apache.hc.client5.http.async.AsyncExecChainHandler;
34+
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
35+
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
3436
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
3537
import org.apache.hc.core5.http.HttpException;
3638
import org.apache.hc.core5.http.HttpRequest;
3739
import org.apache.hc.core5.http.nio.AsyncEntityProducer;
40+
import org.junit.jupiter.api.Assertions;
3841
import org.junit.jupiter.api.Test;
3942

4043
class TestHttpAsyncClientBuilder {
@@ -82,4 +85,14 @@ public void execute(final HttpRequest request, final AsyncEntityProducer entityP
8285
chain.proceed(request, entityProducer, scope, asyncExecCallback);
8386
}
8487
}
88+
89+
90+
@Test
91+
void testEvictExpiredConnectionsDoesNotRequireMaxIdleTime() throws Exception {
92+
try (final CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create()
93+
.evictExpiredConnections()
94+
.build()) {
95+
Assertions.assertNotNull(client);
96+
}
97+
}
8598
}

httpclient5/src/test/java/org/apache/hc/client5/http/impl/classic/TestHttpClientBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.apache.hc.core5.http.ClassicHttpRequest;
3434
import org.apache.hc.core5.http.ClassicHttpResponse;
3535
import org.apache.hc.core5.http.HttpException;
36+
import org.junit.jupiter.api.Assertions;
3637
import org.junit.jupiter.api.Test;
3738

3839
class TestHttpClientBuilder {
@@ -66,4 +67,13 @@ public ClassicHttpResponse execute(
6667
return chain.proceed(request, scope);
6768
}
6869
}
70+
71+
@Test
72+
void testEvictExpiredConnectionsDoesNotRequireMaxIdleTime() throws Exception {
73+
try (final CloseableHttpClient client = HttpClientBuilder.create()
74+
.evictExpiredConnections()
75+
.build()) {
76+
Assertions.assertNotNull(client);
77+
}
78+
}
6979
}

0 commit comments

Comments
 (0)