Creating Text Stream Using Spring WebFlux
up vote
0
down vote
favorite
I've been using Spring WebFlux to create a text stream, here is the code.
@SpringBootApplication
@RestController
public class ReactiveServer {
private static final String FILE_PATH = "c:/test/";
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/events")
Flux<String> events() {
Flux<String> eventFlux = Flux.fromStream(Stream.generate(() -> FileReader.readFile()));
Flux<Long> durationFlux = Flux.interval(Duration.ofMillis(500));
return Flux.zip(eventFlux, durationFlux).map(Tuple2::getT1);
}
public static void main(String args) {
SpringApplication.run(ReactiveServer.class, args);
}
}
When I access the /events url on the browser I get this, that's almost what I want to get:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
What I need to do is to insert a "ping:" in between iterations to get:
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
But, the best I could get was:
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
Does anyone know of a way to what I need?
java spring-boot spring-webflux
add a comment |
up vote
0
down vote
favorite
I've been using Spring WebFlux to create a text stream, here is the code.
@SpringBootApplication
@RestController
public class ReactiveServer {
private static final String FILE_PATH = "c:/test/";
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/events")
Flux<String> events() {
Flux<String> eventFlux = Flux.fromStream(Stream.generate(() -> FileReader.readFile()));
Flux<Long> durationFlux = Flux.interval(Duration.ofMillis(500));
return Flux.zip(eventFlux, durationFlux).map(Tuple2::getT1);
}
public static void main(String args) {
SpringApplication.run(ReactiveServer.class, args);
}
}
When I access the /events url on the browser I get this, that's almost what I want to get:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
What I need to do is to insert a "ping:" in between iterations to get:
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
But, the best I could get was:
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
Does anyone know of a way to what I need?
java spring-boot spring-webflux
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I've been using Spring WebFlux to create a text stream, here is the code.
@SpringBootApplication
@RestController
public class ReactiveServer {
private static final String FILE_PATH = "c:/test/";
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/events")
Flux<String> events() {
Flux<String> eventFlux = Flux.fromStream(Stream.generate(() -> FileReader.readFile()));
Flux<Long> durationFlux = Flux.interval(Duration.ofMillis(500));
return Flux.zip(eventFlux, durationFlux).map(Tuple2::getT1);
}
public static void main(String args) {
SpringApplication.run(ReactiveServer.class, args);
}
}
When I access the /events url on the browser I get this, that's almost what I want to get:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
What I need to do is to insert a "ping:" in between iterations to get:
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
But, the best I could get was:
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
Does anyone know of a way to what I need?
java spring-boot spring-webflux
I've been using Spring WebFlux to create a text stream, here is the code.
@SpringBootApplication
@RestController
public class ReactiveServer {
private static final String FILE_PATH = "c:/test/";
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, value = "/events")
Flux<String> events() {
Flux<String> eventFlux = Flux.fromStream(Stream.generate(() -> FileReader.readFile()));
Flux<Long> durationFlux = Flux.interval(Duration.ofMillis(500));
return Flux.zip(eventFlux, durationFlux).map(Tuple2::getT1);
}
public static void main(String args) {
SpringApplication.run(ReactiveServer.class, args);
}
}
When I access the /events url on the browser I get this, that's almost what I want to get:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
What I need to do is to insert a "ping:" in between iterations to get:
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
But, the best I could get was:
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379993662,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":0,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994203,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data: ping:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379994706,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":2,"rollingCountBadRequests":0}
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542379995213,"isCircuitBreakerOpen":false,"errorPercentage":0,"errorCount":0,"requestCount":3,"rollingCountBadRequests":0}
Does anyone know of a way to what I need?
java spring-boot spring-webflux
java spring-boot spring-webflux
edited yesterday
asked Nov 16 at 15:29
Nelson Larios
286
286
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
You could try returning a Flux<ServerSentEvent>
and specify the type of event you're trying to send. Like this:
@RestController
public class TestController {
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, path = "/events")
Flux<ServerSentEvent> events() {
Flux<String> events = Flux.interval(Duration.ofMillis(200)).map(String::valueOf);
Flux<ServerSentEvent<String>> sseData = events.map(event -> ServerSentEvent.builder(event).build());
Flux<ServerSentEvent<String>> ping = Flux.interval(Duration.ofMillis(500))
.map(l -> ServerSentEvent.builder("").event("ping").build());
return Flux.merge(sseData, ping);
}
}
With that code snippet, I'm getting the following output:
$ http --stream :8080/events
HTTP/1.1 200 OK
Content-Type: text/event-stream;charset=UTF-8
transfer-encoding: chunked
data:0
data:1
event:ping
data:
data:2
data:3
data:4
event:ping
data:
Which is consistent with Server Sent Events. Is the ping:
prefix something specific to Hystrix? If it is, I don't think this is consistent with the SSE spec and that it's something supported in Spring Framework.
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
When I run your code "ping:" doesn't print. I get this:data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
I've edited my answer
– Brian Clozel
yesterday
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
You could try returning a Flux<ServerSentEvent>
and specify the type of event you're trying to send. Like this:
@RestController
public class TestController {
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, path = "/events")
Flux<ServerSentEvent> events() {
Flux<String> events = Flux.interval(Duration.ofMillis(200)).map(String::valueOf);
Flux<ServerSentEvent<String>> sseData = events.map(event -> ServerSentEvent.builder(event).build());
Flux<ServerSentEvent<String>> ping = Flux.interval(Duration.ofMillis(500))
.map(l -> ServerSentEvent.builder("").event("ping").build());
return Flux.merge(sseData, ping);
}
}
With that code snippet, I'm getting the following output:
$ http --stream :8080/events
HTTP/1.1 200 OK
Content-Type: text/event-stream;charset=UTF-8
transfer-encoding: chunked
data:0
data:1
event:ping
data:
data:2
data:3
data:4
event:ping
data:
Which is consistent with Server Sent Events. Is the ping:
prefix something specific to Hystrix? If it is, I don't think this is consistent with the SSE spec and that it's something supported in Spring Framework.
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
When I run your code "ping:" doesn't print. I get this:data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
I've edited my answer
– Brian Clozel
yesterday
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
add a comment |
up vote
0
down vote
You could try returning a Flux<ServerSentEvent>
and specify the type of event you're trying to send. Like this:
@RestController
public class TestController {
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, path = "/events")
Flux<ServerSentEvent> events() {
Flux<String> events = Flux.interval(Duration.ofMillis(200)).map(String::valueOf);
Flux<ServerSentEvent<String>> sseData = events.map(event -> ServerSentEvent.builder(event).build());
Flux<ServerSentEvent<String>> ping = Flux.interval(Duration.ofMillis(500))
.map(l -> ServerSentEvent.builder("").event("ping").build());
return Flux.merge(sseData, ping);
}
}
With that code snippet, I'm getting the following output:
$ http --stream :8080/events
HTTP/1.1 200 OK
Content-Type: text/event-stream;charset=UTF-8
transfer-encoding: chunked
data:0
data:1
event:ping
data:
data:2
data:3
data:4
event:ping
data:
Which is consistent with Server Sent Events. Is the ping:
prefix something specific to Hystrix? If it is, I don't think this is consistent with the SSE spec and that it's something supported in Spring Framework.
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
When I run your code "ping:" doesn't print. I get this:data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
I've edited my answer
– Brian Clozel
yesterday
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
add a comment |
up vote
0
down vote
up vote
0
down vote
You could try returning a Flux<ServerSentEvent>
and specify the type of event you're trying to send. Like this:
@RestController
public class TestController {
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, path = "/events")
Flux<ServerSentEvent> events() {
Flux<String> events = Flux.interval(Duration.ofMillis(200)).map(String::valueOf);
Flux<ServerSentEvent<String>> sseData = events.map(event -> ServerSentEvent.builder(event).build());
Flux<ServerSentEvent<String>> ping = Flux.interval(Duration.ofMillis(500))
.map(l -> ServerSentEvent.builder("").event("ping").build());
return Flux.merge(sseData, ping);
}
}
With that code snippet, I'm getting the following output:
$ http --stream :8080/events
HTTP/1.1 200 OK
Content-Type: text/event-stream;charset=UTF-8
transfer-encoding: chunked
data:0
data:1
event:ping
data:
data:2
data:3
data:4
event:ping
data:
Which is consistent with Server Sent Events. Is the ping:
prefix something specific to Hystrix? If it is, I don't think this is consistent with the SSE spec and that it's something supported in Spring Framework.
You could try returning a Flux<ServerSentEvent>
and specify the type of event you're trying to send. Like this:
@RestController
public class TestController {
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE, path = "/events")
Flux<ServerSentEvent> events() {
Flux<String> events = Flux.interval(Duration.ofMillis(200)).map(String::valueOf);
Flux<ServerSentEvent<String>> sseData = events.map(event -> ServerSentEvent.builder(event).build());
Flux<ServerSentEvent<String>> ping = Flux.interval(Duration.ofMillis(500))
.map(l -> ServerSentEvent.builder("").event("ping").build());
return Flux.merge(sseData, ping);
}
}
With that code snippet, I'm getting the following output:
$ http --stream :8080/events
HTTP/1.1 200 OK
Content-Type: text/event-stream;charset=UTF-8
transfer-encoding: chunked
data:0
data:1
event:ping
data:
data:2
data:3
data:4
event:ping
data:
Which is consistent with Server Sent Events. Is the ping:
prefix something specific to Hystrix? If it is, I don't think this is consistent with the SSE spec and that it's something supported in Spring Framework.
edited yesterday
answered 2 days ago
Brian Clozel
28.9k67097
28.9k67097
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
When I run your code "ping:" doesn't print. I get this:data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
I've edited my answer
– Brian Clozel
yesterday
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
add a comment |
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
When I run your code "ping:" doesn't print. I get this:data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
I've edited my answer
– Brian Clozel
yesterday
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
HI, Brian, thanks for you answer. What I'm trying to do is to create a data stream in exactly the way the Hystrix Dashboard expects it to be. I think it uses the "ping:" String between events as a kind of separation. So your answer gives me something like: So what I really need is just to print that "ping:" at the beginning of an event. But without the "data:". Like this: ping: Not like this: data:ping:
– Nelson Larios
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
that's what my sample is doing: sending SSE events of type data (the default) and ping. They're currently just interleaved and the ping events are scheduled with a specific duration between them.
– Brian Clozel
yesterday
When I run your code "ping:" doesn't print. I get this:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
When I run your code "ping:" doesn't print. I get this:
data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382826545} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827046} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382827547} data:{"type":"HystrixCommand","name":"GetConsumerCommand","group":"ConsumerRemoteGroup","currentTime":1542382828049}
– Nelson Larios
yesterday
I've edited my answer
– Brian Clozel
yesterday
I've edited my answer
– Brian Clozel
yesterday
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
Hi Brian, it's specific to Hystrix. It's a shame I can't do it with WebFlux. I close to a solution using reactivex. Thank you very much for you efforts.
– Nelson Larios
19 hours ago
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53340867%2fcreating-text-stream-using-spring-webflux%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown