Given the following RESTEasy snippet
UriBuilder FULL_PATH = UriBuilder.fromPath("http://127.0.0.1:8080/movies");
ResteasyClient client = (ResteasyClient)ClientBuilder.newClient();
ResteasyWebTarget target = client.target(FULL_PATH);
MoviesResource proxy = target.proxy(MoviesResource.class);
Movie movie = proxy.movieById(someId);
I could/can/should close WebTarget
or Client
to free resources I allocated*.
However, what do I do if the creation of the proxy object and everything it depends on is handed off to a separate class like so:
public class Foo {
private UriBuilder FULL_PATH = UriBuilder.fromPath("http://127.0.0.1:8080/movies");
public MoviesResource getMoviesApi() {
ResteasyClient client = (ResteasyClient)ClientBuilder.newClient();
ResteasyWebTarget target = client.target(FULL_PATH);
return target.proxy(MoviesResource.class);
}
}
...
MoviesResource proxy = myFoo.getMoviesApi();
Movie movie = proxy.movieById(someId);
// A) how to clean up here?
How do I close the WebTarget
or Client
or their underlying resources? I can't get access to either of them through the proxied instance.
If I do not close them I get this dreaded warning
RESTEASY004687: Closing a class org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine instance for you. Please close clients yourself.
Hence, RESTEasy does clean up for me but that's of course not what I should rely on.
*there are discussions in a number of places eg. Reusing JAX RS Client in multi-threaded environment (with resteasy) and Is JAX-RS Client Thread Safe about what is reusable and what not
Thanks to all the feedback from @james-r-perkins I eventually I arrived at the following (Kotlin) code:
final inline fun <reified T : AutoCloseable> createServiceProxy(
serviceName: String
): T = RestClientBuilder.newBuilder()
.baseUri(createServiceUriBuilder(serviceName).build())
.register(MyClientRequestFilter(appName, tokenProvider))
.build(T::class.java)
Contrary to my earlier comment both the RESTEasy MP RestClientBuilderImpl
and the Quarkus QuarkusRestClientBuilder
DO create proxies that also implement Closeable
(which extends AutoCloseable
). Just as James said...
However, we see value in enforcing that our client interfaces extend AutoCloseable
directly. Sure, it's a few extra characters in the source code but on the plus-side it's type information the compiler can use to allow us to simplify code elsewhere. Hence, it's crucial here that the generics declaration is T : AutoCloseable
rather than T : Any
.