diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/InboundJsonToTupleConversionTest.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/InboundJsonToTupleConversionTest.java new file mode 100644 index 000000000..cb3044c99 --- /dev/null +++ b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/InboundJsonToTupleConversionTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017 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.cloud.stream.config; + +import java.util.concurrent.TimeUnit; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.stream.annotation.EnableBinding; +import org.springframework.cloud.stream.binder.BinderFactory; +import org.springframework.cloud.stream.messaging.Processor; +import org.springframework.cloud.stream.test.binder.TestSupportBinder; +import org.springframework.context.annotation.PropertySource; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHeaders; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.tuple.Tuple; +import org.springframework.tuple.TupleBuilder; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Marius Bogoevici + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = InboundJsonToTupleConversionTest.FooProcessor.class) +public class InboundJsonToTupleConversionTest { + + @Autowired + private Processor testProcessor; + + @Autowired + private BinderFactory binderFactory; + + @Test + public void testInboundJsonTupleConversion() throws Exception { + testProcessor.input().send(MessageBuilder.withPayload("{'name':'foo'}") + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json").build()); + @SuppressWarnings("unchecked") + Message received = ((TestSupportBinder) binderFactory.getBinder(null, MessageChannel.class)) + .messageCollector().forChannel(testProcessor.output()).poll(1, TimeUnit.SECONDS); + assertThat(received).isNotNull(); + assertThat(received.getPayload()).isEqualTo(TupleBuilder.tuple().of("name","foo")); + } + + + @EnableBinding(Processor.class) + @EnableAutoConfiguration + @PropertySource("classpath:/org/springframework/cloud/stream/config/inboundjsontuple/inbound-json-tuple.properties") + public static class FooProcessor { + + @ServiceActivator(inputChannel = "input", outputChannel = "output") + public Tuple consume(Tuple tuple) { + return tuple; + } + + } + +} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/MessageChannelConfigurerTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/MessageChannelConfigurerTests.java index a9c62ca5d..0f41ffa71 100644 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/MessageChannelConfigurerTests.java +++ b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/MessageChannelConfigurerTests.java @@ -37,6 +37,7 @@ import org.springframework.integration.support.MessageBuilder; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessagingException; +import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.messaging.converter.MessageConverter; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.tuple.Tuple; @@ -81,15 +82,17 @@ public class MessageChannelConfigurerTests { @Test public void testObjectMapperConfig() throws Exception { - MessageConverter converter = messageConverterFactory.getMessageConverterForType(MimeTypeUtils + CompositeMessageConverter converters = (CompositeMessageConverter) messageConverterFactory.getMessageConverterForType(MimeTypeUtils .APPLICATION_JSON); - DirectFieldAccessor converterAccessor = new DirectFieldAccessor(converter); - ObjectMapper objectMapper = (ObjectMapper) converterAccessor.getPropertyValue("objectMapper"); - // assert that the ObjectMapper used by the converters is compliant with the Boot configuration - assertThat(!objectMapper.getSerializationConfig().isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) - .withFailMessage("SerializationFeature 'WRITE_DATES_AS_TIMESTAMPS' should be disabled"); - // assert that the globally set bean is used by the converters - assertThat(objectMapper).isSameAs(this.objectMapper); + for (MessageConverter converter : converters.getConverters()) { + DirectFieldAccessor converterAccessor = new DirectFieldAccessor(converter); + ObjectMapper objectMapper = (ObjectMapper) converterAccessor.getPropertyValue("objectMapper"); + // assert that the ObjectMapper used by the converters is compliant with the Boot configuration + assertThat(!objectMapper.getSerializationConfig().isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) + .withFailMessage("SerializationFeature 'WRITE_DATES_AS_TIMESTAMPS' should be disabled"); + // assert that the globally set bean is used by the converters + assertThat(objectMapper).isSameAs(this.objectMapper); + } } @EnableBinding(Sink.class) diff --git a/spring-cloud-stream-integration-tests/src/test/resources/org/springframework/cloud/stream/config/inboundjsontuple/inbound-json-tuple.properties b/spring-cloud-stream-integration-tests/src/test/resources/org/springframework/cloud/stream/config/inboundjsontuple/inbound-json-tuple.properties new file mode 100644 index 000000000..52309356b --- /dev/null +++ b/spring-cloud-stream-integration-tests/src/test/resources/org/springframework/cloud/stream/config/inboundjsontuple/inbound-json-tuple.properties @@ -0,0 +1 @@ +spring.cloud.stream.bindings.input.content-type=application/x-spring-tuple diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/converter/TupleJsonMessageConverter.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/converter/TupleJsonMessageConverter.java index c2a12d23b..bc7ca5261 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/converter/TupleJsonMessageConverter.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/converter/TupleJsonMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2016 the original author or authors. + * Copyright 2015-2017 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. @@ -18,6 +18,7 @@ package org.springframework.cloud.stream.converter; import java.io.IOException; import java.nio.charset.Charset; +import java.util.Arrays; import com.fasterxml.jackson.databind.ObjectMapper; @@ -27,12 +28,14 @@ import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.converter.AbstractMessageConverter; import org.springframework.tuple.Tuple; import org.springframework.tuple.TupleBuilder; +import org.springframework.util.MimeTypeUtils; /** * A {@link org.springframework.messaging.converter.MessageConverter} * to convert a {@link Tuple} to a JSON String * @author David Turanski * @author Ilayaperumal Gopinathan + * @author Marius Bogoevici */ public class TupleJsonMessageConverter extends AbstractMessageConverter { @@ -46,7 +49,7 @@ public class TupleJsonMessageConverter extends AbstractMessageConverter { } public TupleJsonMessageConverter(ObjectMapper objectMapper) { - super(MessageConverterUtils.X_SPRING_TUPLE); + super(Arrays.asList(MessageConverterUtils.X_SPRING_TUPLE, MimeTypeUtils.APPLICATION_JSON)); this.objectMapper = (objectMapper != null) ? objectMapper : new ObjectMapper(); }