Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[jetty-dev] Continuation considerations - wrapping?

All,

Another thing that I'm pondering with jetty-7 continuations is the support of
wrapping.


With servlet-3.0 the async API support the wrapping of both requests and responses.
this means that if you call  request.startAsync(wrappedREquest,wrappedResponse)
then the wrapped req/res are used when doing any subsequent async dispatch.


Up until earlier today, the jetty-7 continuation API was attempting to mimic
this capability.   But there were several problems:

 1) technically it was difficult to come up with a way to keep the wrappers
    and use them for all dispatches for all containers (2.5, 3.0, jetty-6
    and jetty-7).   There was going to be significant extra cost in being
    able to generally keep these wrappers on non 3.0 containers.

 2) Keeping wrappers is generally not useful.   Either wrappers are heavy
    weight... in which case you don't want to keep them while suspended
    as they consume resources that you would be best freed; or they are
    lightweight, in which case it is cheap to re-apply then on any subsequent
    redispatch.

 3) The api continuation.getRequest() is mis-leading, as it represents that
    it would be reasonable to access request fields at any time.   But
    if an async handler called continuation.getRequest().getServletPath()
    it would get different answers depending on where the real request
    was (in a RequestDispatcher.forward(), in a servlet, parked in the container).


So considering this, I've kind of decided that I don't want to support
wrapping in general.

But there is one specific case where wrapping is useful.   If the async
model that is being used is suspend() followed by a complete(), then
the request is not redispatched and it is reasonable for a async handler
to use a response wrapper.


So the compromise that I have now implemented (and would like to get
feedback on), is that there is an optional method

  continuation.suspend(Response wrapper)

You would use this if you intended to eventually call complete()
Thus there are now two distinct patterns of async usage:


  Filter/Servlet:
    continuation.suspend()

  ...

  Async Handler:
    continuation.resume()
  Filter/Servlet:
    response.getOutputStream().write(response);


vs

  Filter/Servlet:
    continuation.suspend(response)

  Filter:
    try{chain.doFilter(request,wrappedResponse)}
    finally{
       if (!continuation.isResponseWrapped())
           wrappedResponse.finish()
    }

  ...

  Async Handler:
    continuation.getServletResponse().getOutputStream().write(response);
    continuation.complete()



If this is not too objectionable, I guess I should write this up in the javadoc
and in the wiki.


cheers






















Back to the top