Reusing JAX RS Client in multi-threaded environment (with resteasy)

java, jax-rs, jersey, multithreading, resteasy

Solution

Your implementation is not thread-safe. When two threads access `someMethod` at the same time they are sharing the same `Client` and one will try to make a second request while the first one is not finished.

You have two choices:

- Synchronize the access to the `Client` and `WebTarget` manually.

- Let the container manage concurrency by annotating the enclosing type with `@javax.ejb.Singleton` which guarantees thread safety. (see chapter 4.8.5 of the EJB specification)

If `someMethod` in a container managed environment I would use the second approach.

Problem

According to the documentation, "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. " Ok, I'm trying to cache Client itself and WebTarget instances in a static variable, the someMethod() is invoked in multi-threaded environment: ``` private static Client client = ClientBuilder.newClient(); private static WebTarget webTarget = client.target("someBaseUrl"); ... public static String someMethod(String arg1, String arg2) { WebTarget target = entrTarget.queryParam("arg1", arg1).queryParam("arg2", arg2); Response response = target.request().get(); final String result = response.readEntity(String.class); response.close(); return result; } ``` But sometimes (not always) I'm get an exception: Invalid use of BasicClientConnManager: connection still allocated. Make sure to release the connection before allocating another one. How can Client/WebTarget be reused/cached correctly? Is it possible with JAX RS Client API? Or I have to use some framework-specific features (resteasy/jersey) Could you provide some example or documentation?

Original source

Related problems