Skip to content

Commit

Permalink
[RESTEASY-1025] async ClientHttpEngine documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
rsearls authored and asoldano committed Jan 15, 2018
1 parent e238b5f commit 1f9a117
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions docbook/reference/en/en-US/modules/JAX-RS_2.1_additions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,85 @@
except JsonValue and its sub-types.
</para>
</sect1>
<sect1>
<title>Asynchronous HTTP Request Processing</title>
<para>
RESTEasy provides a new <emphasis>ClientHttpEngine</emphasis> implementation that
provides asynchronous HTTP request support. The new engine uses
<emphasis>HttpAsyncClient</emphasis> from the Apache <emphasis>HttpComponents</emphasis>
project. RESTEasy's default async engine implementation class is
<emphasis>ApacheHttpAsyncClient4Engine</emphasis>. It can be set as the active
engine by calling method <emphasis>useAsyncHttpEngine</emphasis> in
<emphasis>ResteasyClientBuilder</emphasis>.
</para>
<programlisting>
Client asyncClient = new ResteasyClientBuilder().useAsyncHttpEngine()
.build();
Future&lt;Response&gt; future = asyncClient
.target("http://locahost:8080/test").request()
.async().get();
Response res = future.get();
Assert.assertEquals(HttpResponseCodes.SC_OK, res.getStatus());
String entity = res.readEntity(String.class);
</programlisting>
<sect2>
<title>InvocationCallbacks</title>
<para>
InvocationCallbacks are called from within the io-threads and thus must not block or else
the application may slow down to a halt. Reading the response is safe because the response
is buffered in memory, as are other async and in-memory client-invocations that submit-calls
returning a future not containing Response, InputStream or Reader.
</para>
<programlisting>
final CountDownLatch latch = new CountDownLatch(1);
Future&lt;String&gt; future = nioClient.target(generateURL("/test")).request()
.async().get(new InvocationCallback&lt;String&gt;()
{
@Override
public void completed(String s)
{
Assert.assertEquals("get", s);
latch.countDown();
throw new RuntimeException("for the test of it");
}

@Override
public void failed(Throwable error)
{
}
});
String entity = future.get();
Assert.assertEquals("get", entity);
</programlisting>
<para>
InvocationCallbacks may be called seemingly "after" the future-object returns. Thus, responses
should be handled solely in the InvocationCallback.
</para>
<para>
InvocationCallbacks will see the same result as the future-object and vice versa. Thus, if the
invocationcallback throws an exception, the future-object will not see it. This is the
reason to handle responses only in the InvocationCallback.
</para>

</sect2>

<sect2>
<title>Async Engine Usage Considerations</title>
<para>
Asynchronous IO means non-blocking IO utilizing few threads, typically at most as many
threads as number of cores. As such, performance may profit from fewer thread switches
and less memory usage due to fewer thread-stacks. But doing synchronous, blocking IO (the
invoke-methods not returning a future) may suffer, because the data has to be transferred
piecewiese to/from the io-threads.
</para>
<para>
Request-Entities are fully buffered in memory, thus <emphasis>HttpAsyncClient</emphasis>
is unsuitable for very large uploads. Response-Entities are buffered in memory, except
if requesting a Response, InputStream or Reader as Result. Thus for large downloads or
COMET one of these three return types must be requested, but there may be a performance
penalty because the response-body is transferred piecewise from the io-threads. When
using InvocationCallbacks, the response is always fully buffered in memory.
</para>
</sect2>
</sect1>
</chapter>

0 comments on commit 1f9a117

Please sign in to comment.