How to correctly share JAX-RS 2.0 client
Asked Answered
H

1

16

To give a little context to my issue...

I have a Java EE web application (as a UI / client) that accesses services for data / business logic via a REST interface using the JAX-RS 2.0 client API (Resteasy implementation).

Currently I inject a new JAXRS Client instance per request using a RequestScoped CDI managed bean, the thinking being that the client app may call multiple backend resources per request and I reuse the same JAXRS Client for the whole request (although I read somewhere this may not be correct as I am potentially changing the URI for each invocation)

The documentation for JAXRS Client seems to suggest that the client is a potentially expensive operation and the app should limit the amount of connections it creates. It also seems to contradict itself and suggest the client should be closed once all the requests to a particular WebTarget are finished.

The client application could potentially support thousands of simultaneous users so creating and destroying thousands of 'expensive clients' does not seem to be the correct approach so am thinking a shared client pool is more appropriate but there doesn't seem to be any information on how this should be achieved.

All examples appear to show creating a new client for the request and a) closing it after or b) not closing it but not really explaining what happens on a second request.

Can you help provide some answers on how you think this would be solved or information on what the best practice for this approach is.

Thanks.

Hutt answered 2/1, 2016 at 13:11 Comment(0)
C
17

The only "best-practice" advice I've seen for avoiding either poor performance or poor memory usage patterns with a JAX-RS 2.0 client relates to the Jersey implementation of Jax-RS and so it may not be valid for RestEasy. However, I suspect that the two implementations are similar enough that the advice is portable.

Basically, my understanding is

  • use ClientBuilder to create a small number of fully-configured Client instances - you may need different clients with different configurations (e.g. Serialisation/Deserialisation providers) in different situations. This sort of thing should probably happen around application initialisation, or similar kind of 'rare' events.
  • share each fully-configured Client instance among classes with the same configuration requirements. You might tell your DI framework, for example, to scope each of those Client instances as @Singleton.
  • avoid calling any methods on Client instances which modify the underlying configuration. Examples are things like register(Class<T> componentClass) - pretty much anything on the javax.ws.rs.core.Configurable interface.
  • Each instance object using a shared Client can (and should?) create its own, private and non-shared, WebTargets. Effectively, it's WebTargets which should be @RequestScoped and not Clients.
  • However, as with Client, anything using a WebTarget should avoid doing any diddling via the javax.ws.rs.core.Configurable interface methods.

After that it's pretty much plain sailing.

Corroboration answered 2/1, 2016 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.