spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.58k stars 38.13k forks source link

SseEmitter onError method does not get called on Payara 5 #23668

Closed hsynff closed 5 years ago

hsynff commented 5 years ago

I'm trying below code on Spring MVC (5.1.8 version of dependencies) deployed on Payara 5 (Glassfish) :

@GetMapping("/listen-sse")
public SseEmitter sseEmitter() {
        SseEmitter emitter = new SseEmitter(0L);
        emitter.onError(e -> System.out.println("OnError"));

        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(() -> {
            while (true) {
                try {
                    Thread.sleep(2000);
                    emitter.send("Hello");
                } catch (IOException | InterruptedException e) {
                    System.out.println("Exception");
                    break;
                }
            }
        });

        service.shutdown();
        return emitter;
}

When the client disconnects I can only see "Exception" on console but not "OnError". I've tried the same code with Spring boot (same dependency versions) and embed tomcat everything works as expected.

hsynff commented 5 years ago

I've tested the same war on Tomcat 8.5.42 and onError called

rstoyanchev commented 5 years ago

SseEmitter#onError is a callback connected to the Servlet container via an AsyncListener#onError. This is registered in StandardServletAsyncWebRequest and propagates through the DeferredResult in ResponseBodyEmitter.Handler.

The Servlet container is supposed to notify of async request errors via AsyncListener#onError and in this case it isn't. It could simply be a bug in Glassfish. Or perhaps they intentionally do not notify because of the expectation you would have caught the exception, although that doesn't make sense since an AsyncListener may be completely independent from the code actually writing. So I suspect it is a bug and the fact that it works in Tomcat is another indication.

In any case the bottom line is that SseEmitter#onError is a callback from the Servlet container and if it isn't being called, that's related to the Servlet container.

deeDude commented 4 years ago

This issue also happens with Jetty 9...

rstoyanchev commented 4 years ago

@deeDude, the Jetty 9.x version range spans nearly 7 years. Can you be more specific?

deeDude commented 4 years ago

@deeDude, the Jetty 9.x version range spans nearly 7 years. Can you be more specific?

Sorry for my imprecision, the exact Jetty version is v9.4.22.v20191022, with spring boot v2.2.1