spring-projects / spring-framework

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

HTTP Streaming and Server-Sent Events (SSE) [SPR-12212] #16826

Closed spring-projects-issues closed 8 years ago

spring-projects-issues commented 10 years ago

Rossen Stoyanchev opened SPR-12212 and commented

Spring 4 SockJS support already provides an SEE transport that can be used even in browsers that don't support websocket.

The purpose of this ticket is to provide explicit support for Server-Sent Events in @RequestMapping methods in addition to the Callable and DeferredResult return types.

At present Callable and DeferredResult provide a simple way for a controller to produce a return value asynchronously once and then resume processing. This works for any annotated controller method and supports the full range of options, i.e. @ResponseBody or view resolution, handler interception, exception resolution, etc.

For SSE we'll need to support returning multiple values at different times. This will likely result very specifically in an HttpMessageConverter writing each value to the response.


Affects: 4.1 GA

Sub-tasks:

Issue Links:

Referenced from: commits https://github.com/spring-projects/spring-framework/commit/935ffc5827554d593e6fa8c148b4f3630dc2d918, https://github.com/spring-projects/spring-framework/commit/a32b5e61d0b5dff9c09cc3c7d7b8e5e68ac69ae5

5 votes, 12 watchers

spring-projects-issues commented 10 years ago

Marc Logemann commented

at the end the DeferredResult or DeferredStreamResult ;-) must be able to mimic the following behaviour (in Spring MVC, you will have DeferredResults in a list and not AsyncContexts as shown below)

for (AsyncContext asyncContext : queue) {
    ServletResponse response = asyncContext.getResponse();
    response.setContentType("text/event-stream"); //not good in a loop called multiple times
    PrintWriter out = response.getWriter();
    out.printf("data: 123\n\n");  
    out.flush();
}                    
spring-projects-issues commented 10 years ago

Marc Logemann commented

As a SSE feature bonus the Spring team might think about a special SSE bean (with attributes which mimic the SSE protocol like "data", "retry", "id" and others) and create a MessageConverter which serialize this into proper SSE wire protocol like:

data: xxxxx \n
id: yyyy \n
retry: i \n
\n

people then could simply use this bean in conjunction with the DeferredResult without bothering about the protocol itself like:

// somwhere in the controller
DeferredStreamResult<SseBean> dsResult = new DeferredStreamResult<>();
return dsResult;

// somewhere else which processes on all active DeferredResults 
SseBean sseBean = new SseBean("my Data");
dsResult.setResult(sseBean); //which keeps open the connection
dsResult.setResult(sse2Bean); // which should act on the same responsestream
spring-projects-issues commented 9 years ago

Rossen Stoyanchev commented

This is now in master. See commit a32b5e. Marc Logemann take a look and see if it meets your expectations.

spring-projects-issues commented 9 years ago

Lissandro Dittmar commented

Why not on 4.1.5?

spring-projects-issues commented 9 years ago

Juergen Hoeller commented

4.1.5 is about to be released next week, so basically done except for a few remaining bug reports. And our SSE support is still a prototype - a complete feature, but still very fresh, not much integration-tested yet etc. We'd rather take the extra time until 4.2 RC1 to fine-tune it, reconsidering class names etc.

Note that it's just about three months until 4.2 RC1 - with the release candidate being date-driven and not feature-driven, so it won't be delayed. Feel free to use 4.2 snapshots for the time being... They are in pretty stable state, just with the chance of a few recent classes getting renamed or refactored still.

Juergen

spring-projects-issues commented 9 years ago

Bernhard Frauendienst commented

Do I see this correctly that it's impossible to set a custom timeout on the AsyncContext when using an *Emitter? This seems very undesirable for most SSE use-cases, which should have a much higher timeout than the usual server-default of 10-30s.

spring-projects-issues commented 9 years ago

Rossen Stoyanchev commented

Indeed, you do have an option in the MVC Java config (and the MVC namespace) to configure the default timeout for async requests (see this for example. But there is no way to modify that value on a per request basis. Feel free to create a new ticket to add a timeout value to SseEmitter and ResponseBodyEmitter.