We've recently upgraded our Spring Boot application and have switched to Spring's new WebClient. On undeploy of the webapp, we see a 'idle-connection-evictor' thread as a memory leak, preventing the WebappClassloader to be gc'ed. That thread is created by the Apache HttpClient 5 (async)
The code creates WebClient instances through a custom WebClientBuilder, with the key code:
public WebClient build() {
final ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
buildOAuth2AuthorizedClientManager());
CloseableHttpAsyncClient httpAsyncClient = HttpAsyncClients.custom()
.setConnectionManager(connManager)
.evictIdleConnections(TimeValue.ofSeconds(60))
.build();
return WebClient.builder()
.clientConnector(new HttpComponentsClientHttpConnector(httpAsyncClient))
.apply(oauth2Client.oauth2Configuration())
.build();
}
That CloseableHttpAsyncClient already reeks, as there's no try-with-resource. HttpComponentsClientHttpConnector is Closeable, but clientConnector() then just wants a ClientHttpConnector, which has no methods defined for close/destroy/etc. Spring WebClient itself is also neither Closeable nor offers any shutdown/destroy method.
What is the clean way to make a Spring WebClient close its clientConnector?