Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closing JAX RS Client/Response

It's not clear must I close JAX RS Client/Response instances or not. And if I must, always or not?

According to documentation about the Client class:

Calling this method effectively invalidates all resource targets produced by the client instance.

The WebTarget class does not have any invalidate()/close() method, but the Response class does. According to documentation:

Close the underlying message entity input stream (if available and open) as well as releases any other resources associated with the response (e.g. buffered message entity data).

... The close() method should be invoked on all instances that contain an un-consumed entity input stream to ensure the resources associated with the instance are properly cleaned-up and prevent potential memory leaks. This is typical for client-side scenarios where application layer code processes only the response headers and ignores the response entity.

The last paragraph is not clear to me. What does "un-consumed entity input stream" mean? If I get an InputSteam or a String from response, should I close the response explicitly?

We can get a response result without getting access to Response instance:

Client client = ...;
WebTarget webTarget = ...;
Invocation.Builder builder = webTarget.request(MediaType.APPLICATION_JSON_TYPE);
Invocation invocation = builder.buildGet();
InputStream reso = invocation.invoke(InputStream.class);

I'm working with RESTeasy implementation, and I expected that response will be closed inside of resteasy implementation, but I could not find it. Could anyone tell me why? I know that the Response class will implement Closeable interface But even know, the Response is used, without closing it.

like image 599
Alexandr Avatar asked Oct 12 '15 14:10

Alexandr


2 Answers

In short: do call close() or use closeable with try-with-resources-statements.

  • If you use the JAX-RS Client reference, calling close() on the client closes open sockets.
  • Calling close on Response releases the connection but not any open socket
  • It is not necessary required to call close() since Resteasy will release the connection under the covers. But it should be done if result is an InputStream or if you're dealing with Response results.

Resources/Reference:

According to the Resteasy documentation you should call close() on Response references. In section 47.3 at the end it states that

Resteasy will release the connection under the covers. The only counterexample is the case in which the response is an instance of InputStream, which must be closed explicitly.

On the other hand, if the result of an invocation is an instance of Response, then Response.close() method must be used to released the connection.

You should probably execute this in a try/finally block. Again, releasing a connection only makes it available for another use. It does not normally close the socket.

Note that if ApacheHttpClient4Engine has created its own instance of HttpClient, it is not necessary to wait for finalize() to close open sockets. The ClientHttpEngine interface has a close() method for this purpose.

Finally, if your javax.ws.rs.client.Client class has created the engine automatically for you, you should call Client.close() and this will clean up any socket connections.

like image 57
Jens Kreidler Avatar answered Sep 18 '22 06:09

Jens Kreidler


According to the documentation close() is idempotent.

This operation is idempotent, i.e. it can be invoked multiple times with the same effect which also means that calling the close() method on an already closed message instance is legal and has no further effect.

So you can safely close the InputStream yourself and should.

That being said I style wise would not do invocation.invoke(InputStream.class) as the invoker(Class) is made for doing entity transformation. Instead if you want InputStream you should probably just call invocation.invoke() and deal with the Response object directly as you may want some header info before reading the stream. The reason you want headers when dealing with a response InputStream is typical because you either don't care about the body or the body requires special processing and size considerations which is what the documentation is alluding to (e.g. HEAD request to ping server).

See also link

A message instance returned from this method will be cached for subsequent retrievals via getEntity(). Unless the supplied entity type is an input stream, this method automatically closes the an unconsumed original response entity data stream if open. In case the entity data has been buffered, the buffer will be reset prior consuming the buffered data to enable subsequent invocations of readEntity(...) methods on this response.

So if you choose anything other than InputStream you will not have to close the Response (but regardless its safe to do it anyways as its idempotent).

like image 45
Adam Gent Avatar answered Sep 18 '22 06:09

Adam Gent