I am experimenting with Spring DeferredResult on Tomcat and I am getting crazy results. Is this what I'm doing wrong, or is there some kind of bug in Spring or Tomcat? My code is pretty simple.
@Controller public class Test { private DeferredResult<String> deferred; static class DoSomethingUseful implements Runnable { public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { } } } @RequestMapping(value="/test/start") @ResponseBody public synchronized DeferredResult<String> start() { deferred = new DeferredResult<>(4000L, "timeout\n"); deferred.onTimeout(new DoSomethingUseful()); return deferred; } @RequestMapping(value="/test/stop") @ResponseBody public synchronized String stop() { deferred.setResult("stopped\n"); return "ok\n"; } }
So. The start request creates a DeferredResult with a 4 second timeout. The stop request will set the result to DeferredResult . If you send stop before or after the expiration of the grace period, everything works fine.
However, if you send stop at the same time that the start time has expired, everything becomes crazy. I added the onTimeout action so that it is easy to reproduce, but this is not necessary for the problem to occur. With an APR connector, it simply locks. It sometimes works with the NIO connector, but sometimes it incorrectly sends a timeout message to the stop client and never answers the start client.
To check this:
curl http://localhost/test/start & sleep 5; curl http://localhost/test/stop
I do not think that I am doing something wrong. Spring's documentation seems to say that you can call setResult at any time, even after the request has already expired, and from any thread ("the application can produce the result from the stream of its choice").
Used versions: Tomcat 7.0.39 on Linux, Spring 3.2.2.
source share