eclipse-ee4j / eclipse-ee4j/jersey
Jersey OAuth 2 leaking connections with ApacheHTTPClient / PoolingHttpClientConnectionManager
- Dominant language
- Java
- Stars
- 730
- Forks
- 382
- PR merge metrics
- No merged PRs in 30d
Description
Using:
- org.glassfish.jersey.jersey-server and org.glassfish.jersey.jersey-client 2.30.1
- org.glassfish.jersey.security.jersey.security.oauth2-client 2.30.1
- org.glassfish.jersey.connectors.jersey-apache-connector 2.30.1
- org.apache.httpcomponents.httpcomponents-client 4.5.9
I am setting up the ClientBuilder for the OAuth2-client as follows, and note that I have to stretch the value of setDefaultMaxPerRoute so our application does not lock up regularly:
ClientConfig loConfig = new ClientConfig();
moHttpClientConnectionMgr = new PoolingHttpClientConnectionManager();
moHttpClientConnectionMgr.setMaxTotal( 500 );
moHttpClientConnectionMgr.setDefaultMaxPerRoute( 500 );
moHttpClientConnectionMgr.setValidateAfterInactivity( 1000 );
loConfig.property( ApacheClientProperties.CONNECTION_MANAGER, moHttpClientConnectionMgr );
loConfig.connectorProvider( new ApacheConnectorProvider() );
// For some reason, the Microsoft Azure OAuth server does not support CHUNKED requests, which
// is the default for ApacheHttpClient (apparently).
loConfig.property(
ClientProperties.REQUEST_ENTITY_PROCESSING,
RequestEntityProcessing.BUFFERED );
if( msOutboundProxyUri != null && msOutboundProxyUri.trim().length() > 0 )
{
// set up outbound proxy, if configured
loConfig.property( ClientProperties.PROXY_URI, msOutboundProxyUri );
}
ClientBuilder loBuilder = ClientBuilder.newBuilder().withConfig( loConfig );
I suspect the following code in org/glassfish/jersey/client/oauth2/AuthCodeGrantImpl.java in the finish() method causes a connection to leak and not have the connection returned to the pool whenever the OAuth-provider returns any HTTP status other than 200, because the response is never actually consumed:
final Response response = client.target(accessTokenUri)
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
if (response.getStatus() != 200) {
throw new ProcessingException(LocalizationMessages.ERROR_FLOW_REQUEST_ACCESS_TOKEN(response.getStatus()));
}
this.tokenResult = response.readEntity(TokenResult.class);
return tokenResult;
The same code is present in refreshAccessToken().
Contributor guide
Assessment
This issue has not been assessed yet.