public class AsyncContextImpl implements AsyncContext {
public static enum AsyncState {
- NOT_STARTED, STARTED, DISPATCHING, DISPATCHED, COMPLETING, TIMING_OUT, ERROR_DISPATCHING
+ NOT_STARTED, STARTED, DISPATCHING, DISPATCHING_INTERNAL, DISPATCHED,
+ COMPLETING, TIMING_OUT, ERROR_DISPATCHING
}
private static final Log log = LogFactory.getLog(AsyncContextImpl.class);
log.debug("AsyncContext Start Called["+state.get()+"; "+request.getRequestURI()+"?"+request.getQueryString()+"]", new DebugException());
}
- if (state.compareAndSet(AsyncState.STARTED, AsyncState.DISPATCHING) ||
- state.compareAndSet(AsyncState.DISPATCHED, AsyncState.DISPATCHING)) {
+ if (state.compareAndSet(AsyncState.STARTED, AsyncState.DISPATCHING_INTERNAL) ||
+ state.compareAndSet(AsyncState.DISPATCHED, AsyncState.DISPATCHING_INTERNAL)) {
// TODO SERVLET3 - async
final ServletContext sctx = getServletRequest().getServletContext();
Runnable r = new Runnable() {
dispatch = null;
}
}
+ } else if (this.state.get() == AsyncState.DISPATCHING_INTERNAL) {
+ if (this.dispatch!=null) {
+ try {
+ dispatch.run();
+ } catch (RuntimeException x) {
+ doInternalComplete(true);
+ if (x.getCause() instanceof ServletException) throw (ServletException)x.getCause();
+ if (x.getCause() instanceof IOException) throw (IOException)x.getCause();
+ else throw new ServletException(x);
+ } finally {
+ dispatch = null;
+ this.state.set(AsyncState.DISPATCHED);
+ }
+ }
} else if (this.state.get()==AsyncState.COMPLETING) {
doInternalComplete(false);
} else {
rather than an empty string. (markt)
</fix>
<fix>
+ <bug>49528</bug>: Ensure AsyncContext.isAsyncStarted() returns the
+ correct value after AsyncContext.start(). Tomcat implements this
+ using an internal dispatch that requires slightly different treatment
+ from a standard dispatch to ensure the correct value is returned.
+ (markt)
+ </fix>
+ <fix>
<bug>49530</bug>: Contexts and Servlets not stopped when Tomcat is shut
down. (markt)
</fix>