0

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

Marcel Stör
  • 22,695
  • 19
  • 92
  • 198
  • What version of RESTEasy are you using? – James R. Perkins Feb 17 '23 at 20:59
  • RedHat Quarkus ships with RESTEasy 4.7.7. – Marcel Stör Feb 17 '23 at 22:17
  • If you use the MP REST Client it extends `AutoCloseable` and allows the connection to be closed. That seems like a reasonable feature request in RESTEasy to me. – James R. Perkins Feb 17 '23 at 22:22
  • Hhh, that seems like a really valuable hint, thanks. Sorry, this is all so new to me that I first had to figure out what "MP" stands for. I checked the docs at https://docs.jboss.org/resteasy/docs/4.7.7.Final/userguide/html/MicroProfile_Rest_Client.html; currently analyzing how to potentially migrate our code base. What is e.g. the MP equivalent to this: `ClientBuilder.newBuilder().build().target(urlBuilder.build()).register(MyClientRequestFilter(appName, tokenProvider))`? – Marcel Stör Feb 17 '23 at 22:44
  • Something like this `RestClientBuilder.newBuilder() .baseUri(urlBuilder.build()) .register(yClientRequestFilter(appName, tokenProvider)) .build(MoviesResource.class);`. You can also just inject it with CDI. – James R. Perkins Feb 20 '23 at 15:54
  • Thanks James. I was bit stuck on your earlier statement: "use the MP REST Client it extends `AutoCloseable`". Looking at `RestClientDelegateBean.destroy()` and the `CloseableClientTest` you recently added, isn't it more like "let the proxy interface extend `AutoCloseable` such that MP RESTEasy can close it"? – Marcel Stör Feb 21 '23 at 08:27
  • That is to say that I didn't find any code that would support the claim that MP `RestClientBuilder.build()` would automatically create an `AutoCloseable` proxy. Btw, I'm working with Quarkus which ships with its own almost-copy of that builder (`QuarkusRestClientBuilder`). – Marcel Stör Feb 21 '23 at 15:30
  • Yes, sorry that I was't clear. The MP spec requires the proxy extend `Closeable` or `AutoCloseable` if the interface does not already extend one of them https://download.eclipse.org/microprofile/microprofile-rest-client-3.0/microprofile-rest-client-spec-3.0.html#lifecycle. With CDI it automatically closes the proxy when the proxy is destroyed. – James R. Perkins Feb 21 '23 at 15:35

1 Answers1

0

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.

Marcel Stör
  • 22,695
  • 19
  • 92
  • 198