I asked (and answered myself) this question a couple of days ago, and resolved the problem, but I can't quite understand why the problem was solved and was hoping to get some clarification.
Essentially, I have implemented a jax-rs-based REST service that retrieves information from a RavenDB database and returns that content in a stream. The problem that I had was an unclosed database results iterator, which caused the REST service to hang (and accept no further requests) after exactly 10 requests.
My code is, roughly, as follows:
public Response ...
{
(...)
StreamingOutput adminAreaStream = new StreamingOutput()
{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
@Override
public void write(OutputStream output) throws IOException, WebApplicationException
{
try(IDocumentSession currentSession = ServiceListener.ravenDBStore.openSession())
{
Writer writer = new BufferedWriter(new OutputStreamWriter(output));
(...)
CloseableIterator<StreamResult<AdministrativeArea>> results;
(...)
writer.flush();
writer.close();
results.close();
currentSession.advanced().clear();
currentSession.close();
}
catch (Exception e)
{
System.out.println("Exception: " + e.getMessage() + e.getStackTrace());
}
}
};
if(!requestIsValid)
return Response.status(400).build();
else
return Response.ok(adminAreaStream).build();
}
From what I understand about the object lifecycle in Java, or rather more specifically object reachability and garbage collection, even though I didn't properly close that CleasableIterator, it should go out of scope/become unreachable by the time my method finishes with either a 400 or 200 status - and therefore get garbage collected.
Just to be clear: I am certainly not suggesting that one shouldn't properly close opened connections etc. - I AM doing that now - or rely on Java's garbage collection mechanism to save us from lazy/unclean coding... I am just struggling to understand exactly how those unclosed iterators could have caused the Tomcat behaviour observed.
In fact, my assumption is that we don't even need to know the details about the iterator's implementation, because at the "galactic level" of Java the object lifecycle, implementation differences are irrelevant. => "Once an object has become unreachable, it doesn't matter exactly how it was coded". The only thing I can imagine is that Tomcat somehow, (through its container mechanism ?), slightly changes the game here, and causes things to "hang around". Could someone please shed some light on this ?
Thanks in advance !