英文:
How to close a proxied RESTEasy WebTarget
问题
以下是翻译的内容:
给定以下的RESTEasy代码片段:
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);
我可以/可以/应该关闭 WebTarget
或 Client
以释放我分配的资源。
然而,如果代理对象的创建以及其依赖关系都被交给一个类似如下的独立类:
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) 如何在这里清理资源?
如何关闭 `WebTarget` 或 `Client` 或它们的底层资源?我无法通过代理实例访问它们中的任何一个。如果我*不*关闭它们,我会收到这个可怕的警告:
> RESTEASY004687:正在为您关闭类 org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine 的实例。请自行关闭客户端。
因此,RESTEasy会为我清理资源,但当然这不是我应该依赖的。
<details>
<summary>英文:</summary>
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. https://stackoverflow.com/q/33097230/131929 and https://stackoverflow.com/q/24700798/131929 about what is reusable and what not
</details>
# 答案1
**得分**: 0
感谢 @james-r-perkins 的反馈,最终我得出了以下(Kotlin)代码:
```kotlin
final inline fun <reified T : AutoCloseable> createServiceProxy(
serviceName: String
): T = RestClientBuilder.newBuilder()
.baseUri(createServiceUriBuilder(serviceName).build())
.register(MyClientRequestFilter(appName, tokenProvider))
.build(T::class.java)
与我早前的评论相反,RESTEasy MP RestClientBuilderImpl
和Quarkus QuarkusRestClientBuilder
都创建了代理,而且这些代理也实现了 Closeable
(它扩展了 AutoCloseable
),正如 James 所说的...
然而,我们认为强制要求我们的客户端接口直接扩展 AutoCloseable
是有价值的。当然,这在源代码中会增加一些额外的字符,但从正面来看,这是编译器可以使用的类型信息,以便我们可以简化其他地方的代码。因此,在这里很重要的是泛型声明为 T : AutoCloseable
而不是 T : Any
。
英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论