Wei Zhang created CXF-6395:
------------------------------
Summary: Call setTimeout() in a second request cause
illegalStateException from web container.
Key: CXF-6395
URL: https://issues.apache.org/jira/browse/CXF-6395
Project: CXF
Issue Type: Bug
Components: JAX-RS
Reporter: Wei Zhang
Come from a TCK test case:
Resource class has two methods:
static AsyncResponse asyncResponse;
@GET
@Path("/suspend")
public void getSuspendResponse(@Suspended AsyncResponse async) {
asyncResponse = async;
}
@GET
@Path("/setTimeOut")
public String setTimeOut() {
boolean setTimeout = asyncResponse.setTimeout(10, TimeUnit.SECONDS);
return String.valueOf(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)) {
return false;
}
Runnable task = new Runnable() {
@Override
public void run()
{
handleTimeout();
}
};
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.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)