users@grizzly.java.net

Re: Grizzly HTTP servlet: aggressive recycling revisited

From: Matthew Swift <matthew.swift_at_gmail.com>
Date: Tue, 9 Oct 2012 16:28:46 +0200

Hi Alexey,

Don't worry about the slow response, I assumed that you were at Java One.

Answers below:

On 9 October 2012 08:38, Oleksiy Stashok <oleksiy.stashok_at_oracle.com> wrote:

> Hi Matt,
>
> sorry for possible delays, the mailing list didn't work for the last
> couple of days...
>
>
> On 10/05/2012 07:26 PM, Matthew Swift wrote:
>
> I've been thinking about this some more... thoughts below:
>
> On 5 October 2012 18:19, Matthew Swift <matthew.swift_at_gmail.com> wrote:
>
>> [...]
>>
>> 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?
>>
>>
> This has to be a bug, I'm pretty sure of that. There's no point in
> having the method if it's going to never return true. Let me know if you
> agree, and I'll raise an issue in JIRA for it.
>
> Is it easy to reproduce this issue?
> Response.isCommited() has to return true, if response headers have been
> sent to a client; or false otherwise.
> The exception you reported might occur when you call isCommited after
> response has been resumed, is it the case?
>
>

Yes. Basically if I am doing Servlet 3 async processing using an
AsyncContext then the following works:

                        httpResponse.isCommitted();
                        asyncContext.complete();
                        httpResponse.isCommitted();

But the following triggers an IllegalStateException during the second
isCommitted():

                        httpResponse.isCommitted();
                        httpResponse.sendError(404, "Grrr");
                        httpResponse.isCommitted(); // ISE

To me at least httpResponse should always work regardless of whether or the
internal state (Response) has been recycled or not. In other words I'd
expect isCommitted to work like this:

    public boolean isCommitted() {
        final Response tmp = response;
        return tmp != null ? tmp.isCommitted() : true;
    }

Note that the Javadoc for sendError states:

*If the response has already been committed, this method throws an
> IllegalStateException. After using this method, the response should be
> considered to be committed and should not be written to.*



While you cannot "write" to the response it says nothing about querying the
response state. In addition the servlet spec section 3.11 states:

*Containers commonly recycle request objects in order to avoid the
> performance overhead of request object creation. The developer must be
> aware that maintaining references to request objects for which startAsync
> has not been called outside the scope described above is not recommended as
> it may have indeterminate results.*



It's only referring to the request object and says nothing about responses.
I really think that Servlet implementations should be able to do
conditional processing based on the isCommitted() state of a request. For
example, during error handling - an error may be trapped after the response
has been "committed" and error handling code should be able to check
whether or not it is possible to send an error to a client.


We can definitely implement a switch to allow/disallow Request/Response
> recycling, it shouldn't be a problem at all... it may have some perf.
> impact, cause Request/Response objects are relatively expensive, but we can
> definitely try and double check that.
>
>
No please don't :-) Since the Servlet specification permits recycling I'd
prefer if my Servlet implementation was tolerant to this behavior for
interoperability with other containers.

Thanks again,

Matt