Chapter 45. Resteasy Client API (original) (raw)
Network communication between the client and server is handled in Resteasy, by default, by HttpClient (4.x) from the Apache HttpComponents project. In general, the interface between the Resteasy Client Framework and the network is found in an implementation oforg.jboss.resteasy.client.jaxrs.ClientHttpEngine
, andorg.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine
, which uses HttpClient (4.x), is the default implementation. Resteasy also ships with the following client engines, all found in theorg.jboss.resteasy.client.jaxrs.engines
package:
- URLConnectionClientExecutor: uses
java.net.HttpURLConnection
; - InMemoryClientExecutor: dispatches requests to a server in the same JVM.
and a client executor may be passed to a specific ClientRequest
:
ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build();
Resteasy and HttpClient make reasonable default decisions so that it is possible to use the client framework without ever referencing HttpClient, but for some applications it may be necessary to drill down into the HttpClient details. ApacheHttpClient4Engine
can be supplied with an instance of org.apache.http.client.HttpClient
and an instance of org.apache.http.protocol.HttpContext
, which can carry additional configuration details into the HttpClient layer. For example, authentication may be configured as follows:
// Configure HttpClient to authenticate preemptively // by prepopulating the authentication data cache.
// 1. Create AuthCache instance AuthCache authCache = new BasicAuthCache();
// 2. Generate BASIC scheme object and add it to the local auth cache BasicScheme basicAuth = new BasicScheme(); authCache.put("com.bluemonkeydiamond.sippycups", basicAuth);
// 3. Add AuthCache to the execution context BasicHttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
// 4. Create client executor and proxy httpClient = new DefaultHttpClient(); ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient, localContext); ResteasyClient client = new RestasyClientBuilder().httpEngine(engine).build();
One default decision made by HttpClient and adopted by Resteasy is the use oforg.apache.http.impl.conn.SingleClientConnManager
, which manages a single socket at any given time and which supports the use case in which one or more invocations are made serially from a single thread. For multithreaded applications, SingleClientConnManager
may be replaced by org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager
:
ClientConnectionManager cm = new ThreadSafeClientConnManager(); HttpClient httpClient = new DefaultHttpClient(cm); ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
Note. It is important to understand the difference between "releasing" a connection and "closing" a connection. Releasing a connection makes it available for reuse. Closing a connection frees its resources and makes it unusable.
SingleClientConnManager
manages a single socket, which it allocates to at most a single invocation at any given time. Before that socket can be reused, it has to be released from its current use, which can occur in one of two ways. If an execution of a request or a call on a proxy returns a class other than Response
, then Resteasy will take care of releasing the connection. For example, in the fragments
Resteasy will release the connection under the covers. The only counterexample is the case in which the response is an instance of InputStream
, which must be closed explicitly.
On the other hand, if the result of an invocation is an instance ofResponse
, then Response.close() method must be used to released the connection.
You should probably execute this in a try/finally block. Again, releasing a connection only makes it available for another use. It does not normally close the socket.
On the other hand,ApacheHttpClient4Engine.finalize()
will close any open sockets, but only if it created the HttpClient
it has been using. If an HttpClient
has been passed into theApacheHttpClient4Executor
, then the user is responsible for closing the connections:
Note that if ApacheHttpClient4Engine
has created its own instance of HttpClient
, it is not necessary to wait for finalize()
to close open sockets. TheClientHttpEngine
interface has a close()
method for this purpose.
Finally, if your javax.ws.rs.client.Client class has created the engine automatically for you, you should call Client.close() and this will clean up any socket connections.