users@grizzly.java.net

Grizzly HTTP servlet: aggressive recycling revisited

From: Matthew Swift <matthew.swift_at_gmail.com>
Date: Fri, 5 Oct 2012 18:19:01 +0200

Hi there,

I'm still having problems with the aggressive recycling that Grizzly does
with HttpServletResponse objects, but this time it's nothing to do with
timeouts...

I'm running into stuff like this all the time:

Caused by: java.lang.IllegalStateException: Null response object
at
org.glassfish.grizzly.servlet.HttpServletResponseImpl.isCommitted(HttpServletResponseImpl.java:391)
at org.forgerock.json.resource.servlet.HttpUtils.fail(HttpUtils.java:167)
at
org.forgerock.json.resource.servlet.HttpServletAdapter.doGet(HttpServletAdapter.java:284)
at
org.forgerock.json.resource.servlet.HttpServlet.doGet(HttpServlet.java:141)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at
org.forgerock.json.resource.servlet.HttpServlet.service(HttpServlet.java:283)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:770)
at
org.glassfish.grizzly.servlet.FilterChainImpl.doFilter(FilterChainImpl.java:147)

Where the fail method is doing this:

    static void fail(final HttpServletResponse resp, final Exception e) {
        if (!resp.isCommitted()) {
            try {
                resp.sendError(...);
            } catch (final IOException ignored) {
                // Ignore the error since this was probably the cause.
            }
        }
    }

The call to resp.isCommitted() is the one triggering the exception, which
seems a little harsh! How can it ever return true since, when a response is
committed, I get an exception instead?

At the moment I'm having to be really careful about how I use these APIs.
In particular, I have to be super careful not to try and accidentally
complete a response more than once (the sort of thing that is pretty easy
to do when unrolling the stack through try...finally blocks. In addition,
I've had to be really careful to avoid accidentally closing the response's
output stream after the response has completed since this causes an NPE
(remembering that the stream may be closed automatically by other wrapper
layers like Jackson). In fact I would go say this is definitely a bug -
close() is usually idempotent and robust against multiple invocations.

Any thoughts?

Matt