From e6a0b39df5ce6deda90c4fe3b2e712bf28d1938b Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Fri, 24 Jun 2016 17:10:56 +0200 Subject: [PATCH] Remove SseHttpMessageConverter CodecHttpMessageConverter is now suitable for SSE since it now handles default content type. --- .../http/codec/SseEventEncoder.java | 5 +- .../reactive/SseHttpMessageConverter.java | 67 ------------------- .../web/reactive/sse/SseEvent.java | 14 ++-- .../ResponseEntityResultHandlerTests.java | 1 - .../annotation/SseIntegrationTests.java | 7 +- 5 files changed, 16 insertions(+), 78 deletions(-) delete mode 100644 spring-web-reactive/src/main/java/org/springframework/http/converter/reactive/SseHttpMessageConverter.java diff --git a/spring-web-reactive/src/main/java/org/springframework/http/codec/SseEventEncoder.java b/spring-web-reactive/src/main/java/org/springframework/http/codec/SseEventEncoder.java index 505ee42cf0..f06fedc25f 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/codec/SseEventEncoder.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/codec/SseEventEncoder.java @@ -112,11 +112,14 @@ public class SseEventEncoder extends AbstractEncoder { } } + // Keep the SSE connection open even for cold stream in order to avoid + // unexpected browser reconnection return Flux.concat( encodeString(sb.toString(), bufferFactory), dataBuffer, encodeString("\n", bufferFactory), - Mono.just(FlushingDataBuffer.INSTANCE) + Mono.just(FlushingDataBuffer.INSTANCE), + Flux.never() ); }); diff --git a/spring-web-reactive/src/main/java/org/springframework/http/converter/reactive/SseHttpMessageConverter.java b/spring-web-reactive/src/main/java/org/springframework/http/converter/reactive/SseHttpMessageConverter.java deleted file mode 100644 index 705bed7d75..0000000000 --- a/spring-web-reactive/src/main/java/org/springframework/http/converter/reactive/SseHttpMessageConverter.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.http.converter.reactive; - - -import java.util.Arrays; -import java.util.List; - -import org.reactivestreams.Publisher; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.core.ResolvableType; -import org.springframework.core.codec.Encoder; -import org.springframework.http.codec.SseEventEncoder; -import org.springframework.http.MediaType; -import org.springframework.http.ReactiveHttpOutputMessage; -import org.springframework.web.reactive.sse.SseEvent; - -/** - * Implementation of {@link HttpMessageConverter} that can stream Server-Sent Events - * response. - * - * It allows to write {@code Flux}, which is Spring Web Reactive equivalent - * to Spring MVC {@code SseEmitter}. - * - * Sending {@code Flux} or {@code Flux} is equivalent to sending - * {@code Flux} with the {@code data} property set to the {@code String} or - * {@code Pojo} value. - * - * @author Sebastien Deleuze - * @see SseEvent - * @see Server-Sent Events W3C recommandation - */ -public class SseHttpMessageConverter extends CodecHttpMessageConverter { - - /** - * Constructor that creates a new instance configured with the specified data encoders. - */ - public SseHttpMessageConverter(List> dataEncoders) { - super(new SseEventEncoder(dataEncoders), null); - } - - @Override - public Mono write(Publisher inputStream, ResolvableType type, - MediaType contentType, ReactiveHttpOutputMessage outputMessage) { - - outputMessage.getHeaders().add("Content-Type", "text/event-stream"); - // Keep the SSE connection open even for cold stream in order to avoid unexpected Browser reconnection - return super.write(Flux.from(inputStream).concatWith(Flux.never()), type, contentType, outputMessage); - } - -} diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/sse/SseEvent.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/sse/SseEvent.java index 6f0eaf6828..1b2f99b9dc 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/sse/SseEvent.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/sse/SseEvent.java @@ -16,7 +16,7 @@ package org.springframework.web.reactive.sse; -import org.springframework.http.converter.reactive.SseHttpMessageConverter; +import org.springframework.http.codec.SseEventEncoder; import org.springframework.util.MimeType; /** @@ -26,7 +26,7 @@ import org.springframework.util.MimeType; * {@code SseEmitter} type. It allows to send Server-Sent Events in a reactive way. * * @author Sebastien Deleuze - * @see SseHttpMessageConverter + * @see SseEventEncoder * @see Server-Sent Events W3C recommandation */ public class SseEvent { @@ -95,9 +95,9 @@ public class SseEvent { /** * Set {@code data} SSE field. If a multiline {@code String} is provided, it will be * turned into multiple {@code data} field lines by as - * defined in Server-Sent Events W3C recommandation. + * defined in Server-Sent Events W3C recommendation. * - * If no {@code mediaType} is defined, default {@link SseHttpMessageConverter} will: + * If no {@code mediaType} is defined, default {@link SseEventEncoder} will: * - Turn single line {@code String} to a single {@code data} field * - Turn multiline line {@code String} to multiple {@code data} fields * - Serialize other {@code Object} as JSON @@ -117,7 +117,7 @@ public class SseEvent { /** * Set the {@link MimeType} used to serialize the {@code data}. - * {@link SseHttpMessageConverter} should be configured with the relevant encoder to be + * {@link SseEventEncoder} should be configured with the relevant encoder to be * able to serialize it. */ public void setMimeType(MimeType mimeType) { @@ -147,8 +147,8 @@ public class SseEvent { /** * Set SSE comment. If a multiline comment is provided, it will be turned into multiple - * SSE comment lines by {@link SseHttpMessageConverter} as defined in Server-Sent Events W3C - * recommandation. + * SSE comment lines by {@link SseEventEncoder} as defined in Server-Sent Events W3C + * recommendation. */ public void setComment(String comment) { this.comment = comment; diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java index 3cdd9ad26c..ba131de3f2 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/ResponseEntityResultHandlerTests.java @@ -33,7 +33,6 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.io.buffer.support.DataBufferTestUtils; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.reactive.CodecHttpMessageConverter; import org.springframework.http.converter.reactive.HttpMessageConverter; diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java index 1c9b514a29..30cbbecc3d 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java @@ -29,6 +29,7 @@ import reactor.core.test.TestSubscriber; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.codec.Encoder; import org.springframework.core.codec.support.ByteBufferDecoder; import org.springframework.core.codec.support.JacksonJsonDecoder; import org.springframework.core.codec.support.JacksonJsonEncoder; @@ -36,8 +37,9 @@ import org.springframework.core.codec.support.JsonObjectDecoder; import org.springframework.core.codec.support.StringDecoder; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ReactorHttpClientRequestFactory; +import org.springframework.http.codec.SseEventEncoder; +import org.springframework.http.converter.reactive.CodecHttpMessageConverter; import org.springframework.http.converter.reactive.HttpMessageConverter; -import org.springframework.http.converter.reactive.SseHttpMessageConverter; import org.springframework.http.server.reactive.AbstractHttpHandlerIntegrationTests; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.web.bind.annotation.RequestMapping; @@ -165,7 +167,8 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests { @Override protected void extendMessageConverters(List> converters) { - converters.add(new SseHttpMessageConverter(Arrays.asList(new JacksonJsonEncoder()))); + Encoder sseEncoder = new SseEventEncoder(Arrays.asList(new JacksonJsonEncoder())); + converters.add(new CodecHttpMessageConverter<>(sseEncoder)); } } -- GitLab