4

Here is my code.

import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.JerseyClient;
import org.glassfish.jersey.client.JerseyClientBuilder;

public class Jersey2HttpClient {

    private static class InstanceHolder {
        private static final JerseyClient INSTANCE = createClient();

        private static JerseyClient createClient() {
            ClientConfig clientConfig = new ClientConfig();
            clientConfig.property(ClientProperties.READ_TIMEOUT, 20000);
            clientConfig.property(ClientProperties.CONNECT_TIMEOUT, 20000);
            PoolingHttpClientConnectionManager connectionManager =
                new PoolingHttpClientConnectionManager();
            connectionManager.setMaxTotal(200);
            connectionManager.setDefaultMaxPerRoute(50);
            clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
            clientConfig.connectorProvider(new ApacheConnectorProvider());

            JerseyClient client = JerseyClientBuilder.createClient(clientConfig);
            client.register(RequestLogger.requestLoggingFilter);
            return client;
        }
    }

    public static JerseyClient getInstance() {
        return InstanceHolder.INSTANCE;
    }
}

I have the following questions.

  1. If every time the same client will be returned(through getInstance()) to the calling thread when are 'connection pooling objects' created? It seems like the same object (client) is used for connections.

  2. What exactly happens when the following code is executed.

    JerseyClient client = JerseyClientBuilder.createClient(clientConfig);

In other words why is creating a client an expensive operation? I haven't even mentioned the url or the request yet.

Sorry for my weak knowledge on this subject.

druk
  • 553
  • 6
  • 16

1 Answers1

10

Client instances are heavy-weight

The initialization of Client instances might be an expensive operation because Clients are heavy-weight objects that manage the underlying communication infrastructure with the server.

You should create only a small number of Client instances and reuse them when possible. The documentation states the following:

Clients are heavy-weight objects that manage the client-side communication infrastructure. Initialization as well as disposal of a Client instance may be a rather expensive operation. It is therefore advised to construct only a small number of Client instances in the application. Client instances must be properly closed before being disposed to avoid leaking resources.

Using the ApacheConnectorProvider

By default, the transport layer in Jersey is provided by HttpURLConnection. This support is implemented in Jersey via HttpUrlConnectorProvider. You can replace the default connector if you want to.

Jersey integrates with Apache HTTP Client via the ApacheConnectorProvider. To use it, ensure you have the following dependecy:

<dependency>
    <groupId>org.glassfish.jersey.connectors</groupId>
    <artifactId>jersey-apache-connector</artifactId>
    <version>2.23.2</version>
</dependency>

In your code, you have instantiated a PoolingHttpClientConnectionManager but you are not using it anywhere. Add the following lines to your code:

clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
clientConfig.connectorProvider(new ApacheConnectorProvider());

For additional details, refer to Jersey documentation about connectors.

Aarjav
  • 1,334
  • 11
  • 22
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • Hi I added a suggested code changes. According to the documentation Client must be closed but how is that possible in a multi threaded environment when every thread accesses the same instance of class(like in the above code) and it is not suggested to create a new instance of Client whenever needed. So do I call close on the response object in that case? Is there a better way to handle this in multi threaded environments? – druk Aug 10 '16 at 13:01
  • Just a quick note for further reference: according to [Miroslav Fuksa](http://stackoverflow.com/users/2645465/miroslav-fuksa), developer on the Jersey project, [Jersey client is thread-safe](http://stackoverflow.com/a/18652915/1426227). – cassiomolin Aug 10 '16 at 13:36
  • @user3184974 What you need to close after every request is the connection and not the `Client` instance. For more details, refer to the [documentation](https://jersey.java.net/documentation/latest/client.html#d0e5170). This [answer](http://stackoverflow.com/a/35265704/1426227) also may be helpful. – cassiomolin Aug 10 '16 at 13:41