From 7af7a55ede0cba513836032ff7f12be46b316633 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 5 Jul 2016 12:02:47 -0400 Subject: [PATCH] Polish and simplify JacksonJsonEncoder --- .../http/codec/json/JacksonJsonEncoder.java | 50 ++++++++----------- .../core/codec/ByteBufferEncoderTests.java | 2 +- .../core/codec/ResourceEncoderTests.java | 2 +- .../core/codec/StringEncoderTests.java | 2 +- .../AbstractDataBufferAllocatingTestCase.java | 6 +-- .../support/DataBufferTestUtilsTests.java | 4 +- .../buffer/support/DataBufferUtilsTests.java | 6 +-- .../http/codec/SseEventEncoderTests.java | 8 +-- .../codec/json/JacksonJsonEncoderTests.java | 17 +++---- .../http/codec/xml/Jaxb2EncoderTests.java | 2 +- 10 files changed, 44 insertions(+), 55 deletions(-) diff --git a/spring-web-reactive/src/main/java/org/springframework/http/codec/json/JacksonJsonEncoder.java b/spring-web-reactive/src/main/java/org/springframework/http/codec/json/JacksonJsonEncoder.java index 7499826d7cb..0d7e177d09b 100644 --- a/spring-web-reactive/src/main/java/org/springframework/http/codec/json/JacksonJsonEncoder.java +++ b/spring-web-reactive/src/main/java/org/springframework/http/codec/json/JacksonJsonEncoder.java @@ -46,14 +46,16 @@ import org.springframework.util.MimeType; */ public class JacksonJsonEncoder extends AbstractEncoder { - private final ObjectMapper mapper; - private static final ByteBuffer START_ARRAY_BUFFER = ByteBuffer.wrap(new byte[]{'['}); private static final ByteBuffer SEPARATOR_BUFFER = ByteBuffer.wrap(new byte[]{','}); private static final ByteBuffer END_ARRAY_BUFFER = ByteBuffer.wrap(new byte[]{']'}); + + private final ObjectMapper mapper; + + public JacksonJsonEncoder() { this(new ObjectMapper()); } @@ -66,54 +68,44 @@ public class JacksonJsonEncoder extends AbstractEncoder { this.mapper = mapper; } + @Override - public Flux encode(Publisher inputStream, - DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, - Object... hints) { + public Flux encode(Publisher inputStream, DataBufferFactory bufferFactory, + ResolvableType elementType, MimeType mimeType, Object... hints) { + Assert.notNull(inputStream, "'inputStream' must not be null"); Assert.notNull(bufferFactory, "'bufferFactory' must not be null"); Assert.notNull(elementType, "'elementType' must not be null"); + if (inputStream instanceof Mono) { - // single object - return Flux.from(inputStream) - .map(value -> serialize(value, bufferFactory, elementType)); + return Flux.from(inputStream).map(value -> encodeValue(value, bufferFactory, elementType)); } - else { - // array - Mono startArray = - Mono.just(bufferFactory.wrap(START_ARRAY_BUFFER)); - Flux arraySeparators = - Mono.fromSupplier(() -> bufferFactory.wrap(SEPARATOR_BUFFER)).repeat(); - Mono endArray = - Mono.just(bufferFactory.wrap(END_ARRAY_BUFFER)); - - Flux serializedObjects = Flux.from(inputStream) - .map(value -> serialize(value, bufferFactory, elementType)); - Flux array = Flux.zip(serializedObjects, arraySeparators) - .flatMap(tuple -> Flux.just(tuple.getT1(), tuple.getT2())); + Flux array = Flux.from(inputStream) + .flatMap(value -> + Flux.just(encodeValue(value, bufferFactory, elementType), + bufferFactory.wrap(SEPARATOR_BUFFER))); - Flux arrayWithoutLastSeparator = array.skipLast(1); - - return Flux.concat(startArray, arrayWithoutLastSeparator, endArray); - } + return Flux.concat(Mono.just(bufferFactory.wrap(START_ARRAY_BUFFER)), array.skipLast(1), + Mono.just(bufferFactory.wrap(END_ARRAY_BUFFER))); } - private DataBuffer serialize(Object value, DataBufferFactory dataBufferFactory, - ResolvableType type) { + private DataBuffer encodeValue(Object value, DataBufferFactory bufferFactory, ResolvableType type) { TypeFactory typeFactory = this.mapper.getTypeFactory(); JavaType javaType = typeFactory.constructType(type.getType()); ObjectWriter writer = this.mapper.writerFor(javaType); - DataBuffer buffer = dataBufferFactory.allocateBuffer(); + + DataBuffer buffer = bufferFactory.allocateBuffer(); OutputStream outputStream = buffer.asOutputStream(); + try { writer.writeValue(outputStream, value); } catch (IOException e) { throw new CodecException("Error while writing the data", e); } + return buffer; } - } diff --git a/spring-web-reactive/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java b/spring-web-reactive/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java index dc44221899d..157724d3b17 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/codec/ByteBufferEncoderTests.java @@ -61,7 +61,7 @@ public class ByteBufferEncoderTests extends AbstractDataBufferAllocatingTestCase Flux source = Flux.just(ByteBuffer.wrap(fooBytes), ByteBuffer.wrap(barBytes)); - Flux output = this.encoder.encode(source, this.dataBufferFactory, + Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClassWithGenerics(Publisher.class, ByteBuffer.class), null); TestSubscriber diff --git a/spring-web-reactive/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java b/spring-web-reactive/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java index 75bb8a07c38..b27f987a2a5 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/codec/ResourceEncoderTests.java @@ -62,7 +62,7 @@ public class ResourceEncoderTests extends AbstractDataBufferAllocatingTestCase { Mono source = Mono.just(resource); - Flux output = this.encoder.encode(source, this.dataBufferFactory, + Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClass(Resource.class), null); diff --git a/spring-web-reactive/src/test/java/org/springframework/core/codec/StringEncoderTests.java b/spring-web-reactive/src/test/java/org/springframework/core/codec/StringEncoderTests.java index 6bcf51c6ca5..2a4e60f18c2 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/codec/StringEncoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/codec/StringEncoderTests.java @@ -59,7 +59,7 @@ public class StringEncoderTests extends AbstractDataBufferAllocatingTestCase { @Test public void write() throws InterruptedException { Flux output = Flux.from( - this.encoder.encode(Flux.just("foo"), this.dataBufferFactory, null, null)) + this.encoder.encode(Flux.just("foo"), this.bufferFactory, null, null)) .map(chunk -> { byte[] b = new byte[chunk.readableByteCount()]; chunk.read(b); diff --git a/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java b/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java index 8afe4d5abf7..1ec7c9990a2 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/AbstractDataBufferAllocatingTestCase.java @@ -37,7 +37,7 @@ import static org.junit.Assert.assertEquals; public abstract class AbstractDataBufferAllocatingTestCase { @Parameterized.Parameter - public DataBufferFactory dataBufferFactory; + public DataBufferFactory bufferFactory; @Parameterized.Parameters(name = "{0}") public static Object[][] dataBufferFactories() { @@ -53,12 +53,12 @@ public abstract class AbstractDataBufferAllocatingTestCase { } protected DataBuffer createDataBuffer(int capacity) { - return this.dataBufferFactory.allocateBuffer(capacity); + return this.bufferFactory.allocateBuffer(capacity); } protected DataBuffer stringBuffer(String value) { byte[] bytes = value.getBytes(StandardCharsets.UTF_8); - DataBuffer buffer = this.dataBufferFactory.allocateBuffer(bytes.length); + DataBuffer buffer = this.bufferFactory.allocateBuffer(bytes.length); buffer.write(bytes); return buffer; } diff --git a/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferTestUtilsTests.java b/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferTestUtilsTests.java index 6c5012e5a58..1763f4bbce7 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferTestUtilsTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferTestUtilsTests.java @@ -33,7 +33,7 @@ public class DataBufferTestUtilsTests extends AbstractDataBufferAllocatingTestCa @Test public void dumpBytes() { - DataBuffer buffer = this.dataBufferFactory.allocateBuffer(4); + DataBuffer buffer = this.bufferFactory.allocateBuffer(4); byte[] source = {'a', 'b', 'c', 'd'}; buffer.write(source); @@ -46,7 +46,7 @@ public class DataBufferTestUtilsTests extends AbstractDataBufferAllocatingTestCa @Test public void dumpString() { - DataBuffer buffer = this.dataBufferFactory.allocateBuffer(4); + DataBuffer buffer = this.bufferFactory.allocateBuffer(4); String source = "abcd"; buffer.write(source.getBytes(StandardCharsets.UTF_8)); diff --git a/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferUtilsTests.java b/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferUtilsTests.java index 63029c58822..51dc81833fa 100644 --- a/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferUtilsTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/core/io/buffer/support/DataBufferUtilsTests.java @@ -42,7 +42,7 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase { .toURI(); FileChannel channel = FileChannel.open(Paths.get(uri), StandardOpenOption.READ); - Flux flux = DataBufferUtils.read(channel, this.dataBufferFactory, 4); + Flux flux = DataBufferUtils.read(channel, this.bufferFactory, 4); TestSubscriber .subscribe(flux) @@ -61,7 +61,7 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase { .toURI(); FileChannel channel = FileChannel.open(Paths.get(uri), StandardOpenOption.READ); - Flux flux = DataBufferUtils.read(channel, this.dataBufferFactory, 3); + Flux flux = DataBufferUtils.read(channel, this.bufferFactory, 3); TestSubscriber .subscribe(flux) @@ -80,7 +80,7 @@ public class DataBufferUtilsTests extends AbstractDataBufferAllocatingTestCase { InputStream is = DataBufferUtilsTests.class .getResourceAsStream("DataBufferUtilsTests.txt"); - Flux flux = DataBufferUtils.read(is, this.dataBufferFactory, 4); + Flux flux = DataBufferUtils.read(is, this.bufferFactory, 4); TestSubscriber .subscribe(flux) diff --git a/spring-web-reactive/src/test/java/org/springframework/http/codec/SseEventEncoderTests.java b/spring-web-reactive/src/test/java/org/springframework/http/codec/SseEventEncoderTests.java index 352f8d47993..bb5b0996a7d 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/codec/SseEventEncoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/codec/SseEventEncoderTests.java @@ -64,7 +64,7 @@ public class SseEventEncoderTests extends AbstractDataBufferAllocatingTestCase { event.setComment("bla\nbla bla\nbla bla bla"); event.setReconnectTime(123L); Mono source = Mono.just(event); - Flux output = encoder.encode(source, this.dataBufferFactory, + Flux output = encoder.encode(source, this.bufferFactory, ResolvableType.forClass(SseEvent.class), new MimeType("text", "event-stream")); TestSubscriber .subscribe(output) @@ -84,7 +84,7 @@ public class SseEventEncoderTests extends AbstractDataBufferAllocatingTestCase { public void encodeString() { SseEventEncoder encoder = new SseEventEncoder(Arrays.asList(new JacksonJsonEncoder())); Flux source = Flux.just("foo", "bar"); - Flux output = encoder.encode(source, this.dataBufferFactory, + Flux output = encoder.encode(source, this.bufferFactory, ResolvableType.forClass(String.class), new MimeType("text", "event-stream")); TestSubscriber .subscribe(output) @@ -103,7 +103,7 @@ public class SseEventEncoderTests extends AbstractDataBufferAllocatingTestCase { public void encodeMultilineString() { SseEventEncoder encoder = new SseEventEncoder(Arrays.asList(new JacksonJsonEncoder())); Flux source = Flux.just("foo\nbar", "foo\nbaz"); - Flux output = encoder.encode(source, this.dataBufferFactory, + Flux output = encoder.encode(source, this.bufferFactory, ResolvableType.forClass(String.class), new MimeType("text", "event-stream")); TestSubscriber .subscribe(output) @@ -122,7 +122,7 @@ public class SseEventEncoderTests extends AbstractDataBufferAllocatingTestCase { public void encodePojo() { SseEventEncoder encoder = new SseEventEncoder(Arrays.asList(new JacksonJsonEncoder())); Flux source = Flux.just(new Pojo("foofoo", "barbar"), new Pojo("foofoofoo", "barbarbar")); - Flux output = encoder.encode(source, this.dataBufferFactory, + Flux output = encoder.encode(source, this.bufferFactory, ResolvableType.forClass(Pojo.class), new MimeType("text", "event-stream")); TestSubscriber .subscribe(output) diff --git a/spring-web-reactive/src/test/java/org/springframework/http/codec/json/JacksonJsonEncoderTests.java b/spring-web-reactive/src/test/java/org/springframework/http/codec/json/JacksonJsonEncoderTests.java index ebcfe78b19f..b7249a03315 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/codec/json/JacksonJsonEncoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/codec/json/JacksonJsonEncoderTests.java @@ -39,11 +39,13 @@ public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCas private JacksonJsonEncoder encoder; + @Before public void createEncoder() { this.encoder = new JacksonJsonEncoder(); } + @Test public void canEncode() { assertTrue(this.encoder.canEncode(null, MediaType.APPLICATION_JSON)); @@ -57,13 +59,10 @@ public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCas new Pojo("foofoo", "barbar"), new Pojo("foofoofoo", "barbarbar") ); - ResolvableType type = ResolvableType.forClass(Pojo.class); - Flux output = - this.encoder.encode(source, this.dataBufferFactory, type, null); + Flux output = this.encoder.encode(source, this.bufferFactory, type, null); - TestSubscriber - .subscribe(output) + TestSubscriber.subscribe(output) .assertComplete() .assertNoError() .assertValuesWith( @@ -80,13 +79,10 @@ public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCas @Test public void encodeWithType() { Flux source = Flux.just(new Foo(), new Bar()); - ResolvableType type = ResolvableType.forClass(ParentClass.class); - Flux output = - this.encoder.encode(source, this.dataBufferFactory, type, null); + Flux output = this.encoder.encode(source, this.bufferFactory, type, null); - TestSubscriber - .subscribe(output) + TestSubscriber.subscribe(output) .assertComplete() .assertNoError() .assertValuesWith(stringConsumer("["), @@ -96,6 +92,7 @@ public class JacksonJsonEncoderTests extends AbstractDataBufferAllocatingTestCas stringConsumer("]")); } + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") private static class ParentClass { } diff --git a/spring-web-reactive/src/test/java/org/springframework/http/codec/xml/Jaxb2EncoderTests.java b/spring-web-reactive/src/test/java/org/springframework/http/codec/xml/Jaxb2EncoderTests.java index 4476cfcaf73..4c51b88268a 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/codec/xml/Jaxb2EncoderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/codec/xml/Jaxb2EncoderTests.java @@ -71,7 +71,7 @@ public class Jaxb2EncoderTests extends AbstractDataBufferAllocatingTestCase { @Test public void encode() { Flux source = Flux.just(new Pojo("foofoo", "barbar"), new Pojo("foofoofoo", "barbarbar")); - Flux output = this.encoder.encode(source, this.dataBufferFactory, + Flux output = this.encoder.encode(source, this.bufferFactory, ResolvableType.forClass(Pojo.class), MediaType.APPLICATION_XML); TestSubscriber