docs/source/manual/client.rst
.. _man-client:
#################
Dropwizard Client
#################
.. highlight:: text
.. rubric:: The ``dropwizard-client`` module provides you with two different performant,
instrumented HTTP clients so you can integrate your service with other web
services: :ref:`man-client-apache` and :ref:`man-client-jersey`.
.. code-block:: xml
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-client</artifactId>
</dependency>
.. _man-client-apache:
Apache HttpClient
=================
The underlying library for ``dropwizard-client`` is Apache's HttpClient_, a full-featured,
well-tested HTTP client library.
.. _HttpClient: http://hc.apache.org/httpcomponents-core-4.3.x/index.html
To create a :ref:`managed <man-core-managed>`, instrumented ``HttpClient`` instance, your
:ref:`configuration class <man-core-configuration>` needs an :ref:`http client configuration <man-configuration-clients-http>` instance:
.. code-block:: java
public class ExampleConfiguration extends Configuration {
@Valid
@NotNull
private HttpClientConfiguration httpClient = new HttpClientConfiguration();
@JsonProperty("httpClient")
public HttpClientConfiguration getHttpClientConfiguration() {
return httpClient;
}
@JsonProperty("httpClient")
public void setHttpClientConfiguration(HttpClientConfiguration httpClient) {
this.httpClient = httpClient;
}
}
Then, in your application's ``run`` method, create a new ``HttpClientBuilder``:
.. code-block:: java
@Override
public void run(ExampleConfiguration config,
Environment environment) {
final HttpClient httpClient = new HttpClientBuilder(environment).using(config.getHttpClientConfiguration())
.build(getName());
environment.jersey().register(new ExternalServiceResource(httpClient));
}
.. _man-client-apache-metrics:
Metrics
-------
Dropwizard's ``HttpClientBuilder`` actually gives you an instrumented subclass which tracks the
following pieces of data:
``org.apache.http.conn.ClientConnectionManager.available-connections``
The number of idle connections ready to be used to execute requests.
``org.apache.http.conn.ClientConnectionManager.leased-connections``
The number of persistent connections currently being used to execute requests.
``org.apache.http.conn.ClientConnectionManager.max-connections``
The maximum number of allowed connections.
``org.apache.http.conn.ClientConnectionManager.pending-connections``
The number of connection requests being blocked awaiting a free connection.
``org.apache.http.client.HttpClient.get-requests``
The rate at which ``GET`` requests are being sent.
``org.apache.http.client.HttpClient.post-requests``
The rate at which ``POST`` requests are being sent.
``org.apache.http.client.HttpClient.head-requests``
The rate at which ``HEAD`` requests are being sent.
``org.apache.http.client.HttpClient.put-requests``
The rate at which ``PUT`` requests are being sent.
``org.apache.http.client.HttpClient.delete-requests``
The rate at which ``DELETE`` requests are being sent.
``org.apache.http.client.HttpClient.options-requests``
The rate at which ``OPTIONS`` requests are being sent.
``org.apache.http.client.HttpClient.trace-requests``
The rate at which ``TRACE`` requests are being sent.
``org.apache.http.client.HttpClient.connect-requests``
The rate at which ``CONNECT`` requests are being sent.
``org.apache.http.client.HttpClient.move-requests``
The rate at which ``MOVE`` requests are being sent.
``org.apache.http.client.HttpClient.patch-requests``
The rate at which ``PATCH`` requests are being sent.
``org.apache.http.client.HttpClient.other-requests``
The rate at which requests with none of the above methods are being sent.
.. note::
The naming strategy for the metrics associated requests is configurable.
Specifically, the last part e.g. get-requests.
What is displayed is ``HttpClientMetricNameStrategies.METHOD_ONLY``, you can
also include the host via ``HttpClientMetricNameStrategies.HOST_AND_METHOD``
or a url without query string via ``HttpClientMetricNameStrategies.QUERYLESS_URL_AND_METHOD``
.. _man-client-jersey:
Jersey Client
=============
If HttpClient_ is too low-level for you, Dropwizard also supports Jersey's `Client API`_.
Jersey's ``Client`` allows you to use all of the server-side media type support that your service
uses to, for example, deserialize ``application/json`` request entities as POJOs.
.. _Client API: https://eclipse-ee4j.github.io/jersey.github.io/documentation/2.29.1/client.html
To create a :ref:`managed <man-core-managed>`, instrumented ``JerseyClient`` instance, your
:ref:`configuration class <man-core-configuration>` needs an :ref:`jersey client configuration <man-configuration-clients-jersey>` instance:
.. code-block:: java
public class ExampleConfiguration extends Configuration {
@Valid
@NotNull
private JerseyClientConfiguration jerseyClient = new JerseyClientConfiguration();
@JsonProperty("jerseyClient")
public JerseyClientConfiguration getJerseyClientConfiguration() {
return jerseyClient;
}
@JsonProperty("jerseyClient")
public void setJerseyClientConfiguration(JerseyClientConfiguration jerseyClient) {
this.jerseyClient = jerseyClient;
}
}
Then, in your service's ``run`` method, create a new ``JerseyClientBuilder``:
.. code-block:: java
@Override
public void run(ExampleConfiguration config,
Environment environment) {
final Client client = new JerseyClientBuilder(environment).using(config.getJerseyClientConfiguration())
.build(getName());
environment.jersey().register(new ExternalServiceResource(client));
}
Configuration
-------------
The Client that Dropwizard creates deviates from the `Jersey Client Configuration` defaults. The
default, in Jersey, is for a client to never timeout reading or connecting in a request, while in
Dropwizard, the default is 500 milliseconds.
There are a couple of ways to change this behavior. The recommended way is to modify the
:ref:`YAML configuration <man-configuration-clients-http>`. Alternatively, set the properties on
the ``JerseyClientConfiguration``, which will take effect for all built clients. On a per client
basis, the configuration can be changed by utilizing the ``property`` method and, in this case,
the `Jersey Client Properties`_ can be used.
.. warning::
Do not try to change Jersey properties using `Jersey Client Properties`_ through the
``withProperty(String propertyName, Object propertyValue)``
method on the ``JerseyClientBuilder``, because by default it's configured by Dropwizard's
``HttpClientBuilder``, so the Jersey properties are ignored.
.. _Jersey Client Configuration: https://eclipse-ee4j.github.io/jersey.github.io/documentation/2.29.1/appendix-properties.html#appendix-properties-client
.. _Jersey Client Properties: https://eclipse-ee4j.github.io/jersey.github.io/apidocs/2.29.1/jersey/org/glassfish/jersey/client/ClientProperties.html
.. _man-client-jersey-rx-usage:
Rx Usage
--------
To increase the ergonomics of asynchronous client requests, Jersey allows creation of `rx-clients`_.
You can instruct Dropwizard to create such a client (RxJava2):
.. code-block:: java
@Override
public void run(ExampleConfiguration config,
Environment environment) {
final Client client =
new JerseyClientBuilder(environment)
.using(config.getJerseyClientConfiguration())
.buildRx(getName(), RxFlowableInvokerProvider.class);
//Any custom Service Resource that waits for Client in constructor
environment.jersey().register(new ExternalServiceResource(client));
}
``RxFlowableInvokerProvider.class`` is the JavaRx implementation and can be added to the pom:
.. code-block:: xml
<dependency>
<groupId>org.glassfish.jersey.ext.rx</groupId>
<artifactId>jersey-rx-client-rxjava2</artifactId>
</dependency>
Alternatively, there are RxJava, Guava, and JSR-166e implementations.
By allowing Dropwizard to create the rx-client, the same thread pool that is utilized by traditional
synchronous and asynchronous requests, is used for rx requests.
.. _rx-clients: https://eclipse-ee4j.github.io/jersey.github.io/documentation/2.29.1/rx-client.html
Proxy Authentication
--------------------
The client can utilise a forward proxy, supporting both Basic and NTLM authentication schemes.
Basic Auth against a proxy is simple:
.. code-block:: yaml
proxy:
host: '192.168.52.11'
port: 8080
scheme : 'https'
auth:
username: 'secret'
password: 'stuff'
nonProxyHosts:
- 'localhost'
- '192.168.52.*'
- '*.example.com'
NTLM Auth is configured by setting the relevant windows properties.
.. code-block:: yaml
proxy:
host: '192.168.52.11'
port: 8080
scheme : 'https'
auth:
username: 'secret'
password: 'stuff'
authScheme: 'NTLM'
realm: 'realm' # optional, defaults to ANY_REALM
hostname: 'workstation' # optional, defaults to null but may be required depending on your AD environment
domain: 'HYPERCOMPUGLOBALMEGANET' # optional, defaults to null but may be required depending on your AD environment
credentialType: 'NT'
nonProxyHosts:
- 'localhost'
- '192.168.52.*'
- '*.example.com'