Description
Come from a TCK test case:
Resource class has two methods:
static AsyncResponse asyncResponse;
@GET
@Path("/suspend")
public void getSuspendResponse(@Suspended AsyncResponse async)
@GET
@Path("/setTimeOut")
public String setTimeOut()
The first request invokes method getSuspendResponse(), the AsyncResponse is in suspend status. The second request invokes method setTimeOut() to invoke setTimeOut() method of the suspend AsyncRespone. AsyncResponseImp.setTimeout() -> cont.suspend(timeout)(Servlet3ContinuationProvider$Servlet3Continuation) -> context.setTimeout(timeout);
The the impl class of AsyncContext throw a illegalStateException: called setTimeout after the container-initiated dispatch which called startAsync has returned.
According to the javadoc of AsyncContext class, seemed the behavior of AsyncContext is correct. We tried to challenge this test case, but was rejected.
Checked restesay code, found they thought the invocation is illegal, but they provide a work around:
protected WeakReference<Thread> creatingThread = new WeakReference<Thread>(Thread.currentThread());
protected ScheduledFuture timeoutFuture; // this is to get around TCK tests that call setTimeout in a separate thread which is illegal.
protected ScheduledExecutorService asyncScheduler;
public synchronized boolean setTimeout(long time, TimeUnit unit) throws IllegalStateException {
......
Thread thread = creatingThread.get();
if (thread != null && thread != Thread.currentThread()) {
// this is to get around TCK tests that call setTimeout in a separate thread which is illegal.
if (timeoutFuture != null && !timeoutFuture.cancel(false))
Runnable task = new Runnable() {
@Override
public void run()
};
timeoutFuture = asyncScheduler.schedule(task, time, unit);
return true;
} else
}
Check if current thread is the creating thread of AsyncResponseImpl object, if not, means setTimeout() method is called in a second request, then handle the timeout with a ScheduledExecutorService instead of AsyncContext to avoid the illegalState exception.
I tried to add above code to setTimeout() method. It's ok when setTimeout() was called, and handleTimeout() method was called also when timeout. But client can't get a response which said timeout until connection timeout.