diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java index 740dbcc18a..777157c02f 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/config/WebReactiveConfiguration.java @@ -46,6 +46,7 @@ import org.springframework.core.convert.support.ReactiveStreamsToCompletableFutu import org.springframework.core.convert.support.ReactiveStreamsToRxJava1Converter; import org.springframework.format.Formatter; import org.springframework.http.MediaType; +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.ResourceHttpMessageConverter; @@ -241,6 +242,7 @@ public class WebReactiveConfiguration implements ApplicationContextAware { * {@link #configureMessageConverters(List)}. */ protected final void addDefaultHttpMessageConverters(List> converters) { + List> sseDataEncoders = new ArrayList<>(); converters.add(converter(new ByteBufferEncoder(), new ByteBufferDecoder())); converters.add(converter(new StringEncoder(), new StringDecoder())); converters.add(new ResourceHttpMessageConverter()); @@ -248,9 +250,14 @@ public class WebReactiveConfiguration implements ApplicationContextAware { converters.add(converter(new Jaxb2Encoder(), new Jaxb2Decoder())); } if (jackson2Present) { - JsonObjectDecoder objectDecoder = new JsonObjectDecoder(); - converters.add(converter(new JacksonJsonEncoder(), new JacksonJsonDecoder(objectDecoder))); + JacksonJsonEncoder jacksonEncoder = new JacksonJsonEncoder(); + JacksonJsonDecoder jacksonDecoder = new JacksonJsonDecoder(new JsonObjectDecoder()); + converters.add(converter(jacksonEncoder, jacksonDecoder)); + sseDataEncoders.add(jacksonEncoder); + } else { + } + converters.add(converter(new SseEventEncoder(sseDataEncoders), null)); } private static HttpMessageConverter converter(Encoder encoder, Decoder decoder) { diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/WebReactiveConfigurationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/WebReactiveConfigurationTests.java index 0f4e8e32c7..962bd32c85 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/WebReactiveConfigurationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/config/WebReactiveConfigurationTests.java @@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlRootElement; import org.junit.Before; import org.junit.Test; +import static org.springframework.http.MediaType.*; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import rx.Observable; @@ -139,13 +140,14 @@ public class WebReactiveConfigurationTests { assertNotNull(adapter); List> converters = adapter.getMessageConverters(); - assertEquals(5, converters.size()); + assertEquals(6, converters.size()); - assertHasConverter(converters, ByteBuffer.class, MediaType.APPLICATION_OCTET_STREAM); - assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN); - assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_XML); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_JSON); + assertHasConverter(converters, ByteBuffer.class, APPLICATION_OCTET_STREAM, APPLICATION_OCTET_STREAM); + assertHasConverter(converters, String.class, TEXT_PLAIN, TEXT_PLAIN); + assertHasConverter(converters, Resource.class, IMAGE_PNG, IMAGE_PNG); + assertHasConverter(converters, TestBean.class, APPLICATION_XML, APPLICATION_XML); + assertHasConverter(converters, TestBean.class, APPLICATION_JSON, APPLICATION_JSON); + assertHasConverter(converters, TestBean.class, null, MediaType.parseMediaType("text/event-stream")); name = "mvcConversionService"; ConversionService service = context.getBean(name, ConversionService.class); @@ -168,8 +170,8 @@ public class WebReactiveConfigurationTests { List> converters = adapter.getMessageConverters(); assertEquals(2, converters.size()); - assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_XML); + assertHasConverter(converters, String.class, TEXT_PLAIN, TEXT_PLAIN); + assertHasConverter(converters, TestBean.class, APPLICATION_XML, APPLICATION_XML); } @Test @@ -195,13 +197,14 @@ public class WebReactiveConfigurationTests { assertEquals(0, handler.getOrder()); List> converters = handler.getMessageConverters(); - assertEquals(5, converters.size()); + assertEquals(6, converters.size()); - assertHasConverter(converters, ByteBuffer.class, MediaType.APPLICATION_OCTET_STREAM); - assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN); - assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_XML); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_JSON); + assertHasConverter(converters, ByteBuffer.class, APPLICATION_OCTET_STREAM, APPLICATION_OCTET_STREAM); + assertHasConverter(converters, String.class, TEXT_PLAIN, TEXT_PLAIN); + assertHasConverter(converters, Resource.class, IMAGE_PNG, IMAGE_PNG); + assertHasConverter(converters, TestBean.class, APPLICATION_XML, APPLICATION_XML); + assertHasConverter(converters, TestBean.class, APPLICATION_JSON, APPLICATION_JSON); + assertHasConverter(converters, TestBean.class, null, MediaType.parseMediaType("text/event-stream")); name = "mvcContentTypeResolver"; RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class); @@ -219,13 +222,14 @@ public class WebReactiveConfigurationTests { assertEquals(100, handler.getOrder()); List> converters = handler.getMessageConverters(); - assertEquals(5, converters.size()); + assertEquals(6, converters.size()); - assertHasConverter(converters, ByteBuffer.class, MediaType.APPLICATION_OCTET_STREAM); - assertHasConverter(converters, String.class, MediaType.TEXT_PLAIN); - assertHasConverter(converters, Resource.class, MediaType.IMAGE_PNG); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_XML); - assertHasConverter(converters, TestBean.class, MediaType.APPLICATION_JSON); + assertHasConverter(converters, ByteBuffer.class, APPLICATION_OCTET_STREAM, APPLICATION_OCTET_STREAM); + assertHasConverter(converters, String.class, TEXT_PLAIN, TEXT_PLAIN); + assertHasConverter(converters, Resource.class, IMAGE_PNG, IMAGE_PNG); + assertHasConverter(converters, TestBean.class, APPLICATION_XML, APPLICATION_XML); + assertHasConverter(converters, TestBean.class, APPLICATION_JSON, APPLICATION_JSON); + assertHasConverter(converters, TestBean.class, null, MediaType.parseMediaType("text/event-stream")); name = "mvcContentTypeResolver"; RequestedContentTypeResolver resolver = context.getBean(name, RequestedContentTypeResolver.class); @@ -254,10 +258,12 @@ public class WebReactiveConfigurationTests { } - private void assertHasConverter(List> converters, Class clazz, MediaType mediaType) { + private void assertHasConverter(List> converters, Class clazz, + MediaType readMediaType, MediaType writeMediaType) { ResolvableType type = ResolvableType.forClass(clazz); assertTrue(converters.stream() - .filter(c -> c.canRead(type, mediaType) && c.canWrite(type, mediaType)) + .filter(c -> (readMediaType == null || c.canRead(type, readMediaType)) + && (writeMediaType == null || c.canWrite(type, writeMediaType))) .findAny() .isPresent()); }