From 2fe7cf58c12fa084c1f1e4a078f542c696b60de6 Mon Sep 17 00:00:00 2001 From: Soby Chacko Date: Fri, 7 Jan 2022 17:53:41 -0500 Subject: [PATCH] Initial take on removing StreamListener StreamListener was deprecated in 3.0.x. This commit is the initial one in removing StreamListener and it's related components completely in 4.0.x. More tests need to be adjusted and migrated which will be addressed in later commits. --- .../stream/binder/AbstractBinderTests.java | 222 ---- ...ListenerAnnotatedMethodArgumentsTests.java | 192 --- ...notationBeanPostProcessorOverrideTest.java | 106 -- .../StreamListenerAsMetaAnnotationTests.java | 147 --- ...eamListenerContentTypeConversionTests.java | 77 -- .../StreamListenerDuplicateMappingTests.java | 127 -- .../StreamListenerHandlerBeanTests.java | 150 --- .../StreamListenerHandlerMethodTests.java | 623 --------- .../StreamListenerMessageArgumentTests.java | 125 -- ...mListenerMethodRegisteredOnlyOnceTest.java | 76 -- ...stenerMethodReturnWithConversionTests.java | 200 --- ...mListenerMethodSetupOrchestratorTests.java | 161 --- ...mListenerMethodWithReturnMessageTests.java | 125 -- ...eamListenerMethodWithReturnValueTests.java | 120 -- .../config/StreamListenerTestUtils.java | 105 -- ...enerWithAnnotatedInputOutputArgsTests.java | 185 --- .../StreamListenerWithConditionsTest.java | 144 -- .../config/TextPlainToJsonConversionTest.java | 123 -- .../TextPlainToJsonConversionTest.java.todo | 123 ++ .../config/contentType/ContentTypeTests.java | 272 ---- .../contentType/ContentTypeTests.java.todo | 272 ++++ .../stream/annotation/StreamListener.java | 180 --- ...spatchingStreamListenerMessageHandler.java | 149 --- ...ageChannelStreamListenerResultAdapter.java | 63 - ...amListenerAnnotationBeanPostProcessor.java | 571 -------- .../binding/StreamListenerErrorMessages.java | 133 -- .../binding/StreamListenerMessageHandler.java | 70 - .../binding/StreamListenerMethodUtils.java | 185 --- .../StreamListenerParameterAdapter.java | 55 - .../binding/StreamListenerResultAdapter.java | 52 - ...StreamListenerSetupMethodOrchestrator.java | 137 -- .../config/BindingServiceConfiguration.java | 13 - .../stream/binder/ErrorBindingTests.java | 43 +- .../binder/tck/ContentTypeTckTests.java | 1163 ----------------- .../binder/tck/ContentTypeTckTests.java.todo | 1163 +++++++++++++++++ .../stream/binder/tck/ErrorHandlingTests.java | 104 -- .../binder/tck/ErrorHandlingTests.java.todo | 104 ++ .../stream/binder/test/SampleStreamApp.java | 91 -- .../binder/test/SampleStreamApp.java.todo | 91 ++ .../ImplicitFunctionBindingTests.java | 33 +- 40 files changed, 1787 insertions(+), 6288 deletions(-) delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotatedMethodArgumentsTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotationBeanPostProcessorOverrideTest.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAsMetaAnnotationTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerContentTypeConversionTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerDuplicateMappingTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerBeanTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerMethodTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMessageArgumentTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodRegisteredOnlyOnceTest.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodReturnWithConversionTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodSetupOrchestratorTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnMessageTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnValueTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerTestUtils.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithAnnotatedInputOutputArgsTests.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithConditionsTest.java delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java create mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java.todo delete mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java create mode 100644 spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java.todo delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/annotation/StreamListener.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/DispatchingStreamListenerMessageHandler.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/MessageChannelStreamListenerResultAdapter.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerErrorMessages.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMessageHandler.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMethodUtils.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerParameterAdapter.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerResultAdapter.java delete mode 100644 spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerSetupMethodOrchestrator.java delete mode 100644 spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java create mode 100644 spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java.todo delete mode 100644 spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java create mode 100644 spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java.todo delete mode 100644 spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java create mode 100644 spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java.todo diff --git a/spring-cloud-stream-binder-test/src/main/java/org/springframework/cloud/stream/binder/AbstractBinderTests.java b/spring-cloud-stream-binder-test/src/main/java/org/springframework/cloud/stream/binder/AbstractBinderTests.java index c3933d00a..c96bd78f1 100644 --- a/spring-cloud-stream-binder-test/src/main/java/org/springframework/cloud/stream/binder/AbstractBinderTests.java +++ b/spring-cloud-stream-binder-test/src/main/java/org/springframework/cloud/stream/binder/AbstractBinderTests.java @@ -17,10 +17,7 @@ package org.springframework.cloud.stream.binder; import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -34,9 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; -import org.springframework.cloud.stream.binder.AbstractBinderTests.Station.Readings; import org.springframework.cloud.stream.binding.MessageConverterConfigurer; -import org.springframework.cloud.stream.binding.StreamListenerMessageHandler; import org.springframework.cloud.stream.config.BindingProperties; import org.springframework.cloud.stream.config.BindingServiceProperties; import org.springframework.cloud.stream.converter.CompositeMessageConverterFactory; @@ -51,12 +46,8 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.converter.SmartMessageConverter; -import org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver; -import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite; -import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; import org.springframework.util.Assert; import org.springframework.util.MimeTypeUtils; -import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -424,193 +415,6 @@ public abstract class AbstractBinderTests producerBinding = binder.bindProducer( - String.format("bad%s0a", getDestinationNameDelimiter()), - moduleOutputChannel, producerBindingProperties.getProducer()); - - Binding consumerBinding = binder.bindConsumer( - String.format("bad%s0a", getDestinationNameDelimiter()), "test-1", - moduleInputChannel, consumerBindingProperties.getConsumer()); - - Station station = new Station(); - Message message = MessageBuilder.withPayload(station).build(); - moduleInputChannel.subscribe(handler); - moduleOutputChannel.send(message); - - QueueChannel replyChannel = (QueueChannel) handler.getOutputChannel(); - - Message replyMessage = replyChannel.receive(5000); - assertThat(replyMessage.getPayload() instanceof Station).isTrue(); - producerBinding.unbind(); - consumerBinding.unbind(); - } - - @SuppressWarnings("rawtypes") - @Test - public void testSendJsonReceivePojoWithStreamListener(TestInfo testInfo) throws Exception { - StreamListenerMessageHandler handler = this.buildStreamListener( - AbstractBinderTests.class, "echoStation", Station.class); - Binder binder = getBinder(); - - BindingProperties producerBindingProperties = createProducerBindingProperties( - createProducerProperties(testInfo)); - - DirectChannel moduleOutputChannel = createBindableChannel("output", - producerBindingProperties); - - BindingProperties consumerBindingProperties = createConsumerBindingProperties( - createConsumerProperties()); - - DirectChannel moduleInputChannel = createBindableChannel("input", - consumerBindingProperties); - - Binding producerBinding = binder.bindProducer( - String.format("bad%s0d", getDestinationNameDelimiter()), - moduleOutputChannel, producerBindingProperties.getProducer()); - - Binding consumerBinding = binder.bindConsumer( - String.format("bad%s0d", getDestinationNameDelimiter()), "test-4", - moduleInputChannel, consumerBindingProperties.getConsumer()); - - String value = "{\"readings\":[{\"stationid\":\"fgh\"," - + "\"customerid\":\"12345\",\"timestamp\":null}," - + "{\"stationid\":\"hjk\",\"customerid\":\"222\",\"timestamp\":null}]}"; - - Message message = MessageBuilder.withPayload(value) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - moduleInputChannel.subscribe(handler); - moduleOutputChannel.send(message); - - QueueChannel channel = (QueueChannel) handler.getOutputChannel(); - - Message reply = (Message) channel.receive(5000); - - assertThat(reply).isNotNull(); - assertThat(reply.getPayload() instanceof Station).isTrue(); - producerBinding.unbind(); - consumerBinding.unbind(); - } - - @SuppressWarnings("rawtypes") - @Test - public void testSendJsonReceiveJsonWithStreamListener(TestInfo testInfo) throws Exception { - StreamListenerMessageHandler handler = this.buildStreamListener( - AbstractBinderTests.class, "echoStationString", String.class); - Binder binder = getBinder(); - - BindingProperties producerBindingProperties = createProducerBindingProperties( - createProducerProperties(testInfo)); - - DirectChannel moduleOutputChannel = createBindableChannel("output", - producerBindingProperties); - - BindingProperties consumerBindingProperties = createConsumerBindingProperties( - createConsumerProperties()); - - DirectChannel moduleInputChannel = createBindableChannel("input", - consumerBindingProperties); - - Binding producerBinding = binder.bindProducer( - String.format("bad%s0e", getDestinationNameDelimiter()), - moduleOutputChannel, producerBindingProperties.getProducer()); - - Binding consumerBinding = binder.bindConsumer( - String.format("bad%s0e", getDestinationNameDelimiter()), "test-5", - moduleInputChannel, consumerBindingProperties.getConsumer()); - - String value = "{\"readings\":[{\"stationid\":\"fgh\"," - + "\"customerid\":\"12345\",\"timestamp\":null}," - + "{\"stationid\":\"hjk\",\"customerid\":\"222\",\"timestamp\":null}]}"; - - Message message = MessageBuilder.withPayload(value) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - moduleInputChannel.subscribe(handler); - moduleOutputChannel.send(message); - - QueueChannel channel = (QueueChannel) handler.getOutputChannel(); - - Message reply = (Message) channel.receive(5000); - - assertThat(reply).isNotNull(); - assertThat(reply.getPayload() instanceof String).isTrue(); - producerBinding.unbind(); - consumerBinding.unbind(); - } - - @SuppressWarnings("rawtypes") - @Test - public void testSendPojoReceivePojoWithStreamListener(TestInfo testInfo) throws Exception { - StreamListenerMessageHandler handler = this.buildStreamListener( - AbstractBinderTests.class, "echoStation", Station.class); - Binder binder = getBinder(); - - BindingProperties producerBindingProperties = createProducerBindingProperties( - createProducerProperties(testInfo)); - - DirectChannel moduleOutputChannel = createBindableChannel("output", - producerBindingProperties); - - BindingProperties consumerBindingProperties = createConsumerBindingProperties( - createConsumerProperties()); - - DirectChannel moduleInputChannel = createBindableChannel("input", - consumerBindingProperties); - - Binding producerBinding = binder.bindProducer( - String.format("bad%s0f", getDestinationNameDelimiter()), - moduleOutputChannel, producerBindingProperties.getProducer()); - - Binding consumerBinding = binder.bindConsumer( - String.format("bad%s0f", getDestinationNameDelimiter()), "test-6", - moduleInputChannel, consumerBindingProperties.getConsumer()); - - Readings r1 = new Readings(); - r1.setCustomerid("123"); - r1.setStationid("XYZ"); - Readings r2 = new Readings(); - r2.setCustomerid("546"); - r2.setStationid("ABC"); - Station station = new Station(); - station.setReadings(Arrays.asList(r1, r2)); - Message message = MessageBuilder.withPayload(station) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON) - .build(); - moduleInputChannel.subscribe(handler); - moduleOutputChannel.send(message); - - QueueChannel channel = (QueueChannel) handler.getOutputChannel(); - - Message reply = (Message) channel.receive(5000); - - assertThat(reply).isNotNull(); - assertThat(reply.getPayload() instanceof Station).isTrue(); - producerBinding.unbind(); - consumerBinding.unbind(); - } - @SuppressWarnings("unused") // it is used via reflection private Station echoStation(Station station) { return station; @@ -621,32 +425,6 @@ public abstract class AbstractBinderTests handlerClass, - String handlerMethodName, Class... parameters) throws Exception { - String channelName = "reply_" + System.nanoTime(); - - this.applicationContext.getBeanFactory().registerSingleton(channelName, new QueueChannel()); - - Method m = ReflectionUtils.findMethod(handlerClass, handlerMethodName, - parameters); - InvocableHandlerMethod method = new InvocableHandlerMethod(this, m); - HandlerMethodArgumentResolverComposite resolver = new HandlerMethodArgumentResolverComposite(); - CompositeMessageConverterFactory factory = new CompositeMessageConverterFactory(); - resolver.addResolver(new PayloadMethodArgumentResolver( - factory.getMessageConverterForAllRegistered())); - method.setMessageMethodArgumentResolvers(resolver); - Constructor c = ReflectionUtils.accessibleConstructor( - StreamListenerMessageHandler.class, InvocableHandlerMethod.class, - boolean.class, String[].class); - StreamListenerMessageHandler handler = (StreamListenerMessageHandler) c - .newInstance(method, false, new String[] {}); - handler.setOutputChannelName(channelName); - handler.setBeanFactory(this.applicationContext); - handler.afterPropertiesSet(); -// context.refresh(); - return handler; - } - public static class Station { List readings = new ArrayList<>(); diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotatedMethodArgumentsTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotatedMethodArgumentsTests.java deleted file mode 100644 index ad3ed5df4..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotatedMethodArgumentsTests.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2016-2019 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 - * - * https://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.ArrayList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.UUID; - -import jakarta.validation.Valid; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.handler.annotation.Header; -import org.springframework.messaging.handler.annotation.Headers; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException; -import org.springframework.util.MimeType; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Oleg Zhurakousky - * @author Artem Bilan - */ -public class StreamListenerAnnotatedMethodArgumentsTests { - - @BeforeClass - public static void init() { - Locale.setDefault(Locale.US); - } - - @Test - @SuppressWarnings("unchecked") - public void testAnnotatedArguments() { - ConfigurableApplicationContext context = SpringApplication - .run(TestPojoWithAnnotatedArguments.class, "--server.port=0"); - - TestPojoWithAnnotatedArguments testPojoWithAnnotatedArguments = context - .getBean(TestPojoWithAnnotatedArguments.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input() - .send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", MimeType.valueOf("application/json")) - .setHeader("testHeader", "testValue").build()); - assertThat(testPojoWithAnnotatedArguments.receivedArguments).hasSize(3); - assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0)) - .isInstanceOf(StreamListenerTestUtils.FooPojo.class); - assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(1)) - .isInstanceOf(Map.class); - assertThat((Map) testPojoWithAnnotatedArguments.receivedArguments - .get(1)).containsEntry(MessageHeaders.CONTENT_TYPE, - MimeType.valueOf("application/json")); - assertThat((Map) testPojoWithAnnotatedArguments.receivedArguments - .get(1)).containsEntry("testHeader", "testValue"); - assertThat(testPojoWithAnnotatedArguments.receivedArguments.get(2)) - .isEqualTo("application/json"); - context.close(); - } - - @Test - public void testInputAnnotationAtMethodParameter() { - try { - SpringApplication.run(TestPojoWithInvalidInputAnnotatedArgument.class, - "--server.port=0"); - fail("Exception expected: " + INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - - @Test - public void testValidAnnotationAtMethodParameterWithPojoThatPassesValidation() { - ConfigurableApplicationContext context = SpringApplication.run( - TestPojoWithValidAnnotationThatPassesValidation.class, "--server.port=0"); - - TestPojoWithValidAnnotationThatPassesValidation testPojoWithValidAnnotationThatPassesValidation = context - .getBean(TestPojoWithValidAnnotationThatPassesValidation.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"" + id + "\"}") - .setHeader("contentType", MimeType.valueOf("application/json")).build()); - assertThat( - testPojoWithValidAnnotationThatPassesValidation.receivedArguments.get(0)) - .hasFieldOrPropertyWithValue("foo", id); - context.close(); - } - - @Test - @Ignore - public void testValidAnnotationAtMethodParameterWithPojoThatFailsValidation() { - ConfigurableApplicationContext context = SpringApplication.run( - TestPojoWithValidAnnotationThatPassesValidation.class, "--server.port=0"); - - Sink sink = context.getBean(Sink.class); - try { - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"\"}") - .setHeader("contentType", MimeType.valueOf("application/json")) - .build()); - fail("Exception expected: MethodArgumentNotValidException!"); - } - catch (MethodArgumentNotValidException e) { - assertThat(e.getMessage()).contains( - "default message [foo]]; default message [must not be blank]]"); - } - context.close(); - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestPojoWithAnnotatedArguments { - - List receivedArguments = new ArrayList<>(); - - @StreamListener(Processor.INPUT) - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo, - @Headers Map headers, - @Header(MessageHeaders.CONTENT_TYPE) String contentType) { - this.receivedArguments.add(fooPojo); - this.receivedArguments.add(headers); - this.receivedArguments.add(contentType); - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestPojoWithInvalidInputAnnotatedArgument { - - List receivedArguments = new ArrayList<>(); - - @StreamListener - public void receive( - @Input(Processor.INPUT) @Payload StreamListenerTestUtils.FooPojo fooPojo, - @Headers Map headers, - @Header(MessageHeaders.CONTENT_TYPE) String contentType) { - this.receivedArguments.add(fooPojo); - this.receivedArguments.add(headers); - this.receivedArguments.add(contentType); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithValidAnnotationThatPassesValidation { - - List receivedArguments = new ArrayList<>(); - - @StreamListener(Processor.INPUT) - public void receive( - @Valid StreamListenerTestUtils.PojoWithValidation pojoWithValidation) { - this.receivedArguments.add(pojoWithValidation); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotationBeanPostProcessorOverrideTest.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotationBeanPostProcessorOverrideTest.java deleted file mode 100644 index ba0e89ac5..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAnnotationBeanPostProcessorOverrideTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.junit.Ignore; -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binding.StreamListenerAnnotationBeanPostProcessor; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.handler.annotation.Payload; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.cloud.stream.config.BindingServiceConfiguration.STREAM_LISTENER_ANNOTATION_BEAN_POST_PROCESSOR_NAME; - -/** - * @author Marius Bogoevici - */ -public class StreamListenerAnnotationBeanPostProcessorOverrideTest { - - @Test - @SuppressWarnings("unchecked") - @Ignore - public void testOverrideStreamListenerAnnotationBeanPostProcessor() throws Exception { - ConfigurableApplicationContext context = SpringApplication - .run(TestPojoWithAnnotatedArguments.class, "--server.port=0"); - - TestPojoWithAnnotatedArguments testPojoWithAnnotatedArguments = context - .getBean(TestPojoWithAnnotatedArguments.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "foo").build()); - sink.input().send(MessageBuilder.withPayload("{\"bar\":\"foofoo" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "bar").build()); - assertThat(testPojoWithAnnotatedArguments.receivedFoo).hasSize(1); - assertThat(testPojoWithAnnotatedArguments.receivedFoo.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - context.close(); - } - - @Configuration - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestPojoWithAnnotatedArguments { - - List receivedFoo = new ArrayList<>(); - - /** - * Overrides the default {@link StreamListenerAnnotationBeanPostProcessor}. - */ - @Bean(name = STREAM_LISTENER_ANNOTATION_BEAN_POST_PROCESSOR_NAME) - public static StreamListenerAnnotationBeanPostProcessor streamListenerAnnotationBeanPostProcessor() { - return new StreamListenerAnnotationBeanPostProcessor() { - @Override - protected StreamListener postProcessAnnotation( - StreamListener originalAnnotation, Method annotatedMethod) { - Map attributes = new HashMap<>( - AnnotationUtils.getAnnotationAttributes(originalAnnotation)); - attributes.put("condition", - "headers['type']=='" + originalAnnotation.condition() + "'"); - return AnnotationUtils.synthesizeAnnotation(attributes, - StreamListener.class, annotatedMethod); - } - }; - } - - @StreamListener(value = Sink.INPUT, condition = "foo") - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedFoo.add(fooPojo); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAsMetaAnnotationTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAsMetaAnnotationTests.java deleted file mode 100644 index a1edb0922..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerAsMetaAnnotationTests.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2017-2019 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 - * - * https://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.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.junit.Ignore; -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.annotation.AliasFor; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.Payload; - -import static org.assertj.core.api.Assertions.assertThat; - -@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@MessageMapping -@Documented -@StreamListener -@interface EventHandler { - - /** - * The name of the binding target (e.g. channel) that the method subscribes to. - * @return the name of the binding target. - */ - @AliasFor(annotation = StreamListener.class, attribute = "target") - String value() default ""; - - /** - * The name of the binding target (e.g. channel) that the method subscribes to. - * @return the name of the binding target. - */ - @AliasFor(annotation = StreamListener.class, attribute = "target") - String target() default ""; - - /** - * A condition that must be met by all items that are dispatched to this method. - * @return a SpEL expression that must evaluate to a {@code boolean} value. - */ - @AliasFor(annotation = StreamListener.class, attribute = "condition") - String condition() default ""; - -} - -/** - * @author David Turanski - */ -public class StreamListenerAsMetaAnnotationTests { - - @Test - @Ignore - public void testCustomAnnotation() { - ConfigurableApplicationContext context = SpringApplication - .run(TestPojoWithCustomAnnotatedArguments.class, "--server.port=0"); - - TestPojoWithCustomAnnotatedArguments testPojoWithAnnotatedArguments = context - .getBean(TestPojoWithCustomAnnotatedArguments.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "foo").build()); - assertThat(testPojoWithAnnotatedArguments.receivedFoo).hasSize(1); - assertThat(testPojoWithAnnotatedArguments.receivedFoo.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - context.close(); - } - - @Test - @Ignore - public void testAnnotation() { - ConfigurableApplicationContext context = SpringApplication - .run(TestPojoWithAnnotatedArguments.class, "--server.port=0"); - - TestPojoWithAnnotatedArguments testPojoWithAnnotatedArguments = context - .getBean(TestPojoWithAnnotatedArguments.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "foo").build()); - assertThat(testPojoWithAnnotatedArguments.receivedFoo).hasSize(1); - assertThat(testPojoWithAnnotatedArguments.receivedFoo.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - context.close(); - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestPojoWithCustomAnnotatedArguments { - - List receivedFoo = new ArrayList<>(); - - List receivedBar = new ArrayList<>(); - - @EventHandler(value = Sink.INPUT, condition = "headers['type']=='foo'") - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedFoo.add(fooPojo); - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestPojoWithAnnotatedArguments { - - List receivedFoo = new ArrayList<>(); - - List receivedBar = new ArrayList<>(); - - @StreamListener(value = Sink.INPUT, condition = "headers['type']=='foo'") - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedFoo.add(fooPojo); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerContentTypeConversionTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerContentTypeConversionTests.java deleted file mode 100644 index a827552c3..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerContentTypeConversionTests.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2016-2019 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 - * - * https://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.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - */ -public class StreamListenerContentTypeConversionTests { - - @Test - public void testContentTypeConversion() throws Exception { - ConfigurableApplicationContext context = SpringApplication - .run(TestSinkWithContentTypeConversion.class, "--server.port=0"); - @SuppressWarnings("unchecked") - TestSinkWithContentTypeConversion testSink = context - .getBean(TestSinkWithContentTypeConversion.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json").build()); - assertThat(testSink.latch.await(10, TimeUnit.SECONDS)); - assertThat(testSink.receivedArguments).hasSize(1); - assertThat(testSink.receivedArguments.get(0)).hasFieldOrPropertyWithValue("foo", - "barbar" + id); - context.close(); - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestSinkWithContentTypeConversion { - - List receivedArguments = new ArrayList<>(); - - CountDownLatch latch = new CountDownLatch(1); - - @StreamListener(Sink.INPUT) - public void receive(StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedArguments.add(fooPojo); - this.latch.countDown(); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerDuplicateMappingTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerDuplicateMappingTests.java deleted file mode 100644 index c5cb84694..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerDuplicateMappingTests.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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 org.junit.Test; - -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binding.StreamListenerErrorMessages; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.SendTo; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - */ -public class StreamListenerDuplicateMappingTests { - - @Test - @SuppressWarnings("unchecked") - public void testMultipleMappingsWithReturnValue() { - ConfigurableApplicationContext context = null; - try { - context = SpringApplication.run(TestMultipleMappingsWithReturnValue.class, - "--server.port=0"); - fail("Exception expected on duplicate mapping"); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).startsWith( - StreamListenerErrorMessages.MULTIPLE_VALUE_RETURNING_METHODS); - } - finally { - if (context != null) { - context.close(); - } - } - } - - @Test - public void testDuplicateMappingFromAbstractMethod() { - ConfigurableApplicationContext context = null; - try { - context = SpringApplication.run(TestDuplicateMappingFromAbstractMethod.class, - "--server.port=0"); - } - catch (BeanCreationException e) { - String errorMessage = e.getCause().getMessage() - .startsWith("Duplicate @StreamListener mapping") - ? "Duplicate mapping exception is not expected" - : "Test failed with exception"; - fail(errorMessage + ": " + e.getMessage()); - } - finally { - if (context != null) { - context.close(); - } - } - } - - public interface GenericSink { - - void testMethod(T msg); - - } - - public interface Base { - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestMultipleMappingsWithReturnValue { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String receive(Message fooMessage) { - return null; - } - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String receiveDuplicateMapping(Message fooMessage) { - return null; - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestDuplicateMappingFromAbstractMethod - implements GenericSink { - - @Override - @StreamListener(Sink.INPUT) - public void testMethod(TestBase msg) { - } - - } - - public class TestBase implements Base { - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerBeanTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerBeanTests.java deleted file mode 100644 index 160c9aefd..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerBeanTests.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - */ -@RunWith(Parameterized.class) -public class StreamListenerHandlerBeanTests { - - private Class configClass; - - public StreamListenerHandlerBeanTests(Class configClass) { - this.configClass = configClass; - } - - @Parameterized.Parameters - public static Collection InputConfigs() { - return Arrays.asList(TestHandlerBeanWithSendTo.class, TestHandlerBean2.class); - } - - @Test - @SuppressWarnings("unchecked") - public void testHandlerBean() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(this.configClass, - "--spring.cloud.stream.bindings.output.contentType=application/json", - "--server.port=0"); - MessageCollector collector = context.getBean(MessageCollector.class); - Processor processor = context.getBean(Processor.class); - String id = UUID.randomUUID().toString(); - processor.input() - .send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json").build()); - HandlerBean handlerBean = context.getBean(HandlerBean.class); - Assertions.assertThat(handlerBean.receivedPojos).hasSize(1); - Assertions.assertThat(handlerBean.receivedPojos.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - Message message = (Message) collector - .forChannel(processor.output()).poll(1, TimeUnit.SECONDS); - assertThat(message).isNotNull(); - assertThat(message.getPayload()).isEqualTo("{\"bar\":\"barbar" + id + "\"}"); - assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.APPLICATION_JSON)); - context.close(); - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestHandlerBeanWithSendTo { - - @Bean - public HandlerBeanWithSendTo handlerBean() { - return new HandlerBeanWithSendTo(); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestHandlerBean2 { - - @Bean - public HandlerBeanWithOutput handlerBean() { - return new HandlerBeanWithOutput(); - } - - } - - public static class HandlerBeanWithSendTo extends HandlerBean { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public StreamListenerTestUtils.BarPojo receive( - StreamListenerTestUtils.FooPojo fooMessage) { - this.receivedPojos.add(fooMessage); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooMessage.getFoo()); - return barPojo; - } - - } - - public static class HandlerBeanWithOutput extends HandlerBean { - - @StreamListener(Processor.INPUT) - @Output(Processor.OUTPUT) - public StreamListenerTestUtils.BarPojo receive( - StreamListenerTestUtils.FooPojo fooMessage) { - this.receivedPojos.add(fooMessage); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooMessage.getFoo()); - return barPojo; - } - - } - - public static class HandlerBean { - - List receivedPojos = new ArrayList<>(); - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerMethodTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerMethodTests.java deleted file mode 100644 index 0be6c2147..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerHandlerMethodTests.java +++ /dev/null @@ -1,623 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binding.StreamListenerErrorMessages; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.annotation.Router; -import org.springframework.integration.channel.DirectChannel; -import org.springframework.integration.support.DefaultMessageBuilderFactory; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageHandler; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.util.Assert; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INPUT_AT_STREAM_LISTENER; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INVALID_INBOUND_NAME; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INVALID_OUTBOUND_NAME; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INVALID_OUTPUT_VALUES; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.NO_INPUT_DESTINATION; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.RETURN_TYPE_MULTIPLE_OUTBOUND_SPECIFIED; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.RETURN_TYPE_NO_OUTBOUND_SPECIFIED; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Gary Russell - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - */ -public class StreamListenerHandlerMethodTests { - - @Test - public void testInvalidInputOnMethod() throws Exception { - try { - SpringApplication.run(TestInvalidInputOnMethod.class, "--server.port=0", - "--spring.jmx.enabled=false"); - fail("Exception expected: " + INPUT_AT_STREAM_LISTENER); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(INPUT_AT_STREAM_LISTENER); - } - } - - @SuppressWarnings("unchecked") - @Test - public void testMethodWithObjectAsMethodArgument() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestMethodWithObjectAsMethodArgument.class, "--server.port=0", - "--spring.jmx.enabled=false", - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.cloud.stream.bindings.output.contentType=text/plain"); - Processor processor = context.getBean(Processor.class); - final String testMessage = "testing"; - processor.input().send(MessageBuilder.withPayload(testMessage).build()); - MessageCollector messageCollector = context.getBean(MessageCollector.class); - Message result = (Message) messageCollector - .forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS); - assertThat(result).isNotNull(); - assertThat(result.getPayload()).isEqualTo(testMessage.toUpperCase()); - context.close(); - } - - @SuppressWarnings("unchecked") - @Test - /** - * @since 2.0 : This test is an example of the new behavior of 2.0 when it comes to - * contentType handling. The default contentType being JSON in order to be able to - * check a message without quotes the user needs to set the input/output contentType - * accordingly Also, received messages are always of Message now. - */ - public void testMethodHeadersPropagatged() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestMethodHeadersPropagated.class, "--server.port=0", - "--spring.jmx.enabled=false", - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.cloud.stream.bindings.output.contentType=text/plain"); - Processor processor = context.getBean(Processor.class); - final String testMessage = "testing"; - processor.input().send( - MessageBuilder.withPayload(testMessage).setHeader("foo", "bar").build()); - MessageCollector messageCollector = context.getBean(MessageCollector.class); - Message result = (Message) messageCollector - .forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS); - assertThat(result).isNotNull(); - assertThat(result.getPayload()).isEqualTo(testMessage.toUpperCase()); - assertThat(result.getHeaders().get("foo")).isEqualTo("bar"); - context.close(); - } - - @SuppressWarnings("unchecked") - @Test - @Disabled - public void testMethodHeadersNotPropagatged() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestMethodHeadersNotPropagated.class, "--server.port=0", - "--spring.jmx.enabled=false", - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.cloud.stream.bindings.output.contentType=text/plain"); - Processor processor = context.getBean(Processor.class); - final String testMessage = "testing"; - processor.input().send( - MessageBuilder.withPayload(testMessage).setHeader("foo", "bar").build()); - MessageCollector messageCollector = context.getBean(MessageCollector.class); - Message result = (Message) messageCollector - .forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS); - assertThat(result).isNotNull(); - assertThat(result.getPayload()).isEqualTo(testMessage.toUpperCase()); - assertThat(result.getHeaders().get("foo")).isNull(); - context.close(); - } - - // TODO: Handle dynamic destinations and contentType - @SuppressWarnings("unchecked") - public void testStreamListenerMethodWithTargetBeanFromOutside() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestStreamListenerMethodWithTargetBeanFromOutside.class, - "--server.port=0", "--spring.jmx.enabled=false", - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.cloud.stream.bindings.output.contentType=text/plain"); - Sink sink = context.getBean(Sink.class); - final String testMessageToSend = "testing"; - sink.input().send(MessageBuilder.withPayload(testMessageToSend).build()); - DirectChannel directChannel = (DirectChannel) context - .getBean(testMessageToSend.toUpperCase(), MessageChannel.class); - MessageCollector messageCollector = context.getBean(MessageCollector.class); - Message result = (Message) messageCollector - .forChannel(directChannel).poll(1000, TimeUnit.MILLISECONDS); - sink.input().send(MessageBuilder.withPayload(testMessageToSend).build()); - assertThat(result).isNotNull(); - assertThat(result.getPayload()).isEqualTo(testMessageToSend.toUpperCase()); - context.close(); - } - - @Test - public void testInvalidReturnTypeWithSendToAndOutput() throws Exception { - try { - SpringApplication.run(TestReturnTypeWithMultipleOutput.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected: " + RETURN_TYPE_MULTIPLE_OUTBOUND_SPECIFIED); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(RETURN_TYPE_MULTIPLE_OUTBOUND_SPECIFIED); - } - } - - @Test - public void testInvalidReturnTypeWithNoOutput() throws Exception { - try { - SpringApplication.run(TestInvalidReturnTypeWithNoOutput.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected: " + RETURN_TYPE_NO_OUTBOUND_SPECIFIED); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(RETURN_TYPE_NO_OUTBOUND_SPECIFIED); - } - } - - @Test - public void testInvalidInputAnnotationWithNoValue() throws Exception { - try { - SpringApplication.run(TestInvalidInputAnnotationWithNoValue.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected: " + INVALID_INBOUND_NAME); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(INVALID_INBOUND_NAME); - } - } - - @Test - public void testInvalidOutputAnnotationWithNoValue() throws Exception { - try { - SpringApplication.run(TestInvalidOutputAnnotationWithNoValue.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected: " + INVALID_OUTBOUND_NAME); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(INVALID_OUTBOUND_NAME); - } - } - - @Test - public void testMethodInvalidInboundName() throws Exception { - try { - SpringApplication.run(TestMethodInvalidInboundName.class, "--server.port=0", - "--spring.jmx.enabled=false"); - fail("Exception expected on using invalid inbound name"); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains( - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - - @Test - public void testMethodInvalidOutboundName() throws Exception { - try { - SpringApplication.run(TestMethodInvalidOutboundName.class, "--server.port=0", - "--spring.jmx.enabled=false"); - fail("Exception expected on using invalid outbound name"); - } - catch (NoSuchBeanDefinitionException e) { - assertThat(e.getMessage()).contains("invalid"); - } - } - - @Test - public void testAmbiguousMethodArguments1() throws Exception { - try { - SpringApplication.run(TestAmbiguousMethodArguments1.class, "--server.port=0", - "--spring.jmx.enabled=false"); - fail("Exception expected: " + AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()) - .contains(AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS); - } - } - - @Test - public void testAmbiguousMethodArguments2() throws Exception { - try { - SpringApplication.run(TestAmbiguousMethodArguments2.class, "--server.port=0", - "--spring.jmx.enabled=false"); - fail("Exception expected:" + AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()) - .contains(AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS); - } - } - - @Test - public void testMethodWithInputAsMethodAndParameter() throws Exception { - try { - SpringApplication.run(TestMethodWithInputAsMethodAndParameter.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected: " + INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - - @Test - public void testMethodWithOutputAsMethodAndParameter() throws Exception { - try { - SpringApplication.run(TestMethodWithOutputAsMethodAndParameter.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected:" + INVALID_OUTPUT_VALUES); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).startsWith(INVALID_OUTPUT_VALUES); - } - } - - @Test - public void testMethodWithoutInput() throws Exception { - try { - SpringApplication.run(TestMethodWithoutInput.class, "--server.port=0", - "--spring.jmx.enabled=false"); - fail("Exception expected when inbound target is not set"); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(NO_INPUT_DESTINATION); - } - } - - @Test - public void testMethodWithMultipleInputParameters() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestMethodWithMultipleInputParameters.class, "--server.port=0", - "--spring.jmx.enabled=false"); - Processor processor = context.getBean(Processor.class); - StreamListenerTestUtils.FooInboundChannel1 inboundChannel2 = context - .getBean(StreamListenerTestUtils.FooInboundChannel1.class); - final CountDownLatch latch = new CountDownLatch(2); - ((SubscribableChannel) processor.output()).subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - Assert.isTrue( - message.getPayload().equals("footesting") - || message.getPayload().equals("BARTESTING"), - "Assert failed"); - latch.countDown(); - } - }); - processor.input().send(MessageBuilder.withPayload("{\"foo\":\"fooTESTing\"}") - .setHeader("contentType", "application/json").build()); - inboundChannel2.input() - .send(MessageBuilder.withPayload("{\"bar\":\"bartestING\"}") - .setHeader("contentType", "application/json").build()); - assertThat(latch.await(1, TimeUnit.SECONDS)); - context.close(); - } - - @Test - public void testMethodWithMultipleOutputParameters() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestMethodWithMultipleOutputParameters.class, "--server.port=0", - "--spring.jmx.enabled=false"); - Processor processor = context.getBean(Processor.class); - StreamListenerTestUtils.FooOutboundChannel1 source2 = context - .getBean(StreamListenerTestUtils.FooOutboundChannel1.class); - final CountDownLatch latch = new CountDownLatch(2); - ((SubscribableChannel) processor.output()).subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - Assert.isTrue(message.getPayload().equals("testing"), "Assert failed"); - Assert.isTrue(message.getHeaders().get("output").equals("output2"), - "Assert failed"); - latch.countDown(); - } - }); - ((SubscribableChannel) source2.output()).subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - Assert.isTrue(message.getPayload().equals("TESTING"), "Assert failed"); - Assert.isTrue(message.getHeaders().get("output").equals("output1"), - "Assert failed"); - latch.countDown(); - } - }); - processor.input().send(MessageBuilder.withPayload("testING") - .setHeader("output", "output1").build()); - processor.input().send(MessageBuilder.withPayload("TESTing") - .setHeader("output", "output2").build()); - assertThat(latch.await(1, TimeUnit.SECONDS)); - context.close(); - } - - @EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class }) - @EnableAutoConfiguration - public static class TestMethodWithMultipleOutputParameters { - - @StreamListener - public void receive(@Input(Processor.INPUT) SubscribableChannel input, - @Output(Processor.OUTPUT) final MessageChannel output1, - @Output(StreamListenerTestUtils.FooOutboundChannel1.OUTPUT) final MessageChannel output2) { - input.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - if (message.getHeaders().get("output").equals("output1")) { - output1.send(org.springframework.messaging.support.MessageBuilder - .withPayload( - message.getPayload().toString().toUpperCase()) - .build()); - } - else if (message.getHeaders().get("output").equals("output2")) { - output2.send(org.springframework.messaging.support.MessageBuilder - .withPayload( - message.getPayload().toString().toLowerCase()) - .build()); - } - } - }); - } - - } - - @EnableBinding({ Sink.class }) - @EnableAutoConfiguration - public static class TestMethodWithoutInput { - - @StreamListener - public void receive(StreamListenerTestUtils.FooPojo fooPojo) { - } - - } - - @EnableBinding({ Processor.class }) - @EnableAutoConfiguration - public static class TestMethodWithObjectAsMethodArgument { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String receive(Object received) { - return received.toString().toUpperCase(); - } - - } - - @EnableBinding({ Processor.class }) - @EnableAutoConfiguration - public static class TestMethodHeadersPropagated { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String receive(String received) { - return received.toUpperCase(); - } - - } - - @EnableBinding({ Processor.class }) - @EnableAutoConfiguration - public static class TestMethodHeadersNotPropagated { - - @StreamListener(value = Processor.INPUT, copyHeaders = "${foo.bar:false}") - @SendTo(Processor.OUTPUT) - public String receive(String received) { - return received.toUpperCase(); - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestStreamListenerMethodWithTargetBeanFromOutside { - - private static final String ROUTER_QUEUE = "routeInstruction"; - - @StreamListener(Sink.INPUT) - @SendTo(ROUTER_QUEUE) - public Message convertMessageBody(Message message) { - return new DefaultMessageBuilderFactory() - .withPayload(message.getPayload().toUpperCase()).build(); - } - - @Router(inputChannel = ROUTER_QUEUE) - public String route(String message) { - return message.toUpperCase(); - } - - } - - @EnableBinding({ Sink.class }) - @EnableAutoConfiguration - public static class TestInvalidInputOnMethod { - - @StreamListener - @Input(Sink.INPUT) - public void receive(StreamListenerTestUtils.FooPojo fooPojo) { - } - - } - - @EnableBinding({ Sink.class }) - @EnableAutoConfiguration - public static class TestAmbiguousMethodArguments1 { - - @StreamListener(Processor.INPUT) - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo, - String value) { - } - - } - - @EnableBinding({ Sink.class }) - @EnableAutoConfiguration - public static class TestAmbiguousMethodArguments2 { - - @StreamListener(Processor.INPUT) - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo, - @Payload StreamListenerTestUtils.BarPojo barPojo) { - } - - } - - @EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class }) - @EnableAutoConfiguration - public static class TestReturnTypeWithMultipleOutput { - - @StreamListener - public String receive(@Input(Processor.INPUT) SubscribableChannel input1, - @Output(Processor.OUTPUT) MessageChannel output1, - @Output(StreamListenerTestUtils.FooOutboundChannel1.OUTPUT) MessageChannel output2) { - return "foo"; - } - - } - - @EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class }) - @EnableAutoConfiguration - public static class TestInvalidReturnTypeWithNoOutput { - - @StreamListener - public String receive(@Input(Processor.INPUT) SubscribableChannel input1) { - return "foo"; - } - - } - - @EnableBinding({ Processor.class }) - @EnableAutoConfiguration - public static class TestInvalidInputAnnotationWithNoValue { - - @StreamListener - public void receive(@Input SubscribableChannel input) { - } - - } - - @EnableBinding({ Processor.class }) - @EnableAutoConfiguration - public static class TestInvalidOutputAnnotationWithNoValue { - - @StreamListener - public void receive(@Input(Processor.OUTPUT) SubscribableChannel input, - @Output MessageChannel output) { - } - - } - - @EnableBinding({ Sink.class }) - @EnableAutoConfiguration - public static class TestMethodInvalidInboundName { - - @StreamListener - public void receive(@Input("invalid") SubscribableChannel input) { - } - - } - - @EnableBinding({ Processor.class }) - @EnableAutoConfiguration - public static class TestMethodInvalidOutboundName { - - @StreamListener - public void receive(@Input(Processor.INPUT) SubscribableChannel input, - @Output("invalid") MessageChannel output) { - } - - } - - @EnableBinding({ Sink.class }) - @EnableAutoConfiguration - public static class TestMethodWithInputAsMethodAndParameter { - - @StreamListener - public void receive(@Input(Sink.INPUT) StreamListenerTestUtils.FooPojo fooPojo) { - } - - } - - @EnableBinding({ Processor.class, StreamListenerTestUtils.FooOutboundChannel1.class }) - @EnableAutoConfiguration - public static class TestMethodWithOutputAsMethodAndParameter { - - @StreamListener - @Output(StreamListenerTestUtils.FooOutboundChannel1.OUTPUT) - public void receive(@Input(Processor.INPUT) SubscribableChannel input, - @Output(Processor.OUTPUT) final MessageChannel output1) { - input.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output1.send(org.springframework.messaging.support.MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - } - - } - - @EnableBinding({ Processor.class, StreamListenerTestUtils.FooInboundChannel1.class }) - @EnableAutoConfiguration - public static class TestMethodWithMultipleInputParameters { - - @StreamListener - public void receive(@Input(Processor.INPUT) SubscribableChannel input1, - @Input(StreamListenerTestUtils.FooInboundChannel1.INPUT) SubscribableChannel input2, - final @Output(Processor.OUTPUT) MessageChannel output) { - input1.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output.send(org.springframework.messaging.support.MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - input2.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output.send(org.springframework.messaging.support.MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMessageArgumentTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMessageArgumentTests.java deleted file mode 100644 index 028e2222e..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMessageArgumentTests.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.SendTo; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - */ -@RunWith(Parameterized.class) -public class StreamListenerMessageArgumentTests { - - private Class configClass; - - public StreamListenerMessageArgumentTests(Class configClass) { - this.configClass = configClass; - } - - @Parameterized.Parameters - public static Collection InputConfigs() { - return Arrays.asList(new Class[] { TestPojoWithMessageArgument1.class, - TestPojoWithMessageArgument2.class }); - } - - @Test - @SuppressWarnings("unchecked") - public void testMessageArgument() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(this.configClass, - "--server.port=0", - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - MessageCollector collector = context.getBean(MessageCollector.class); - Processor processor = context.getBean(Processor.class); - String id = UUID.randomUUID().toString(); - processor.input().send(MessageBuilder.withPayload("barbar" + id) - .setHeader("contentType", "text/plain").build()); - TestPojoWithMessageArgument testPojoWithMessageArgument = context - .getBean(TestPojoWithMessageArgument.class); - assertThat(testPojoWithMessageArgument.receivedMessages).hasSize(1); - assertThat(testPojoWithMessageArgument.receivedMessages.get(0).getPayload()) - .isEqualTo("barbar" + id); - Message message = (Message) collector - .forChannel(processor.output()).poll(1, TimeUnit.SECONDS); - assertThat(message).isNotNull(); - assertThat(message.getPayload()).contains("barbar" + id); - context.close(); - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithMessageArgument1 extends TestPojoWithMessageArgument { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public StreamListenerTestUtils.BarPojo receive(Message fooMessage) { - this.receivedMessages.add(fooMessage); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooMessage.getPayload()); - return barPojo; - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithMessageArgument2 extends TestPojoWithMessageArgument { - - @StreamListener(Processor.INPUT) - @Output(Processor.OUTPUT) - public StreamListenerTestUtils.BarPojo receive(Message fooMessage) { - this.receivedMessages.add(fooMessage); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooMessage.getPayload()); - return barPojo; - } - - } - - public static class TestPojoWithMessageArgument { - - List> receivedMessages = new ArrayList<>(); - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodRegisteredOnlyOnceTest.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodRegisteredOnlyOnceTest.java deleted file mode 100644 index 7b475d835..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodRegisteredOnlyOnceTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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 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.boot.test.mock.mockito.SpyBean; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import static org.mockito.Mockito.verify; - -/** - * See issue https://github.com/spring-cloud/spring-cloud-stream/issues/1080 - * - * StreamListener method called twice when using @SpyBean - * - * @author Soby Chacko - */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest -public class StreamListenerMethodRegisteredOnlyOnceTest { - - @Autowired - private SomeSink sink; - - @SpyBean - private SomeHandler handler; - - @Test - public void should_handleSomeMessage() { - this.sink.channel().send(new GenericMessage<>("Payload")); - verify(this.handler).handleMessage(); // should only be invoked once. - } - - public interface SomeSink { - - @Input(Sink.INPUT) - SubscribableChannel channel(); - - } - - @EnableBinding(SomeSink.class) - @EnableAutoConfiguration - public static class SomeHandler { - - @StreamListener(Sink.INPUT) - public void handleMessage() { - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodReturnWithConversionTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodReturnWithConversionTests.java deleted file mode 100644 index 5c6fe2eea..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodReturnWithConversionTests.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Suite; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.RunnerBuilder; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - * - */ -@RunWith(StreamListenerMethodReturnWithConversionTests.class) -@Suite.SuiteClasses({ - StreamListenerMethodReturnWithConversionTests.TestReturnConversion.class, - StreamListenerMethodReturnWithConversionTests.TestReturnNoConversion.class }) -public class StreamListenerMethodReturnWithConversionTests extends Suite { - - public StreamListenerMethodReturnWithConversionTests(Class klass, - RunnerBuilder builder) throws InitializationError { - super(klass, builder); - } - - @RunWith(Parameterized.class) - public static class TestReturnConversion { - - private Class configClass; - - public TestReturnConversion(Class configClass) { - this.configClass = configClass; - } - - @Parameterized.Parameters - public static Collection InputConfigs() { - return Arrays.asList(new Class[] { TestPojoWithMimeType1.class, - TestPojoWithMimeType2.class }); - } - - @Test - @SuppressWarnings("unchecked") - public void testReturnConversion() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - this.configClass, - "--spring.cloud.stream.bindings.output.contentType=application/json", - "--server.port=0", "--spring.jmx.enabled=false"); - MessageCollector collector = context.getBean(MessageCollector.class); - Processor processor = context.getBean(Processor.class); - String id = UUID.randomUUID().toString(); - processor.input() - .send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json").build()); - TestPojoWithMimeType testPojoWithMimeType = context - .getBean(TestPojoWithMimeType.class); - Assertions.assertThat(testPojoWithMimeType.receivedPojos).hasSize(1); - Assertions.assertThat(testPojoWithMimeType.receivedPojos.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - Message message = (Message) collector - .forChannel(processor.output()).poll(1, TimeUnit.SECONDS); - assertThat(message).isNotNull(); - assertThat(new String(message.getPayload())) - .isEqualTo("{\"bar\":\"barbar" + id + "\"}"); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.APPLICATION_JSON)); - context.close(); - } - - } - - @RunWith(Parameterized.class) - public static class TestReturnNoConversion { - - private Class configClass; - - private ObjectMapper mapper = new ObjectMapper(); - - public TestReturnNoConversion(Class configClass) { - this.configClass = configClass; - } - - @Parameterized.Parameters - public static Collection InputConfigs() { - return Arrays.asList(new Class[] { TestPojoWithMimeType1.class, - TestPojoWithMimeType2.class }); - } - - @Test - @SuppressWarnings("unchecked") - public void testReturnNoConversion() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - this.configClass, "--server.port=0", "--spring.jmx.enabled=false"); - MessageCollector collector = context.getBean(MessageCollector.class); - Processor processor = context.getBean(Processor.class); - String id = UUID.randomUUID().toString(); - processor.input() - .send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json").build()); - TestPojoWithMimeType testPojoWithMimeType = context - .getBean(TestPojoWithMimeType.class); - Assertions.assertThat(testPojoWithMimeType.receivedPojos).hasSize(1); - Assertions.assertThat(testPojoWithMimeType.receivedPojos.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - Message message = (Message) collector - .forChannel(processor.output()).poll(1, TimeUnit.SECONDS); - assertThat(message).isNotNull(); - StreamListenerTestUtils.BarPojo barPojo = this.mapper.readValue( - message.getPayload(), StreamListenerTestUtils.BarPojo.class); - assertThat(barPojo.getBar()).isEqualTo("barbar" + id); - assertThat(message.getHeaders().get(MessageHeaders.CONTENT_TYPE, - MimeType.class) != null); - context.close(); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithMimeType1 extends TestPojoWithMimeType { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public StreamListenerTestUtils.BarPojo receive( - StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedPojos.add(fooPojo); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooPojo.getFoo()); - return barPojo; - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithMimeType2 extends TestPojoWithMimeType { - - @StreamListener(Processor.INPUT) - @Output(Processor.OUTPUT) - public StreamListenerTestUtils.BarPojo receive( - StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedPojos.add(fooPojo); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooPojo.getFoo()); - return barPojo; - } - - } - - public static class TestPojoWithMimeType { - - List receivedPojos = new ArrayList<>(); - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodSetupOrchestratorTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodSetupOrchestratorTests.java deleted file mode 100644 index ba89ee697..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodSetupOrchestratorTests.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2018-2019 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 - * - * https://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.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.SpyBean; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binding.StreamListenerAnnotationBeanPostProcessor; -import org.springframework.cloud.stream.binding.StreamListenerSetupMethodOrchestrator; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.context.annotation.Bean; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.util.ReflectionUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -/** - * @author Soby Chacko - */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest -public class StreamListenerMethodSetupOrchestratorTests { - - @SpyBean - CustomOrchestrator customOrchestrator; - - @SpyBean - MultipleStreamListenerProcessor multipleStreamListenerProcessor; - - @SpyBean - StreamListenerAnnotationBeanPostProcessor streamListenerAnnotationBeanPostProcessor; - - @Test - @SuppressWarnings("unchecked") - public void testCustomStreamListenerOrchestratorAndDefaultTogetherInSameContext() - throws Exception { - - // Two StreamListener methods, so 2 invocations - verify(this.customOrchestrator, times(2)).supports(any()); - - Method method = this.multipleStreamListenerProcessor.getClass() - .getMethod("handleMessage"); - StreamListener streamListener = AnnotatedElementUtils.findMergedAnnotation(method, - StreamListener.class); - // verify that the invocation happened on the custom Orchestrator - verify(this.customOrchestrator).orchestrateStreamListenerSetupMethod( - streamListener, method, this.multipleStreamListenerProcessor); - - Method method1 = this.multipleStreamListenerProcessor.getClass() - .getMethod("produceString"); - StreamListener streamListener1 = AnnotatedElementUtils - .findMergedAnnotation(method, StreamListener.class); - - // Verify that the invocation did not happen on the custom orchestrator - verify(this.customOrchestrator, never()).orchestrateStreamListenerSetupMethod( - streamListener1, method1, this.multipleStreamListenerProcessor); - - Field field = ReflectionUtils.findField( - this.streamListenerAnnotationBeanPostProcessor.getClass(), - "streamListenerSetupMethodOrchestrators"); - ReflectionUtils.makeAccessible(field); - - Set field1; - field1 = (LinkedHashSet) ReflectionUtils - .getField(field, this.streamListenerAnnotationBeanPostProcessor); - List list = new ArrayList<>(field1); - - // Ensure that the custom orchestrator did not support this request - assertThat(list.get(0).supports(method1)).isEqualTo(false); - // Ensure that we are using the default Orchestrator in - // StreamListenerAnnoatationBeanPostProcessor - assertThat(list.get(1).supports(method1)).isEqualTo(true); - } - - public interface SomeProcessor { - - @Input(Sink.INPUT) - SubscribableChannel channel1(); - - @Input("foobar") - SubscribableChannel channel2(); - - @Output(Source.OUTPUT) - MessageChannel channel3(); - - } - - @EnableBinding(SomeProcessor.class) - @EnableAutoConfiguration - public static class MultipleStreamListenerProcessor { - - @StreamListener(Sink.INPUT) - public void handleMessage() { - } - - @StreamListener("foobar") - @SendTo("output") - public String produceString() { - return "foobar"; - } - - @Bean - public CustomOrchestrator myOrchestrator() { - return new CustomOrchestrator(); - } - - } - - static class CustomOrchestrator implements StreamListenerSetupMethodOrchestrator { - - @Override - public boolean supports(Method method) { - return method.getReturnType() != String.class; - } - - @Override - public void orchestrateStreamListenerSetupMethod(StreamListener streamListener, - Method method, Object bean) { - // stub method - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnMessageTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnMessageTests.java deleted file mode 100644 index 03fa383e9..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnMessageTests.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.SendTo; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - */ -@RunWith(Parameterized.class) -public class StreamListenerMethodWithReturnMessageTests { - - private Class configClass; - - public StreamListenerMethodWithReturnMessageTests(Class configClass) { - this.configClass = configClass; - } - - @Parameterized.Parameters - public static Collection InputConfigs() { - return Arrays.asList(new Class[] { TestPojoWithMessageReturn1.class, - TestPojoWithMessageReturn2.class }); - } - - @Test - @SuppressWarnings("unchecked") - public void testReturnMessage() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(this.configClass, - "--server.port=0", "--spring.jmx.enabled=false"); - MessageCollector collector = context.getBean(MessageCollector.class); - Processor processor = context.getBean(Processor.class); - String id = UUID.randomUUID().toString(); - processor.input() - .send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json").build()); - TestPojoWithMessageReturn testPojoWithMessageReturn = context - .getBean(TestPojoWithMessageReturn.class); - Assertions.assertThat(testPojoWithMessageReturn.receivedPojos).hasSize(1); - Assertions.assertThat(testPojoWithMessageReturn.receivedPojos.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - Message message = (Message) collector - .forChannel(processor.output()).poll(1, TimeUnit.SECONDS); - assertThat(message).isNotNull(); - assertThat(message.getPayload()).contains("barbar" + id); - context.close(); - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithMessageReturn1 extends TestPojoWithMessageReturn { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Message receive(StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedPojos.add(fooPojo); - StreamListenerTestUtils.BarPojo barPojo = new StreamListenerTestUtils.BarPojo(); - barPojo.setBar(fooPojo.getFoo()); - return MessageBuilder.withPayload(barPojo).setHeader("foo", "bar").build(); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestPojoWithMessageReturn2 extends TestPojoWithMessageReturn { - - @StreamListener(Processor.INPUT) - @Output(Processor.OUTPUT) - public Message receive(StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedPojos.add(fooPojo); - StreamListenerTestUtils.BarPojo bazPojo = new StreamListenerTestUtils.BarPojo(); - bazPojo.setBar(fooPojo.getFoo()); - return MessageBuilder.withPayload(bazPojo).setHeader("foo", "bar").build(); - } - - } - - public static class TestPojoWithMessageReturn { - - List receivedPojos = new ArrayList<>(); - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnValueTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnValueTests.java deleted file mode 100644 index 8829ff44e..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerMethodWithReturnValueTests.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -import org.assertj.core.api.Assertions; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.SendTo; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Oleg Zhurakousky - */ -@RunWith(Parameterized.class) -public class StreamListenerMethodWithReturnValueTests { - - private Class configClass; - - public StreamListenerMethodWithReturnValueTests(Class configClass) { - this.configClass = configClass; - } - - @Parameterized.Parameters - public static Collection InputConfigs() { - return Arrays.asList( - new Class[] { TestStringProcessor1.class, TestStringProcessor2.class }); - } - - @Test - @SuppressWarnings("unchecked") - public void testReturn() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run(this.configClass, - "--server.port=0", "--spring.jmx.enabled=false"); - MessageCollector collector = context.getBean(MessageCollector.class); - Processor processor = context.getBean(Processor.class); - String id = UUID.randomUUID().toString(); - processor.input() - .send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json").build()); - Message message = (Message) collector - .forChannel(processor.output()).poll(1, TimeUnit.SECONDS); - TestStringProcessor testStringProcessor = context - .getBean(TestStringProcessor.class); - Assertions.assertThat(testStringProcessor.receivedPojos).hasSize(1); - Assertions.assertThat(testStringProcessor.receivedPojos.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - assertThat(message).isNotNull(); - assertThat(message.getPayload()).contains("barbar" + id); - context.close(); - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestStringProcessor1 extends TestStringProcessor { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String receive(StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedPojos.add(fooPojo); - return fooPojo.getFoo(); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestStringProcessor2 extends TestStringProcessor { - - @StreamListener(Processor.INPUT) - @Output(Processor.OUTPUT) - public String receive(StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedPojos.add(fooPojo); - return fooPojo.getFoo(); - } - - } - - public static class TestStringProcessor { - - List receivedPojos = new ArrayList<>(); - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerTestUtils.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerTestUtils.java deleted file mode 100644 index 88dc892a6..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerTestUtils.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2016-2019 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 - * - * https://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 org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.SubscribableChannel; - -/** - * @author Ilayaperumal Gopinathan - */ -public class StreamListenerTestUtils { - - public interface FooInboundChannel1 { - - String INPUT = "foo1-input"; - - @Input(FooInboundChannel1.INPUT) - SubscribableChannel input(); - - } - - public interface FooOutboundChannel1 { - - String OUTPUT = "foo1-output"; - - @Output(FooOutboundChannel1.OUTPUT) - MessageChannel output(); - - } - - public static class FooPojo { - - private String foo; - - public String getFoo() { - return this.foo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("FooPojo{"); - sb.append("foo='").append(this.foo).append('\''); - sb.append('}'); - return sb.toString(); - } - - } - - public static class BarPojo { - - private String bar; - - public String getBar() { - return this.bar; - } - - public void setBar(String bar) { - this.bar = bar; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("BarPojo{"); - sb.append("bar='").append(this.bar).append('\''); - sb.append('}'); - return sb.toString(); - } - - } - - public static class PojoWithValidation { - - private String foo; - - public String getFoo() { - return this.foo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithAnnotatedInputOutputArgsTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithAnnotatedInputOutputArgsTests.java deleted file mode 100644 index 2e2662dc9..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithAnnotatedInputOutputArgsTests.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binding.StreamListenerErrorMessages; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageHandler; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.support.MessageBuilder; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.springframework.cloud.stream.binding.StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS; - -/** - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - */ -public class StreamListenerWithAnnotatedInputOutputArgsTests { - - @Test - public void testInputOutputArgs() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestInputOutputArgs.class, "--server.port=0", - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - sendMessageAndValidate(context); - } - - @Test - public void testInputOutputArgsWithMoreParameters() { - try { - SpringApplication.run(TestInputOutputArgsWithMoreParameters.class, - "--server.port=0"); - fail("Expected exception: " + INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains(INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - - @Test - public void testInputOutputArgsWithInvalidBindableTarget() { - try { - SpringApplication.run(TestInputOutputArgsWithInvalidBindableTarget.class, - "--server.port=0", "--spring.jmx.enabled=false"); - fail("Exception expected on using invalid bindable target as method parameter"); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains( - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - - @Test - public void testInputOutputArgsWithParameterOrderChanged() throws Exception { - ConfigurableApplicationContext context = SpringApplication.run( - TestInputOutputArgsWithParameterOrderChanged.class, "--server.port=0", - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - sendMessageAndValidate(context); - } - - @SuppressWarnings("unchecked") - private void sendMessageAndValidate(ConfigurableApplicationContext context) - throws InterruptedException { - Processor processor = context.getBean(Processor.class); - processor.input().send(MessageBuilder.withPayload("hello") - .setHeader("contentType", "text/plain").build()); - MessageCollector messageCollector = context.getBean(MessageCollector.class); - Message result = (Message) messageCollector - .forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS); - assertThat(result).isNotNull(); - assertThat(result.getPayload()).isEqualTo("HELLO"); - context.close(); - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestInputOutputArgs { - - @StreamListener - public void receive(@Input(Processor.INPUT) SubscribableChannel input, - @Output(Processor.OUTPUT) final MessageChannel output) { - input.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output.send(MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestInputOutputArgsWithMoreParameters { - - @StreamListener - public void receive(@Input(Processor.INPUT) SubscribableChannel input, - @Output(Processor.OUTPUT) final MessageChannel output, String someArg) { - input.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output.send(MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestInputOutputArgsWithInvalidBindableTarget { - - @StreamListener - public void receive(@Input("invalid") SubscribableChannel input, - @Output(Processor.OUTPUT) final MessageChannel output) { - input.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output.send(MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - } - - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class TestInputOutputArgsWithParameterOrderChanged { - - @StreamListener - public void receive(@Output(Processor.OUTPUT) final MessageChannel output, - @Input("input") SubscribableChannel input) { - input.subscribe(new MessageHandler() { - @Override - public void handleMessage(Message message) throws MessagingException { - output.send(MessageBuilder - .withPayload(message.getPayload().toString().toUpperCase()) - .build()); - } - }); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithConditionsTest.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithConditionsTest.java deleted file mode 100644 index eb3cd7f75..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/StreamListenerWithConditionsTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.ArrayList; -import java.util.List; -import java.util.UUID; - -import org.junit.Ignore; -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binding.StreamListenerErrorMessages; -import org.springframework.cloud.stream.messaging.Sink; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.handler.annotation.Payload; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; - -/** - * @author Marius Bogoevici - */ -public class StreamListenerWithConditionsTest { - - @Test - @Ignore - public void testAnnotatedArgumentsWithConditionalClass() throws Exception { - ConfigurableApplicationContext context = SpringApplication - .run(TestPojoWithAnnotatedArguments.class, "--server.port=0"); - - TestPojoWithAnnotatedArguments testPojoWithAnnotatedArguments = context - .getBean(TestPojoWithAnnotatedArguments.class); - Sink sink = context.getBean(Sink.class); - String id = UUID.randomUUID().toString(); - sink.input().send(MessageBuilder.withPayload("{\"foo\":\"barbar" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "foo").build()); - sink.input().send(MessageBuilder.withPayload("{\"bar\":\"foofoo" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "bar").build()); - sink.input().send(MessageBuilder.withPayload("{\"bar\":\"foofoo" + id + "\"}") - .setHeader("contentType", "application/json") - .setHeader("testHeader", "testValue").setHeader("type", "qux").build()); - assertThat(testPojoWithAnnotatedArguments.receivedFoo).hasSize(1); - assertThat(testPojoWithAnnotatedArguments.receivedFoo.get(0)) - .hasFieldOrPropertyWithValue("foo", "barbar" + id); - assertThat(testPojoWithAnnotatedArguments.receivedBar).hasSize(1); - assertThat(testPojoWithAnnotatedArguments.receivedBar.get(0)) - .hasFieldOrPropertyWithValue("bar", "foofoo" + id); - context.close(); - } - - @Test - public void testConditionalFailsWithReturnValue() throws Exception { - try { - ConfigurableApplicationContext context = SpringApplication.run( - TestConditionalOnMethodWithReturnValueFails.class, "--server.port=0"); - context.close(); - fail("Context creation failure expected"); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains( - StreamListenerErrorMessages.CONDITION_ON_METHOD_RETURNING_VALUE); - } - } - - @Test - public void testConditionalFailsWithDeclarativeMethod() throws Exception { - try { - ConfigurableApplicationContext context = SpringApplication.run( - TestConditionalOnDeclarativeMethodFails.class, "--server.port=0"); - context.close(); - fail("Context creation failure expected"); - } - catch (IllegalArgumentException e) { - assertThat(e.getMessage()).contains( - StreamListenerErrorMessages.CONDITION_ON_DECLARATIVE_METHOD); - } - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestPojoWithAnnotatedArguments { - - List receivedFoo = new ArrayList<>(); - - List receivedBar = new ArrayList<>(); - - @StreamListener(value = Sink.INPUT, condition = "headers['type']=='foo'") - public void receive(@Payload StreamListenerTestUtils.FooPojo fooPojo) { - this.receivedFoo.add(fooPojo); - } - - @StreamListener(target = Sink.INPUT, condition = "headers['type']=='bar'") - public void receive(@Payload StreamListenerTestUtils.BarPojo barPojo) { - this.receivedBar.add(barPojo); - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestConditionalOnDeclarativeMethodFails { - - @StreamListener(condition = "headers['type']=='foo'") - public void receive(@Input("input") MessageChannel input) { - // do nothing - } - - } - - @EnableBinding(Sink.class) - @EnableAutoConfiguration - public static class TestConditionalOnMethodWithReturnValueFails { - - @StreamListener(value = Sink.INPUT, condition = "headers['type']=='foo'") - public String receive(String value) { - return null; - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java deleted file mode 100644 index 33c9094d8..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2017-2018 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 - * - * https://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 com.fasterxml.jackson.databind.ObjectMapper; -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.annotation.StreamListener; -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.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Marius Bogoevici - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - * @since 1.2 - */ -@RunWith(SpringJUnit4ClassRunner.class) -// @checkstyle:off -@SpringBootTest(classes = TextPlainToJsonConversionTest.FooProcessor.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) -// @checkstyle:on -public class TextPlainToJsonConversionTest { - - @Autowired - private Processor testProcessor; - - @Autowired - private BinderFactory binderFactory; - - private ObjectMapper mapper = new ObjectMapper(); - - @SuppressWarnings("unchecked") - @Test - public void testNoContentTypeToJsonConversionOnInput() throws Exception { - this.testProcessor.input() - .send(MessageBuilder.withPayload("{\"name\":\"Bar\"}").build()); - Message received = (Message) ((TestSupportBinder) this.binderFactory - .getBinder(null, MessageChannel.class)).messageCollector() - .forChannel(this.testProcessor.output()) - .poll(1, TimeUnit.SECONDS); - assertThat(received).isNotNull(); - Foo foo = this.mapper.readValue(received.getPayload(), Foo.class); - assertThat(foo.getName()).isEqualTo("transformed-Bar"); - } - - /** - * @since 2.0: Conversion from text/plain -> json is no longer supported. Strict - * contentType only. - */ - @Test(expected = MessagingException.class) - public void testTextPlainToJsonConversionOnInput() { - this.testProcessor.input().send(MessageBuilder.withPayload("{\"name\":\"Bar\"}") - .setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build()); - } - - @EnableBinding(Processor.class) - @EnableAutoConfiguration - public static class FooProcessor { - - @StreamListener("input") - @SendTo("output") - public Foo consume(Foo foo) { - Foo returnFoo = new Foo(); - returnFoo.setName("transformed-" + foo.getName()); - return returnFoo; - } - - } - - public static class Foo { - - private String name; - - public Foo() { - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return "Foo{name='" + this.name + "'}"; - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java.todo b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java.todo new file mode 100644 index 000000000..cf877e9ee --- /dev/null +++ b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/TextPlainToJsonConversionTest.java.todo @@ -0,0 +1,123 @@ +///* +// * Copyright 2017-2018 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 +// * +// * https://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 com.fasterxml.jackson.databind.ObjectMapper; +//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.annotation.StreamListener; +//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.integration.support.MessageBuilder; +//import org.springframework.messaging.Message; +//import org.springframework.messaging.MessageChannel; +//import org.springframework.messaging.MessageHeaders; +//import org.springframework.messaging.MessagingException; +//import org.springframework.messaging.handler.annotation.SendTo; +//import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +///** +// * @author Marius Bogoevici +// * @author Vinicius Carvalho +// * @author Oleg Zhurakousky +// * @since 1.2 +// */ +//@RunWith(SpringJUnit4ClassRunner.class) +//// @checkstyle:off +//@SpringBootTest(classes = TextPlainToJsonConversionTest.FooProcessor.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) +//// @checkstyle:on +//public class TextPlainToJsonConversionTest { +// +// @Autowired +// private Processor testProcessor; +// +// @Autowired +// private BinderFactory binderFactory; +// +// private ObjectMapper mapper = new ObjectMapper(); +// +// @SuppressWarnings("unchecked") +// @Test +// public void testNoContentTypeToJsonConversionOnInput() throws Exception { +// this.testProcessor.input() +// .send(MessageBuilder.withPayload("{\"name\":\"Bar\"}").build()); +// Message received = (Message) ((TestSupportBinder) this.binderFactory +// .getBinder(null, MessageChannel.class)).messageCollector() +// .forChannel(this.testProcessor.output()) +// .poll(1, TimeUnit.SECONDS); +// assertThat(received).isNotNull(); +// Foo foo = this.mapper.readValue(received.getPayload(), Foo.class); +// assertThat(foo.getName()).isEqualTo("transformed-Bar"); +// } +// +// /** +// * @since 2.0: Conversion from text/plain -> json is no longer supported. Strict +// * contentType only. +// */ +// @Test(expected = MessagingException.class) +// public void testTextPlainToJsonConversionOnInput() { +// this.testProcessor.input().send(MessageBuilder.withPayload("{\"name\":\"Bar\"}") +// .setHeader(MessageHeaders.CONTENT_TYPE, "text/plain").build()); +// } +// +// @EnableBinding(Processor.class) +// @EnableAutoConfiguration +// public static class FooProcessor { +// +// @StreamListener("input") +// @SendTo("output") +// public Foo consume(Foo foo) { +// Foo returnFoo = new Foo(); +// returnFoo.setName("transformed-" + foo.getName()); +// return returnFoo; +// } +// +// } +// +// public static class Foo { +// +// private String name; +// +// public Foo() { +// } +// +// public String getName() { +// return this.name; +// } +// +// public void setName(String name) { +// this.name = name; +// } +// +// @Override +// public String toString() { +// return "Foo{name='" + this.name + "'}"; +// } +// +// } +// +//} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java deleted file mode 100644 index 3c341fd0e..000000000 --- a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2017-2019 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 - * - * https://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.contentType; - -import java.util.LinkedList; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Test; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.messaging.Source; -import org.springframework.cloud.stream.test.binder.MessageCollector; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.handler.annotation.Headers; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Vinicius Carvalho - * @author Oleg Zhurakousky - */ -@SuppressWarnings("unchecked") -public class ContentTypeTests { - - private ObjectMapper mapper = new ObjectMapper(); - - @Test - public void testSendWithDefaultContentType() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", - "--spring.jmx.enabled=false")) { - - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - User user = new User("Alice"); - source.output().send(MessageBuilder.withPayload(user).build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - User received = this.mapper.readValue(message.getPayload(), User.class); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.APPLICATION_JSON)); - assertThat(user.getName()).isEqualTo(received.getName()); - } - } - - @Test - public void testSendJsonAsString() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", - "--spring.jmx.enabled=false")) { - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - User user = new User("Alice"); - String json = this.mapper.writeValueAsString(user); - source.output().send(MessageBuilder.withPayload(user).build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.APPLICATION_JSON)); - assertThat(json).isEqualTo(message.getPayload()); - } - } - - @Test - public void testSendJsonString() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", - "--spring.jmx.enabled=false")) { - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - source.output().send(MessageBuilder.withPayload("foo").build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.APPLICATION_JSON)); - assertThat("foo").isEqualTo(message.getPayload()); - } - } - - @Test - public void testSendBynaryData() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", - "--spring.jmx.enabled=false")) { - - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - byte[] data = new byte[] { 0, 1, 2, 3 }; - source.output() - .send(MessageBuilder.withPayload(data) - .setHeader(MessageHeaders.CONTENT_TYPE, - MimeTypeUtils.APPLICATION_OCTET_STREAM) - .build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.APPLICATION_OCTET_STREAM)); - assertThat(message.getPayload()).isEqualTo(data); - } - } - - @Test - public void testSendBinaryDataWithContentType() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", "--spring.jmx.enabled=false", - "--spring.cloud.stream.bindings.output.contentType=image/jpeg")) { - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - byte[] data = new byte[] { 0, 1, 2, 3 }; - source.output().send(MessageBuilder.withPayload(data).build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - assertThat(message.getPayload()).isEqualTo(data); - } - } - - @Test - public void testSendBinaryDataWithContentTypeUsingHeaders() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", - "--spring.jmx.enabled=false")) { - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - byte[] data = new byte[] { 0, 1, 2, 3 }; - source.output().send(MessageBuilder.withPayload(data) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.IMAGE_JPEG) - .build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.IMAGE_JPEG)); - assertThat(message.getPayload()).isEqualTo(data); - } - } - - @Test - public void testSendStringType() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SourceApplication.class, "--server.port=0", "--spring.jmx.enabled=false", - "--spring.cloud.stream.bindings.output.contentType=text/plain")) { - MessageCollector collector = context.getBean(MessageCollector.class); - Source source = context.getBean(Source.class); - User user = new User("Alice"); - source.output().send(MessageBuilder.withPayload(user).build()); - Message message = (Message) collector - .forChannel(source.output()).poll(1, TimeUnit.SECONDS); - assertThat( - message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) - .includes(MimeTypeUtils.TEXT_PLAIN)); - assertThat(message.getPayload()).isEqualTo(user.toString()); - } - } - - @Test - public void testReceiveWithDefaults() throws Exception { - try (ConfigurableApplicationContext context = SpringApplication.run( - SinkApplication.class, "--server.port=0", "--spring.jmx.enabled=false")) { - TestSink testSink = context.getBean(TestSink.class); - SinkApplication sourceApp = context.getBean(SinkApplication.class); - User user = new User("Alice"); - testSink.pojo().send(MessageBuilder - .withPayload(this.mapper.writeValueAsBytes(user)).build()); - Map headers = (Map) sourceApp.arguments.pop(); - User received = (User) sourceApp.arguments.pop(); - assertThat(((MimeType) headers.get(MessageHeaders.CONTENT_TYPE)) - .includes(MimeTypeUtils.APPLICATION_JSON)); - assertThat(user.getName()).isEqualTo(received.getName()); - } - } - - @Test - public void testReceiveRawWithDifferentContentTypes() { - try (ConfigurableApplicationContext context = SpringApplication.run( - SinkApplication.class, "--server.port=0", "--spring.jmx.enabled=false")) { - TestSink testSink = context.getBean(TestSink.class); - SinkApplication sourceApp = context.getBean(SinkApplication.class); - testSink.raw().send(MessageBuilder.withPayload(new byte[4]) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.IMAGE_JPEG) - .build()); - testSink.raw().send(MessageBuilder.withPayload(new byte[4]) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.IMAGE_GIF) - .build()); - Map headers = (Map) sourceApp.arguments.pop(); - sourceApp.arguments.pop(); - assertThat(((MimeType) headers.get(MessageHeaders.CONTENT_TYPE)) - .includes(MimeTypeUtils.IMAGE_GIF)); - headers = (Map) sourceApp.arguments.pop(); - sourceApp.arguments.pop(); - assertThat(((MimeType) headers.get(MessageHeaders.CONTENT_TYPE)) - .includes(MimeTypeUtils.IMAGE_JPEG)); - } - } - - - public interface TestSink { - - @Input("POJO_INPUT") - SubscribableChannel pojo(); - - @Input("STRING_INPUT") - SubscribableChannel string(); - - @Input("TUPLE_INPUT") - SubscribableChannel tuple(); - - @Input("RAW_INPUT") - SubscribableChannel raw(); - - } - - @EnableBinding(Source.class) - @SpringBootApplication - public static class SourceApplication { - - } - - @EnableBinding(TestSink.class) - @SpringBootApplication - public static class SinkApplication { - - public LinkedList arguments = new LinkedList<>(); - - @StreamListener("POJO_INPUT") - public void receive(User user, @Headers Map headers) { - this.arguments.push(user); - this.arguments.push(headers); - } - - @StreamListener("STRING_INPUT") - public void receive(String string) { - } - - @StreamListener("RAW_INPUT") - public void receive(byte[] data, @Headers Map headers) { - this.arguments.push(data); - this.arguments.push(headers); - } - - } - -} diff --git a/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java.todo b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java.todo new file mode 100644 index 000000000..06ed93ff8 --- /dev/null +++ b/spring-cloud-stream-integration-tests/src/test/java/org/springframework/cloud/stream/config/contentType/ContentTypeTests.java.todo @@ -0,0 +1,272 @@ +///* +// * Copyright 2017-2019 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 +// * +// * https://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.contentType; +// +//import java.util.LinkedList; +//import java.util.Map; +//import java.util.concurrent.TimeUnit; +// +//import com.fasterxml.jackson.databind.ObjectMapper; +//import org.junit.Test; +// +//import org.springframework.boot.SpringApplication; +//import org.springframework.boot.autoconfigure.SpringBootApplication; +//import org.springframework.cloud.stream.annotation.EnableBinding; +//import org.springframework.cloud.stream.annotation.Input; +//import org.springframework.cloud.stream.annotation.StreamListener; +//import org.springframework.cloud.stream.messaging.Source; +//import org.springframework.cloud.stream.test.binder.MessageCollector; +//import org.springframework.context.ConfigurableApplicationContext; +//import org.springframework.integration.support.MessageBuilder; +//import org.springframework.messaging.Message; +//import org.springframework.messaging.MessageHeaders; +//import org.springframework.messaging.SubscribableChannel; +//import org.springframework.messaging.handler.annotation.Headers; +//import org.springframework.util.MimeType; +//import org.springframework.util.MimeTypeUtils; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +///** +// * @author Vinicius Carvalho +// * @author Oleg Zhurakousky +// */ +//@SuppressWarnings("unchecked") +//public class ContentTypeTests { +// +// private ObjectMapper mapper = new ObjectMapper(); +// +// @Test +// public void testSendWithDefaultContentType() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", +// "--spring.jmx.enabled=false")) { +// +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// User user = new User("Alice"); +// source.output().send(MessageBuilder.withPayload(user).build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// User received = this.mapper.readValue(message.getPayload(), User.class); +// assertThat( +// message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) +// .includes(MimeTypeUtils.APPLICATION_JSON)); +// assertThat(user.getName()).isEqualTo(received.getName()); +// } +// } +// +// @Test +// public void testSendJsonAsString() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", +// "--spring.jmx.enabled=false")) { +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// User user = new User("Alice"); +// String json = this.mapper.writeValueAsString(user); +// source.output().send(MessageBuilder.withPayload(user).build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// assertThat( +// message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) +// .includes(MimeTypeUtils.APPLICATION_JSON)); +// assertThat(json).isEqualTo(message.getPayload()); +// } +// } +// +// @Test +// public void testSendJsonString() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", +// "--spring.jmx.enabled=false")) { +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// source.output().send(MessageBuilder.withPayload("foo").build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// assertThat( +// message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) +// .includes(MimeTypeUtils.APPLICATION_JSON)); +// assertThat("foo").isEqualTo(message.getPayload()); +// } +// } +// +// @Test +// public void testSendBynaryData() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", +// "--spring.jmx.enabled=false")) { +// +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// byte[] data = new byte[] { 0, 1, 2, 3 }; +// source.output() +// .send(MessageBuilder.withPayload(data) +// .setHeader(MessageHeaders.CONTENT_TYPE, +// MimeTypeUtils.APPLICATION_OCTET_STREAM) +// .build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// assertThat( +// message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) +// .includes(MimeTypeUtils.APPLICATION_OCTET_STREAM)); +// assertThat(message.getPayload()).isEqualTo(data); +// } +// } +// +// @Test +// public void testSendBinaryDataWithContentType() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", "--spring.jmx.enabled=false", +// "--spring.cloud.stream.bindings.output.contentType=image/jpeg")) { +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// byte[] data = new byte[] { 0, 1, 2, 3 }; +// source.output().send(MessageBuilder.withPayload(data).build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// assertThat(message.getPayload()).isEqualTo(data); +// } +// } +// +// @Test +// public void testSendBinaryDataWithContentTypeUsingHeaders() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", +// "--spring.jmx.enabled=false")) { +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// byte[] data = new byte[] { 0, 1, 2, 3 }; +// source.output().send(MessageBuilder.withPayload(data) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.IMAGE_JPEG) +// .build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// assertThat( +// message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) +// .includes(MimeTypeUtils.IMAGE_JPEG)); +// assertThat(message.getPayload()).isEqualTo(data); +// } +// } +// +// @Test +// public void testSendStringType() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SourceApplication.class, "--server.port=0", "--spring.jmx.enabled=false", +// "--spring.cloud.stream.bindings.output.contentType=text/plain")) { +// MessageCollector collector = context.getBean(MessageCollector.class); +// Source source = context.getBean(Source.class); +// User user = new User("Alice"); +// source.output().send(MessageBuilder.withPayload(user).build()); +// Message message = (Message) collector +// .forChannel(source.output()).poll(1, TimeUnit.SECONDS); +// assertThat( +// message.getHeaders().get(MessageHeaders.CONTENT_TYPE, MimeType.class) +// .includes(MimeTypeUtils.TEXT_PLAIN)); +// assertThat(message.getPayload()).isEqualTo(user.toString()); +// } +// } +// +// @Test +// public void testReceiveWithDefaults() throws Exception { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SinkApplication.class, "--server.port=0", "--spring.jmx.enabled=false")) { +// TestSink testSink = context.getBean(TestSink.class); +// SinkApplication sourceApp = context.getBean(SinkApplication.class); +// User user = new User("Alice"); +// testSink.pojo().send(MessageBuilder +// .withPayload(this.mapper.writeValueAsBytes(user)).build()); +// Map headers = (Map) sourceApp.arguments.pop(); +// User received = (User) sourceApp.arguments.pop(); +// assertThat(((MimeType) headers.get(MessageHeaders.CONTENT_TYPE)) +// .includes(MimeTypeUtils.APPLICATION_JSON)); +// assertThat(user.getName()).isEqualTo(received.getName()); +// } +// } +// +// @Test +// public void testReceiveRawWithDifferentContentTypes() { +// try (ConfigurableApplicationContext context = SpringApplication.run( +// SinkApplication.class, "--server.port=0", "--spring.jmx.enabled=false")) { +// TestSink testSink = context.getBean(TestSink.class); +// SinkApplication sourceApp = context.getBean(SinkApplication.class); +// testSink.raw().send(MessageBuilder.withPayload(new byte[4]) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.IMAGE_JPEG) +// .build()); +// testSink.raw().send(MessageBuilder.withPayload(new byte[4]) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.IMAGE_GIF) +// .build()); +// Map headers = (Map) sourceApp.arguments.pop(); +// sourceApp.arguments.pop(); +// assertThat(((MimeType) headers.get(MessageHeaders.CONTENT_TYPE)) +// .includes(MimeTypeUtils.IMAGE_GIF)); +// headers = (Map) sourceApp.arguments.pop(); +// sourceApp.arguments.pop(); +// assertThat(((MimeType) headers.get(MessageHeaders.CONTENT_TYPE)) +// .includes(MimeTypeUtils.IMAGE_JPEG)); +// } +// } +// +// +// public interface TestSink { +// +// @Input("POJO_INPUT") +// SubscribableChannel pojo(); +// +// @Input("STRING_INPUT") +// SubscribableChannel string(); +// +// @Input("TUPLE_INPUT") +// SubscribableChannel tuple(); +// +// @Input("RAW_INPUT") +// SubscribableChannel raw(); +// +// } +// +// @EnableBinding(Source.class) +// @SpringBootApplication +// public static class SourceApplication { +// +// } +// +// @EnableBinding(TestSink.class) +// @SpringBootApplication +// public static class SinkApplication { +// +// public LinkedList arguments = new LinkedList<>(); +// +// @StreamListener("POJO_INPUT") +// public void receive(User user, @Headers Map headers) { +// this.arguments.push(user); +// this.arguments.push(headers); +// } +// +// @StreamListener("STRING_INPUT") +// public void receive(String string) { +// } +// +// @StreamListener("RAW_INPUT") +// public void receive(byte[] data, @Headers Map headers) { +// this.arguments.push(data); +// this.arguments.push(headers); +// } +// +// } +// +//} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/annotation/StreamListener.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/annotation/StreamListener.java deleted file mode 100644 index bad7b106a..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/annotation/StreamListener.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.springframework.cloud.stream.binding.StreamListenerParameterAdapter; -import org.springframework.core.annotation.AliasFor; -import org.springframework.messaging.handler.annotation.MessageMapping; - -/** - * NOTE: It is no longer recommended to use StreamListener in favor of functional programming model. - * It will be deprecated and subsequently removed in the future - *
- *
- * Annotation that marks a method to be a listener to inputs declared via - * {@link EnableBinding} (e.g. channels). - * - * Annotated methods are allowed to have flexible signatures, which determine how the - * method is invoked and how their return results are processed. This annotation can be - * applied for two separate classes of methods. - * - *

Declarative mode

- * - * A method is considered declarative if all its method parameter types and return type - * (if not void) are binding targets or conversion targets from binding targets via a - * registered {@link StreamListenerParameterAdapter}. - * - * Only declarative methods can have binding targets or conversion targets as arguments - * and return type. - * - * Declarative methods must specify what inputs and outputs correspond to their arguments - * and return type, and can do this in one of the following ways. - * - *
    - *
  • By using either the {@link Input} or {@link Output} annotation for each of the - * parameters and the {@link Output} annotation on the method for the return type (if - * applicable). The use of annotations in this case is mandatory. In this case the - * {@link StreamListener} annotation must not specify a value.
  • - *
  • By setting an {@link Input} bound target as the annotation value of - * {@link StreamListener} and using - * {@link org.springframework.messaging.handler.annotation.SendTo} on the method for - * the return type (if applicable). In this case the method must have exactly one - * parameter, corresponding to an input. - *
  • - *
- * - * An example of declarative method signature using the former idiom is as follows: - * - *
- * @StreamListener
- * public @Output("joined") Flux<String> join(
- *       @Input("input1") Flux<String> input1,
- *       @Input("input2") Flux<String> input2) {
- *   // ... join the two input streams via functional operators
- * }
- * 
- * - * An example of declarative method signature using the latter idiom is as follows: - * - *
- * @StreamListener(Processor.INPUT)
- * @SendTo(Processor.OUTPUT)
- * public Flux<String> convert(Flux<String> input) {
- *     return input.map(String::toUppercase);
- * }
- * 
- * - * Declarative methods are invoked only once, when the context is refreshed. - * - *

Individual message handler mode

- * - * Non declarative methods are treated as message handler based, and are invoked for each - * incoming message received from that target. In this case, the method can have a - * flexible signature, as described by {@link MessageMapping}. - * - * If the method returns a {@link org.springframework.messaging.Message}, the result will - * be automatically sent to a binding target, as follows: - *
    - *
  • A result of the type {@link org.springframework.messaging.Message} will be sent - * as-is
  • - *
  • All other results will become the payload of a - * {@link org.springframework.messaging.Message}
  • - *
- * - * The output binding target where the return message is sent is determined by consulting - * in the following order: - *
    - *
  • The {@link org.springframework.messaging.MessageHeaders} of the resulting - * message.
  • - *
  • The value set on the - * {@link org.springframework.messaging.handler.annotation.SendTo} annotation, if - * present
  • - *
- * - * An example of individual message handler signature is as follows: - * - *
- * @StreamListener(Processor.INPUT)
- * @SendTo(Processor.OUTPUT)
- * public String convert(String input) {
- * 		return input.toUppercase();
- * }
- * 
- * - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Gary Russell - * @see MessageMapping - * @see EnableBinding - * @see org.springframework.messaging.handler.annotation.SendTo - * - * @deprecated as of 3.1 in favor of functional programming model - */ -@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@MessageMapping -@Documented -@Deprecated -public @interface StreamListener { - - /** - * The name of the binding target (e.g. channel) that the method subscribes to. - * @return the name of the binding target. - */ - @AliasFor("target") - String value() default ""; - - /** - * The name of the binding target (e.g. channel) that the method subscribes to. - * @return the name of the binding target. - */ - @AliasFor("value") - String target() default ""; - - /** - * A condition that must be met by all items that are dispatched to this method. - * @return a SpEL expression that must evaluate to a {@code boolean} value. - */ - String condition() default ""; - - /** - * When "true" (default), and a {@code @SendTo} annotation is present, copy the - * inbound headers to the outbound message (if the header is absent on the outbound - * message). Can be an expression ({@code #{...}}) or property placeholder. Must - * resolve to a boolean or a string that is parsed by {@code Boolean.parseBoolean()}. - * An expression that resolves to {@code null} is interpreted to mean {@code false}. - * - * The expression is evaluated during application initialization, and not for each - * individual message. - * - * Prior to version 1.3.0, the default value used to be "false" and headers were not - * propagated by default. - * - * Starting with version 1.3.0, the default value is "true". - * - * @since 1.2.3 - * @return {@link Boolean} in a String format - */ - String copyHeaders() default "true"; - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/DispatchingStreamListenerMessageHandler.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/DispatchingStreamListenerMessageHandler.java deleted file mode 100644 index 9efd38543..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/DispatchingStreamListenerMessageHandler.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2017-2019 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 - * - * https://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.binding; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; -import org.springframework.messaging.Message; -import org.springframework.util.Assert; - -/** - * An {@link AbstractReplyProducingMessageHandler} that delegates to a collection of - * internal {@link ConditionalStreamListenerMessageHandlerWrapper} instances, executing - * the ones that match the given expression. - * - * @author Marius Bogoevici - * @since 1.2 - */ -final class DispatchingStreamListenerMessageHandler - extends AbstractReplyProducingMessageHandler { - - private final List handlerMethods; - - private final boolean evaluateExpressions; - - private final EvaluationContext evaluationContext; - - DispatchingStreamListenerMessageHandler( - Collection handlerMethods, - EvaluationContext evaluationContext) { - Assert.notEmpty(handlerMethods, "'handlerMethods' cannot be empty"); - this.handlerMethods = Collections - .unmodifiableList(new ArrayList<>(handlerMethods)); - boolean evaluateExpressions = false; - for (ConditionalStreamListenerMessageHandlerWrapper handlerMethod : handlerMethods) { - if (handlerMethod.getCondition() != null) { - evaluateExpressions = true; - break; - } - } - this.evaluateExpressions = evaluateExpressions; - if (evaluateExpressions) { - Assert.notNull(evaluationContext, - "'evaluationContext' cannot be null if conditions are used"); - } - this.evaluationContext = evaluationContext; - } - - @Override - protected boolean shouldCopyRequestHeaders() { - return false; - } - - @Override - protected Object handleRequestMessage(Message requestMessage) { - List matchingHandlers = this.evaluateExpressions - ? findMatchingHandlers(requestMessage) : this.handlerMethods; - if (matchingHandlers.size() == 0) { - if (this.logger.isWarnEnabled()) { - this.logger.warn( - "Cannot find a @StreamListener matching for message with id: " - + requestMessage.getHeaders().getId()); - } - return null; - } - else if (matchingHandlers.size() > 1) { - for (ConditionalStreamListenerMessageHandlerWrapper matchingMethod : matchingHandlers) { - matchingMethod.getStreamListenerMessageHandler() - .handleMessage(requestMessage); - } - return null; - } - else { - final ConditionalStreamListenerMessageHandlerWrapper singleMatchingHandler = matchingHandlers - .get(0); - singleMatchingHandler.getStreamListenerMessageHandler() - .handleMessage(requestMessage); - return null; - } - } - - private List findMatchingHandlers( - Message message) { - ArrayList matchingMethods = new ArrayList<>(); - for (ConditionalStreamListenerMessageHandlerWrapper wrapper : this.handlerMethods) { - if (wrapper.getCondition() == null) { - matchingMethods.add(wrapper); - } - else { - boolean conditionMetOnMessage = wrapper.getCondition() - .getValue(this.evaluationContext, message, Boolean.class); - if (conditionMetOnMessage) { - matchingMethods.add(wrapper); - } - } - } - return matchingMethods; - } - - static class ConditionalStreamListenerMessageHandlerWrapper { - - private final Expression condition; - - private final StreamListenerMessageHandler streamListenerMessageHandler; - - ConditionalStreamListenerMessageHandlerWrapper(Expression condition, - StreamListenerMessageHandler streamListenerMessageHandler) { - Assert.notNull(streamListenerMessageHandler, - "the message handler cannot be null"); - Assert.isTrue(condition == null || streamListenerMessageHandler.isVoid(), - "cannot specify a condition and a return value at the same time"); - this.condition = condition; - this.streamListenerMessageHandler = streamListenerMessageHandler; - } - - public Expression getCondition() { - return this.condition; - } - - public boolean isVoid() { - return this.streamListenerMessageHandler.isVoid(); - } - - public StreamListenerMessageHandler getStreamListenerMessageHandler() { - return this.streamListenerMessageHandler; - } - - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/MessageChannelStreamListenerResultAdapter.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/MessageChannelStreamListenerResultAdapter.java deleted file mode 100644 index 16ce41dff..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/MessageChannelStreamListenerResultAdapter.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.binding; - -import java.io.Closeable; -import java.io.IOException; - -import org.springframework.integration.handler.BridgeHandler; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.SubscribableChannel; - -/** - * A {@link StreamListenerResultAdapter} used for bridging an - * {@link org.springframework.cloud.stream.annotation.Output} {@link MessageChannel} to a - * bound {@link MessageChannel}. - * - * @author Marius Bogoevici - * @author Soby Chacko - */ -public class MessageChannelStreamListenerResultAdapter - implements StreamListenerResultAdapter { - - @Override - public boolean supports(Class resultType, Class bindingTarget) { - return MessageChannel.class.isAssignableFrom(resultType) - && MessageChannel.class.isAssignableFrom(bindingTarget); - } - - @Override - public Closeable adapt(MessageChannel streamListenerResult, - MessageChannel bindingTarget) { - BridgeHandler handler = new BridgeHandler(); - handler.setOutputChannel(bindingTarget); - handler.afterPropertiesSet(); - ((SubscribableChannel) streamListenerResult).subscribe(handler); - - return new NoOpCloseeable(); - } - - private static final class NoOpCloseeable implements Closeable { - - @Override - public void close() throws IOException { - - } - - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java deleted file mode 100644 index b4d9b3e40..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Copyright 2016-2020 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 - * - * https://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.binding; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import org.springframework.aop.framework.Advised; -import org.springframework.aop.support.AopUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.beans.factory.config.BeanExpressionContext; -import org.springframework.beans.factory.config.BeanExpressionResolver; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.config.SpringIntegrationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.Expression; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.integration.context.IntegrationContextUtils; -import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory; -import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; -import org.springframework.util.Assert; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -/** - * {@link BeanPostProcessor} that handles {@link StreamListener} annotations found on bean - * methods. - * - * @author Marius Bogoevici - * @author Ilayaperumal Gopinathan - * @author Soby Chacko - * @author Oleg Zhurakousky - */ -public class StreamListenerAnnotationBeanPostProcessor implements BeanPostProcessor, - ApplicationContextAware, SmartInitializingSingleton { - - private static final SpelExpressionParser SPEL_EXPRESSION_PARSER = new SpelExpressionParser(); - - // @checkstyle:off - private final MultiValueMap mappedListenerMethods = new LinkedMultiValueMap<>(); - - // @checkstyle:on - - private final Set streamListenerCallbacks = new HashSet<>(); - - // == dependencies that are injected in 'afterSingletonsInstantiated' to avoid early - // initialization - //private DestinationResolver binderAwareChannelResolver; - - private MessageHandlerMethodFactory messageHandlerMethodFactory; - - // == end dependencies - private SpringIntegrationProperties springIntegrationProperties; - - private ConfigurableApplicationContext applicationContext; - - private BeanExpressionResolver resolver; - - private BeanExpressionContext expressionContext; - - private Set streamListenerSetupMethodOrchestrators = new LinkedHashSet<>(); - - private boolean streamListenerPresent; - - @Override - public final void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - this.applicationContext = (ConfigurableApplicationContext) applicationContext; - this.resolver = this.applicationContext.getBeanFactory() - .getBeanExpressionResolver(); - this.expressionContext = new BeanExpressionContext( - this.applicationContext.getBeanFactory(), null); - } - - @Override - public final void afterSingletonsInstantiated() { - if (!this.streamListenerPresent) { - return; - } - this.injectAndPostProcessDependencies(); - EvaluationContext evaluationContext = IntegrationContextUtils - .getEvaluationContext(this.applicationContext.getBeanFactory()); - for (Map.Entry> mappedBindingEntry : this.mappedListenerMethods - .entrySet()) { - ArrayList handlers; - handlers = new ArrayList<>(); - for (StreamListenerHandlerMethodMapping mapping : mappedBindingEntry - .getValue()) { - final InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory - .createInvocableHandlerMethod(mapping.getTargetBean(), - checkProxy(mapping.getMethod(), mapping.getTargetBean())); - StreamListenerMessageHandler streamListenerMessageHandler = new StreamListenerMessageHandler( - invocableHandlerMethod, - resolveExpressionAsBoolean(mapping.getCopyHeaders(), - "copyHeaders"), - this.springIntegrationProperties - .getMessageHandlerNotPropagatedHeaders()); - streamListenerMessageHandler - .setApplicationContext(this.applicationContext); - streamListenerMessageHandler - .setBeanFactory(this.applicationContext.getBeanFactory()); - if (StringUtils.hasText(mapping.getDefaultOutputChannel())) { - streamListenerMessageHandler - .setOutputChannelName(mapping.getDefaultOutputChannel()); - } - streamListenerMessageHandler.afterPropertiesSet(); - if (StringUtils.hasText(mapping.getCondition())) { - String conditionAsString = resolveExpressionAsString( - mapping.getCondition(), "condition"); - Expression condition = SPEL_EXPRESSION_PARSER - .parseExpression(conditionAsString); - handlers.add( - new DispatchingStreamListenerMessageHandler.ConditionalStreamListenerMessageHandlerWrapper( - condition, streamListenerMessageHandler)); - } - else { - handlers.add( - new DispatchingStreamListenerMessageHandler.ConditionalStreamListenerMessageHandlerWrapper( - null, streamListenerMessageHandler)); - } - } - if (handlers.size() > 1) { - for (DispatchingStreamListenerMessageHandler.ConditionalStreamListenerMessageHandlerWrapper handler : handlers) { - Assert.isTrue(handler.isVoid(), - StreamListenerErrorMessages.MULTIPLE_VALUE_RETURNING_METHODS); - } - } - AbstractReplyProducingMessageHandler handler; - - if (handlers.size() > 1 || handlers.get(0).getCondition() != null) { - handler = new DispatchingStreamListenerMessageHandler(handlers, - evaluationContext); - } - else { - handler = handlers.get(0).getStreamListenerMessageHandler(); - } - handler.setApplicationContext(this.applicationContext); - //handler.setChannelResolver(this.binderAwareChannelResolver); - handler.afterPropertiesSet(); - this.applicationContext.getBeanFactory().registerSingleton( - handler.getClass().getSimpleName() + handler.hashCode(), handler); - this.applicationContext - .getBean(mappedBindingEntry.getKey(), SubscribableChannel.class) - .subscribe(handler); - } - this.mappedListenerMethods.clear(); - } - - @Override - public final Object postProcessAfterInitialization(Object bean, final String beanName) - throws BeansException { - Class targetClass = AopUtils.isAopProxy(bean) ? AopUtils.getTargetClass(bean) - : bean.getClass(); - Method[] uniqueDeclaredMethods = ReflectionUtils - .getUniqueDeclaredMethods(targetClass, ReflectionUtils.USER_DECLARED_METHODS); - for (Method method : uniqueDeclaredMethods) { - StreamListener streamListener = AnnotatedElementUtils - .findMergedAnnotation(method, StreamListener.class); - if (streamListener != null) { - this.streamListenerPresent = true; - this.streamListenerCallbacks.add(() -> { - Assert.isTrue(method.getAnnotation(Input.class) == null, - StreamListenerErrorMessages.INPUT_AT_STREAM_LISTENER); - this.doPostProcess(streamListener, method, bean); - }); - } - } - return bean; - } - - /** - * Extension point, allowing subclasses to customize the {@link StreamListener} - * annotation detected by the postprocessor. - * @param originalAnnotation the original annotation - * @param annotatedMethod the method on which the annotation has been found - * @return the postprocessed {@link StreamListener} annotation - */ - protected StreamListener postProcessAnnotation(StreamListener originalAnnotation, - Method annotatedMethod) { - return originalAnnotation; - } - - private void doPostProcess(StreamListener streamListener, Method method, - Object bean) { - streamListener = postProcessAnnotation(streamListener, method); - Optional orchestratorOptional; - orchestratorOptional = this.streamListenerSetupMethodOrchestrators.stream() - .filter(t -> t.supports(method)).findFirst(); - Assert.isTrue(orchestratorOptional.isPresent(), - "A matching StreamListenerSetupMethodOrchestrator must be present"); - StreamListenerSetupMethodOrchestrator streamListenerSetupMethodOrchestrator = orchestratorOptional - .get(); - streamListenerSetupMethodOrchestrator - .orchestrateStreamListenerSetupMethod(streamListener, method, bean); - } - - private Method checkProxy(Method methodArg, Object bean) { - Method method = methodArg; - if (AopUtils.isJdkDynamicProxy(bean)) { - try { - // Found a @StreamListener method on the target class for this JDK proxy - // -> - // is it also present on the proxy itself? - method = bean.getClass().getMethod(method.getName(), - method.getParameterTypes()); - Class[] proxiedInterfaces = ((Advised) bean).getProxiedInterfaces(); - for (Class iface : proxiedInterfaces) { - try { - method = iface.getMethod(method.getName(), - method.getParameterTypes()); - break; - } - catch (NoSuchMethodException noMethod) { - } - } - } - catch (SecurityException ex) { - ReflectionUtils.handleReflectionException(ex); - } - catch (NoSuchMethodException ex) { - throw new IllegalStateException(String.format( - "@StreamListener method '%s' found on bean target class '%s', " - + "but not found in any interface(s) for bean JDK proxy. Either " - + "pull the method up to an interface or switch to subclass (CGLIB) " - + "proxies by setting proxy-target-class/proxyTargetClass attribute to 'true'", - method.getName(), method.getDeclaringClass().getSimpleName()), - ex); - } - } - return method; - } - - private String resolveExpressionAsString(String value, String property) { - Object resolved = resolveExpression(value); - if (resolved instanceof String) { - return (String) resolved; - } - else { - throw new IllegalStateException("Resolved " + property + " to [" - + resolved.getClass() + "] instead of String for [" + value + "]"); - } - } - - private boolean resolveExpressionAsBoolean(String value, String property) { - Object resolved = resolveExpression(value); - if (resolved == null) { - return false; - } - else if (resolved instanceof String) { - return Boolean.parseBoolean((String) resolved); - } - else if (resolved instanceof Boolean) { - return (Boolean) resolved; - } - else { - throw new IllegalStateException( - "Resolved " + property + " to [" + resolved.getClass() - + "] instead of String or Boolean for [" + value + "]"); - } - } - - private String resolveExpression(String value) { - String resolvedValue = this.applicationContext.getBeanFactory() - .resolveEmbeddedValue(value); - if (resolvedValue.startsWith("#{") && value.endsWith("}")) { - resolvedValue = (String) this.resolver.evaluate(resolvedValue, - this.expressionContext); - } - return resolvedValue; - } - - /** - * This operations ensures that required dependencies are not accidentally injected - * early given that this bean is BPP. - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - private void injectAndPostProcessDependencies() { - Collection streamListenerParameterAdapters = this.applicationContext - .getBeansOfType(StreamListenerParameterAdapter.class).values(); - Collection streamListenerResultAdapters = this.applicationContext - .getBeansOfType(StreamListenerResultAdapter.class).values(); - //this.binderAwareChannelResolver = this.applicationContext - // .getBean("binderAwareChannelResolver", DestinationResolver.class); - this.messageHandlerMethodFactory = this.applicationContext - .getBean("integrationMessageHandlerMethodFactory", MessageHandlerMethodFactory.class); - this.springIntegrationProperties = this.applicationContext - .getBean(SpringIntegrationProperties.class); - - this.streamListenerSetupMethodOrchestrators.addAll(this.applicationContext - .getBeansOfType(StreamListenerSetupMethodOrchestrator.class).values()); - - // Default orchestrator for StreamListener method invocation is added last into - // the LinkedHashSet. - this.streamListenerSetupMethodOrchestrators.add( - new DefaultStreamListenerSetupMethodOrchestrator(this.applicationContext, - streamListenerParameterAdapters, streamListenerResultAdapters)); - - this.streamListenerCallbacks.forEach(Runnable::run); - } - - private static class StreamListenerHandlerMethodMapping { - - private final Object targetBean; - - private final Method method; - - private final String condition; - - private final String defaultOutputChannel; - - private final String copyHeaders; - - StreamListenerHandlerMethodMapping(Object targetBean, Method method, - String condition, String defaultOutputChannel, String copyHeaders) { - this.targetBean = targetBean; - this.method = method; - this.condition = condition; - this.defaultOutputChannel = defaultOutputChannel; - this.copyHeaders = copyHeaders; - } - - Object getTargetBean() { - return this.targetBean; - } - - Method getMethod() { - return this.method; - } - - String getCondition() { - return this.condition; - } - - String getDefaultOutputChannel() { - return this.defaultOutputChannel; - } - - public String getCopyHeaders() { - return this.copyHeaders; - } - - } - - @SuppressWarnings("rawtypes") - private final class DefaultStreamListenerSetupMethodOrchestrator - implements StreamListenerSetupMethodOrchestrator { - - private final ConfigurableApplicationContext applicationContext; - - private final Collection streamListenerParameterAdapters; - - private final Collection streamListenerResultAdapters; - - private DefaultStreamListenerSetupMethodOrchestrator( - ConfigurableApplicationContext applicationContext, - Collection streamListenerParameterAdapters, - Collection streamListenerResultAdapters) { - this.applicationContext = applicationContext; - this.streamListenerParameterAdapters = streamListenerParameterAdapters; - this.streamListenerResultAdapters = streamListenerResultAdapters; - } - - @Override - public void orchestrateStreamListenerSetupMethod(StreamListener streamListener, - Method method, Object bean) { - String methodAnnotatedInboundName = streamListener.value(); - - String methodAnnotatedOutboundName = StreamListenerMethodUtils - .getOutboundBindingTargetName(method); - int inputAnnotationCount = StreamListenerMethodUtils - .inputAnnotationCount(method); - int outputAnnotationCount = StreamListenerMethodUtils - .outputAnnotationCount(method); - boolean isDeclarative = checkDeclarativeMethod(method, - methodAnnotatedInboundName, methodAnnotatedOutboundName); - StreamListenerMethodUtils.validateStreamListenerMethod(method, - inputAnnotationCount, outputAnnotationCount, - methodAnnotatedInboundName, methodAnnotatedOutboundName, - isDeclarative, streamListener.condition()); - if (isDeclarative) { - StreamListenerParameterAdapter[] toSlpaArray; - toSlpaArray = new StreamListenerParameterAdapter[this.streamListenerParameterAdapters - .size()]; - Object[] adaptedInboundArguments = adaptAndRetrieveInboundArguments( - method, methodAnnotatedInboundName, this.applicationContext, - this.streamListenerParameterAdapters.toArray(toSlpaArray)); - invokeStreamListenerResultAdapter(method, bean, - methodAnnotatedOutboundName, adaptedInboundArguments); - } - else { - registerHandlerMethodOnListenedChannel(method, streamListener, bean); - } - } - - @Override - public boolean supports(Method method) { - // default catch all orchestrator - return true; - } - - @SuppressWarnings("unchecked") - private void invokeStreamListenerResultAdapter(Method method, Object bean, - String outboundName, Object... arguments) { - try { - if (Void.TYPE.equals(method.getReturnType())) { - method.invoke(bean, arguments); - } - else { - Object result = method.invoke(bean, arguments); - if (!StringUtils.hasText(outboundName)) { - for (int parameterIndex = 0; parameterIndex < method - .getParameterCount(); parameterIndex++) { - MethodParameter methodParameter = MethodParameter - .forExecutable(method, parameterIndex); - if (methodParameter.hasParameterAnnotation(Output.class)) { - outboundName = methodParameter - .getParameterAnnotation(Output.class).value(); - } - } - } - Object targetBean = this.applicationContext.getBean(outboundName); - for (StreamListenerResultAdapter streamListenerResultAdapter : this.streamListenerResultAdapters) { - if (streamListenerResultAdapter.supports(result.getClass(), - targetBean.getClass())) { - streamListenerResultAdapter.adapt(result, targetBean); - break; - } - } - } - } - catch (Exception e) { - throw new BeanInitializationException( - "Cannot setup StreamListener for " + method, e); - } - } - - private void registerHandlerMethodOnListenedChannel(Method method, - StreamListener streamListener, Object bean) { - Assert.hasText(streamListener.value(), "The binding name cannot be null"); - if (!StringUtils.hasText(streamListener.value())) { - throw new BeanInitializationException( - "A bound component name must be specified"); - } - final String defaultOutputChannel = StreamListenerMethodUtils - .getOutboundBindingTargetName(method); - if (Void.TYPE.equals(method.getReturnType())) { - Assert.isTrue(StringUtils.isEmpty(defaultOutputChannel), - "An output channel cannot be specified for a method that does not return a value"); - } - else { - Assert.isTrue(!StringUtils.isEmpty(defaultOutputChannel), - "An output channel must be specified for a method that can return a value"); - } - StreamListenerMethodUtils.validateStreamListenerMessageHandler(method); - StreamListenerAnnotationBeanPostProcessor.this.mappedListenerMethods.add( - streamListener.value(), - new StreamListenerHandlerMethodMapping(bean, method, - streamListener.condition(), defaultOutputChannel, - streamListener.copyHeaders())); - } - - private boolean checkDeclarativeMethod(Method method, - String methodAnnotatedInboundName, String methodAnnotatedOutboundName) { - int methodArgumentsLength = method.getParameterCount(); - for (int parameterIndex = 0; parameterIndex < methodArgumentsLength; parameterIndex++) { - MethodParameter methodParameter = MethodParameter.forExecutable(method, - parameterIndex); - if (methodParameter.hasParameterAnnotation(Input.class)) { - String inboundName = (String) AnnotationUtils.getValue( - methodParameter.getParameterAnnotation(Input.class)); - Assert.isTrue(StringUtils.hasText(inboundName), - StreamListenerErrorMessages.INVALID_INBOUND_NAME); - Assert.isTrue( - isDeclarativeMethodParameter(inboundName, methodParameter), - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - return true; - } - else if (methodParameter.hasParameterAnnotation(Output.class)) { - String outboundName = (String) AnnotationUtils.getValue( - methodParameter.getParameterAnnotation(Output.class)); - Assert.isTrue(StringUtils.hasText(outboundName), - StreamListenerErrorMessages.INVALID_OUTBOUND_NAME); - Assert.isTrue( - isDeclarativeMethodParameter(outboundName, methodParameter), - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - return true; - } - else if (StringUtils.hasText(methodAnnotatedOutboundName)) { - return isDeclarativeMethodParameter(methodAnnotatedOutboundName, - methodParameter); - } - else if (StringUtils.hasText(methodAnnotatedInboundName)) { - return isDeclarativeMethodParameter(methodAnnotatedInboundName, - methodParameter); - } - } - return false; - } - - /** - * Determines if method parameters signify an imperative or declarative listener - * definition.
- * Imperative - where handler method is invoked on each message by the handler - * infrastructure provided by the framework
- * Declarative - where handler is provided by the method itself.
- * Declarative method parameter could either be {@link MessageChannel} or any - * other Object for which there is a {@link StreamListenerParameterAdapter} (i.e., - * {@link reactor.core.publisher.Flux}). Declarative method is invoked only once - * during initialization phase. - * @param targetBeanName name of the bean - * @param methodParameter method parameter - * @return {@code true} when the method parameter is declarative - */ - @SuppressWarnings("unchecked") - private boolean isDeclarativeMethodParameter(String targetBeanName, - MethodParameter methodParameter) { - boolean declarative = false; - if (!methodParameter.getParameterType().isAssignableFrom(Object.class) - && this.applicationContext.containsBean(targetBeanName)) { - declarative = MessageChannel.class - .isAssignableFrom(methodParameter.getParameterType()); - if (!declarative) { - Class targetBeanClass = this.applicationContext - .getType(targetBeanName); - declarative = this.streamListenerParameterAdapters.stream().anyMatch( - slpa -> slpa.supports(targetBeanClass, methodParameter)); - } - } - return declarative; - } - - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerErrorMessages.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerErrorMessages.java deleted file mode 100644 index cf1a19311..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerErrorMessages.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2016-2019 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 - * - * https://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.binding; - -/** - * @author Ilayaperumal Gopinathan - */ -public abstract class StreamListenerErrorMessages { - - /** - * Error message when the inbound name was invalid. - */ - public static final String INVALID_INBOUND_NAME = "The @Input annotation must have the name of an input as value"; - - /** - * Error message when the outbound name was invalid. - */ - public static final String INVALID_OUTBOUND_NAME = "The @Output annotation must have the name of an input as value"; - - /** - * Error message when there were no outputs specified. - */ - public static final String ATLEAST_ONE_OUTPUT = "At least one output must be specified"; - - /** - * Error message when multiple destinations were specified. - */ - public static final String SEND_TO_MULTIPLE_DESTINATIONS = "Multiple destinations cannot be specified"; - - /** - * Error message when empty destination was provided. - */ - public static final String SEND_TO_EMPTY_DESTINATION = "An empty destination cannot be specified"; - - /** - * Error message when the input or output annotation got placed on a method parameter. - */ - public static final String INVALID_INPUT_OUTPUT_METHOD_PARAMETERS = "@Input or @Output annotations " - + "are not permitted on " - + "method parameters while using the @StreamListener value and a method-level output specification"; - - /** - * Error message when no input destination was provided. - */ - public static final String NO_INPUT_DESTINATION = "No input destination is configured. " - + "Use either the @StreamListener value or @Input"; - - /** - * Error message when an ambiguous message handler method argument was found. - */ - public static final String AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS = "Ambiguous method arguments " - + "for the StreamListener method"; - - /** - * Error message when invalid input values where set. - */ - public static final String INVALID_INPUT_VALUES = "Cannot set both @StreamListener " - + "value and @Input annotation as method parameter"; - - /** - * Error message when invalid input value with output method parameter was set. - */ - public static final String INVALID_INPUT_VALUE_WITH_OUTPUT_METHOD_PARAM = "Setting the @StreamListener " - + "value when using @Output annotation as method parameter is not permitted. " - + "Use @Input method parameter annotation to specify inbound value instead"; - - /** - * Error message when invalid output values were set. - */ - public static final String INVALID_OUTPUT_VALUES = "Cannot set both output (@Output/@SendTo) method annotation value" - + " and @Output annotation as a method parameter"; - - /** - * Error message when condition was set in declarative mode. - */ - public static final String CONDITION_ON_DECLARATIVE_METHOD = "Cannot set a condition when " - + "using @StreamListener in declarative mode"; - - /** - * Error message when condition was set for methods that return a value. - */ - public static final String CONDITION_ON_METHOD_RETURNING_VALUE = "Cannot set a condition " - + "for methods that return a value"; - - /** - * Error message when multiple value returning methods were provided. - */ - public static final String MULTIPLE_VALUE_RETURNING_METHODS = "If multiple @StreamListener " - + "methods are listening to the same binding target, none of them may return a value"; - - private static final String PREFIX = "A method annotated with @StreamListener "; - - /** - * Error message when @StreamListener was used with @Input. - */ - public static final String INPUT_AT_STREAM_LISTENER = PREFIX - + "may never be annotated with @Input. " - + "If it should listen to a specific input, use the value of @StreamListener instead"; - - /** - * Error message when invalid input value with output method parameter was set. - */ - public static final String RETURN_TYPE_NO_OUTBOUND_SPECIFIED = PREFIX - + "having a return type should also have an outbound target specified"; - - /** - * Error message when return type was specified for multiple outbound targets. - */ - public static final String RETURN_TYPE_MULTIPLE_OUTBOUND_SPECIFIED = PREFIX - + "having a return type should have only one outbound target specified"; - - /** - * Error message when invalid declarative method parameters were set. - */ - public static final String INVALID_DECLARATIVE_METHOD_PARAMETERS = PREFIX - + "may use @Input or @Output annotations only in declarative mode " - + "and for parameters that are binding targets or convertible from binding targets."; - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMessageHandler.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMessageHandler.java deleted file mode 100644 index 4a311ce4a..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMessageHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017-2019 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 - * - * https://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.binding; - -import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; - -/** - * @author Marius Bogoevici - * @author Gary Russell - * @since 1.2 - */ -public class StreamListenerMessageHandler extends AbstractReplyProducingMessageHandler { - - private final InvocableHandlerMethod invocableHandlerMethod; - - private final boolean copyHeaders; - - StreamListenerMessageHandler(InvocableHandlerMethod invocableHandlerMethod, - boolean copyHeaders, String[] notPropagatedHeaders) { - super(); - this.invocableHandlerMethod = invocableHandlerMethod; - this.copyHeaders = copyHeaders; - this.setNotPropagatedHeaders(notPropagatedHeaders); - } - - @Override - protected boolean shouldCopyRequestHeaders() { - return this.copyHeaders; - } - - public boolean isVoid() { - return this.invocableHandlerMethod.isVoid(); - } - - @Override - protected Object handleRequestMessage(Message requestMessage) { - try { - return this.invocableHandlerMethod.invoke(requestMessage); - } - catch (Exception e) { - if (e instanceof MessagingException) { - throw (MessagingException) e; - } - else { - throw new MessagingException(requestMessage, - "Exception thrown while invoking " - + this.invocableHandlerMethod.getShortLogMessage(), - e); - } - } - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMethodUtils.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMethodUtils.java deleted file mode 100644 index d61905941..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerMethodUtils.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2016-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 - * - * https://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.binding; - -import java.lang.reflect.Method; - -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; - -/** - * This class contains utility methods for handling {@link StreamListener} annotated bean - * methods. - * - * @author Ilayaperumal Gopinathan - */ -public final class StreamListenerMethodUtils { - - private StreamListenerMethodUtils() { - throw new IllegalStateException("Can't instantiate a utility class"); - } - - protected static int inputAnnotationCount(Method method) { - int inputAnnotationCount = 0; - for (int parameterIndex = 0; parameterIndex < method - .getParameterTypes().length; parameterIndex++) { - MethodParameter methodParameter = MethodParameter.forExecutable(method, - parameterIndex); - if (methodParameter.hasParameterAnnotation(Input.class)) { - inputAnnotationCount++; - } - } - return inputAnnotationCount; - } - - protected static int outputAnnotationCount(Method method) { - int outputAnnotationCount = 0; - for (int parameterIndex = 0; parameterIndex < method - .getParameterTypes().length; parameterIndex++) { - MethodParameter methodParameter = MethodParameter.forExecutable(method, - parameterIndex); - if (methodParameter.hasParameterAnnotation(Output.class)) { - outputAnnotationCount++; - } - } - return outputAnnotationCount; - } - - protected static void validateStreamListenerMethod(Method method, - int inputAnnotationCount, int outputAnnotationCount, - String methodAnnotatedInboundName, String methodAnnotatedOutboundName, - boolean isDeclarative, String condition) { - int methodArgumentsLength = method.getParameterTypes().length; - if (!isDeclarative) { - Assert.isTrue(inputAnnotationCount == 0 && outputAnnotationCount == 0, - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - if (StringUtils.hasText(methodAnnotatedInboundName) - && StringUtils.hasText(methodAnnotatedOutboundName)) { - Assert.isTrue(inputAnnotationCount == 0 && outputAnnotationCount == 0, - StreamListenerErrorMessages.INVALID_INPUT_OUTPUT_METHOD_PARAMETERS); - } - if (StringUtils.hasText(methodAnnotatedInboundName)) { - Assert.isTrue(inputAnnotationCount == 0, - StreamListenerErrorMessages.INVALID_INPUT_VALUES); - Assert.isTrue(outputAnnotationCount == 0, - StreamListenerErrorMessages.INVALID_INPUT_VALUE_WITH_OUTPUT_METHOD_PARAM); - } - else { - Assert.isTrue(inputAnnotationCount >= 1, - StreamListenerErrorMessages.NO_INPUT_DESTINATION); - } - if (StringUtils.hasText(methodAnnotatedOutboundName)) { - Assert.isTrue(outputAnnotationCount == 0, - StreamListenerErrorMessages.INVALID_OUTPUT_VALUES); - } - if (!Void.TYPE.equals(method.getReturnType())) { - Assert.isTrue(!StringUtils.hasText(condition), - StreamListenerErrorMessages.CONDITION_ON_METHOD_RETURNING_VALUE); - } - if (isDeclarative) { - Assert.isTrue(!StringUtils.hasText(condition), - StreamListenerErrorMessages.CONDITION_ON_DECLARATIVE_METHOD); - for (int parameterIndex = 0; parameterIndex < methodArgumentsLength; parameterIndex++) { - MethodParameter methodParameter = MethodParameter.forExecutable(method, - parameterIndex); - if (methodParameter.hasParameterAnnotation(Input.class)) { - String inboundName = (String) AnnotationUtils.getValue( - methodParameter.getParameterAnnotation(Input.class)); - Assert.isTrue(StringUtils.hasText(inboundName), - StreamListenerErrorMessages.INVALID_INBOUND_NAME); - } - if (methodParameter.hasParameterAnnotation(Output.class)) { - String outboundName = (String) AnnotationUtils.getValue( - methodParameter.getParameterAnnotation(Output.class)); - Assert.isTrue(StringUtils.hasText(outboundName), - StreamListenerErrorMessages.INVALID_OUTBOUND_NAME); - } - } - if (methodArgumentsLength > 1) { - Assert.isTrue( - inputAnnotationCount - + outputAnnotationCount == methodArgumentsLength, - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - - if (!method.getReturnType().equals(Void.TYPE)) { - if (!StringUtils.hasText(methodAnnotatedOutboundName)) { - if (outputAnnotationCount == 0) { - throw new IllegalArgumentException( - StreamListenerErrorMessages.RETURN_TYPE_NO_OUTBOUND_SPECIFIED); - } - Assert.isTrue((outputAnnotationCount == 1), - StreamListenerErrorMessages.RETURN_TYPE_MULTIPLE_OUTBOUND_SPECIFIED); - } - } - } - - protected static void validateStreamListenerMessageHandler(Method method) { - int methodArgumentsLength = method.getParameterTypes().length; - if (methodArgumentsLength > 1) { - int numAnnotatedMethodParameters = 0; - int numPayloadAnnotations = 0; - for (int parameterIndex = 0; parameterIndex < methodArgumentsLength; parameterIndex++) { - MethodParameter methodParameter = MethodParameter.forExecutable(method, - parameterIndex); - if (methodParameter.hasParameterAnnotations()) { - numAnnotatedMethodParameters++; - } - if (methodParameter.hasParameterAnnotation(Payload.class)) { - numPayloadAnnotations++; - } - } - if (numPayloadAnnotations > 0) { - Assert.isTrue( - methodArgumentsLength == numAnnotatedMethodParameters - && numPayloadAnnotations <= 1, - StreamListenerErrorMessages.AMBIGUOUS_MESSAGE_HANDLER_METHOD_ARGUMENTS); - } - } - } - - protected static String getOutboundBindingTargetName(Method method) { - SendTo sendTo = AnnotationUtils.findAnnotation(method, SendTo.class); - if (sendTo != null) { - Assert.isTrue(!ObjectUtils.isEmpty(sendTo.value()), - StreamListenerErrorMessages.ATLEAST_ONE_OUTPUT); - Assert.isTrue(sendTo.value().length == 1, - StreamListenerErrorMessages.SEND_TO_MULTIPLE_DESTINATIONS); - Assert.hasText(sendTo.value()[0], - StreamListenerErrorMessages.SEND_TO_EMPTY_DESTINATION); - return sendTo.value()[0]; - } - Output output = AnnotationUtils.findAnnotation(method, Output.class); - if (output != null) { - Assert.isTrue(StringUtils.hasText(output.value()), - StreamListenerErrorMessages.ATLEAST_ONE_OUTPUT); - return output.value(); - } - return null; - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerParameterAdapter.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerParameterAdapter.java deleted file mode 100644 index 7d7ebf784..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerParameterAdapter.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016-2019 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 - * - * https://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.binding; - -import org.springframework.core.MethodParameter; - -/** - * Strategy for adapting a method argument type annotated with - * {@link org.springframework.cloud.stream.annotation.Input} or - * {@link org.springframework.cloud.stream.annotation.Output} from a binding type (e.g. - * {@link org.springframework.messaging.MessageChannel}) supported by an existing binder. - * - * This is a framework extension and is not primarily intended for use by end-users. - * - * @param adapter type - * @param binding result type - * @author Marius Bogoevici - */ -public interface StreamListenerParameterAdapter { - - /** - * Return true if the conversion from the binding target type to the argument type is - * supported. - * @param bindingTargetType the binding target type - * @param methodParameter the method parameter for which the conversion is performed - * @return true if the conversion is supported - */ - boolean supports(Class bindingTargetType, MethodParameter methodParameter); - - /** - * Adapts the binding target to the argument type. The result will be passed as - * argument to a method annotated with - * {@link org.springframework.cloud.stream.annotation.StreamListener} when used for - * setting up a pipeline. - * @param bindingTarget the binding target - * @param parameter the method parameter for which the conversion is performed - * @return an instance of the parameter type, which will be passed to the method - */ - A adapt(B bindingTarget, MethodParameter parameter); - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerResultAdapter.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerResultAdapter.java deleted file mode 100644 index 6724a5263..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerResultAdapter.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2016-2019 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 - * - * https://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.binding; - -import java.io.Closeable; - -/** - * A strategy for adapting the result of a - * {@link org.springframework.cloud.stream.annotation.StreamListener} annotated method to - * a binding target annotated with - * {@link org.springframework.cloud.stream.annotation.Output}. - * - * Used when the {@link org.springframework.cloud.stream.annotation.StreamListener} - * annotated method is operating in declarative mode. - * - * @param stream listener result type - * @param binding target type - * @author Marius Bogoevici - */ -public interface StreamListenerResultAdapter { - - /** - * Return true if the result type can be converted to the binding target. - * @param resultType the result type. - * @param bindingTarget the binding target. - * @return true if the conversion can take place. - */ - boolean supports(Class resultType, Class bindingTarget); - - /** - * Adapts the result to the binding target. - * @param streamListenerResult the result of invoking the method. - * @param bindingTarget the binding target. - * @return an adapted result - */ - Closeable adapt(R streamListenerResult, B bindingTarget); - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerSetupMethodOrchestrator.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerSetupMethodOrchestrator.java deleted file mode 100644 index e1fe39af8..000000000 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerSetupMethodOrchestrator.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2018-2019 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 - * - * https://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.binding; - -import java.lang.reflect.Method; - -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.Output; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.context.ApplicationContext; -import org.springframework.core.MethodParameter; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Orchestrator used for invoking the {@link StreamListener} setup method. - * - * By default {@link StreamListenerAnnotationBeanPostProcessor} will use an internal - * implementation of this interface to invoke {@link StreamListenerParameterAdapter}s and - * {@link StreamListenerResultAdapter}s or handler mappings on the method annotated with - * {@link StreamListener}. - * - * By providing a different implementation of this interface and registering it as a - * Spring Bean in the context, one can override the default invocation strategies used by - * the {@link StreamListenerAnnotationBeanPostProcessor}. A typical usecase for such - * overriding can happen when a downstream - * {@link org.springframework.cloud.stream.binder.Binder} implementation wants to change - * the way in which any of the default StreamListener handling needs to be changed in a - * custom manner. - * - * When beans of this interface are present in the context, they get priority in the - * {@link StreamListenerAnnotationBeanPostProcessor} before falling back to the default - * implementation. - * - * @author Soby Chacko - * @see StreamListener - * @see StreamListenerAnnotationBeanPostProcessor - */ -public interface StreamListenerSetupMethodOrchestrator { - - /** - * Checks the method annotated with {@link StreamListener} to see if this - * implementation can successfully orchestrate this method. - * @param method annotated with {@link StreamListener} - * @return true if this implementation can orchestrate this method, false otherwise - */ - boolean supports(Method method); - - /** - * Method that allows custom orchestration on the {@link StreamListener} setup method. - * @param streamListener reference to the {@link StreamListener} annotation on the - * method - * @param method annotated with {@link StreamListener} - * @param bean that contains the StreamListener method - * - */ - void orchestrateStreamListenerSetupMethod(StreamListener streamListener, - Method method, Object bean); - - /** - * Default implementation for adapting each of the incoming method arguments using an - * available {@link StreamListenerParameterAdapter} and provide the adapted collection - * of arguments back to the caller. - * @param method annotated with {@link StreamListener} - * @param inboundName inbound binding - * @param applicationContext spring application context - * @param streamListenerParameterAdapters used for adapting the method arguments - * @return adapted incoming arguments - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - default Object[] adaptAndRetrieveInboundArguments(Method method, String inboundName, - ApplicationContext applicationContext, - StreamListenerParameterAdapter... streamListenerParameterAdapters) { - Object[] arguments = new Object[method.getParameterTypes().length]; - for (int parameterIndex = 0; parameterIndex < arguments.length; parameterIndex++) { - MethodParameter methodParameter = MethodParameter.forExecutable(method, - parameterIndex); - Class parameterType = methodParameter.getParameterType(); - Object targetReferenceValue = null; - if (methodParameter.hasParameterAnnotation(Input.class)) { - targetReferenceValue = AnnotationUtils - .getValue(methodParameter.getParameterAnnotation(Input.class)); - } - else if (methodParameter.hasParameterAnnotation(Output.class)) { - targetReferenceValue = AnnotationUtils - .getValue(methodParameter.getParameterAnnotation(Output.class)); - } - else if (arguments.length == 1 && StringUtils.hasText(inboundName)) { - targetReferenceValue = inboundName; - } - if (targetReferenceValue != null) { - Assert.isInstanceOf(String.class, targetReferenceValue, - "Annotation value must be a String"); - Object targetBean = applicationContext - .getBean((String) targetReferenceValue); - // Iterate existing parameter adapters first - for (StreamListenerParameterAdapter streamListenerParameterAdapter : streamListenerParameterAdapters) { - if (streamListenerParameterAdapter.supports(targetBean.getClass(), - methodParameter)) { - arguments[parameterIndex] = streamListenerParameterAdapter - .adapt(targetBean, methodParameter); - break; - } - } - if (arguments[parameterIndex] == null - && parameterType.isAssignableFrom(targetBean.getClass())) { - arguments[parameterIndex] = targetBean; - } - Assert.notNull(arguments[parameterIndex], - "Cannot convert argument " + parameterIndex + " of " + method - + "from " + targetBean.getClass() + " to " - + parameterType); - } - else { - throw new IllegalStateException( - StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS); - } - } - return arguments; - } - -} diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java index 8bb16c341..f6fb6ef7d 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java @@ -49,9 +49,7 @@ import org.springframework.cloud.stream.binding.BindingsLifecycleController; import org.springframework.cloud.stream.binding.ContextStartAfterRefreshListener; import org.springframework.cloud.stream.binding.DynamicDestinationsBindable; import org.springframework.cloud.stream.binding.InputBindingLifecycle; -import org.springframework.cloud.stream.binding.MessageChannelStreamListenerResultAdapter; import org.springframework.cloud.stream.binding.OutputBindingLifecycle; -import org.springframework.cloud.stream.binding.StreamListenerAnnotationBeanPostProcessor; import org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider; import org.springframework.cloud.stream.function.StreamFunctionProperties; import org.springframework.cloud.stream.micrometer.DestinationPublishingMetricsAutoConfiguration; @@ -175,12 +173,6 @@ public class BindingServiceConfiguration { }; } - @Bean(name = STREAM_LISTENER_ANNOTATION_BEAN_POST_PROCESSOR_NAME) - @ConditionalOnMissingBean(search = SearchStrategy.CURRENT) - public static StreamListenerAnnotationBeanPostProcessor streamListenerAnnotationBeanPostProcessor() { - return new StreamListenerAnnotationBeanPostProcessor(); - } - @Bean public BindingHandlerAdvise BindingHandlerAdvise( @Nullable MappingsProvider[] providers) { @@ -207,11 +199,6 @@ public class BindingServiceConfiguration { return binderFactory; } - @Bean - public MessageChannelStreamListenerResultAdapter messageChannelStreamListenerResultAdapter() { - return new MessageChannelStreamListenerResultAdapter(); - } - @Bean // This conditional is intentionally not in an autoconfig (usually a bad idea) because // it is used to detect a BindingService in the parent context (which we know diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/ErrorBindingTests.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/ErrorBindingTests.java index 6846ff1fc..303ba97e9 100644 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/ErrorBindingTests.java +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/ErrorBindingTests.java @@ -16,6 +16,9 @@ package org.springframework.cloud.stream.binder; +import java.util.function.Consumer; +import java.util.function.Function; + import org.junit.Test; import org.mockito.Mockito; @@ -23,14 +26,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.cloud.stream.binder.test.InputDestination; import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.cloud.stream.messaging.Sink; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; @@ -58,9 +58,9 @@ public class ErrorBindingTests { Binder binder = binderFactory.getBinder(null, MessageChannel.class); - Mockito.verify(binder).bindConsumer(eq("input"), isNull(), + Mockito.verify(binder).bindConsumer(eq("processor-in-0"), isNull(), any(MessageChannel.class), any(ConsumerProperties.class)); - Mockito.verify(binder).bindProducer(eq("output"), any(MessageChannel.class), + Mockito.verify(binder).bindProducer(eq("processor-out-0"), any(MessageChannel.class), any(ProducerProperties.class)); Mockito.verifyNoMoreInteractions(binder); applicationContext.close(); @@ -72,7 +72,7 @@ public class ErrorBindingTests { TestChannelBinderConfiguration.getCompleteConfiguration( ErrorBindingTests.ErrorConfigurationDefault.class)) .web(WebApplicationType.NONE) - .run("--spring.cloud.stream.bindings.input.consumer.max-attempts=1", + .run("--spring.cloud.stream.bindings.handle-in-0.consumer.max-attempts=1", "--spring.jmx.enabled=false"); InputDestination source = context.getBean(InputDestination.class); @@ -91,7 +91,7 @@ public class ErrorBindingTests { TestChannelBinderConfiguration.getCompleteConfiguration( ErrorBindingTests.ErrorConfigurationWithCustomErrorHandler.class)) .web(WebApplicationType.NONE) - .run("--spring.cloud.stream.bindings.input.consumer.max-attempts=1", + .run("--spring.cloud.stream.bindings.handle-in-0.consumer.max-attempts=1", "--spring.jmx.enabled=false"); InputDestination source = context.getBean(InputDestination.class); @@ -104,36 +104,41 @@ public class ErrorBindingTests { assertThat(errorConfiguration.counter == 6); } - @EnableBinding(Processor.class) @EnableAutoConfiguration public static class TestProcessor { + @Bean + public Function processor() { + return s -> s; + } } - @EnableBinding(Processor.class) @EnableAutoConfiguration public static class ErrorConfigurationDefault { private int counter; - @StreamListener(Sink.INPUT) - public void handle(Object value) { - this.counter++; - throw new RuntimeException("BOOM!"); + @Bean + public Consumer handle() { + return v -> { + this.counter++; + throw new RuntimeException("BOOM!"); + }; } } - @EnableBinding(Processor.class) @EnableAutoConfiguration public static class ErrorConfigurationWithCustomErrorHandler { private int counter; - @StreamListener(Sink.INPUT) - public void handle(Object value) { - this.counter++; - throw new RuntimeException("BOOM!"); + @Bean + public Consumer handle() { + return v -> { + this.counter++; + throw new RuntimeException("BOOM!"); + }; } @ServiceActivator(inputChannel = "input.anonymous.errors") diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java deleted file mode 100644 index d6644ea35..000000000 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * Copyright 2017-2018 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 - * - * https://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.binder.tck; - -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Ignore; -import org.junit.Test; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binder.test.InputDestination; -import org.springframework.cloud.stream.binder.test.OutputDestination; -import org.springframework.cloud.stream.binder.test.TestChannelBinder; -import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.integration.channel.DirectChannel; -import org.springframework.lang.Nullable; -import org.springframework.messaging.Message; -import org.springframework.messaging.MessageChannel; -import org.springframework.messaging.MessageHeaders; -import org.springframework.messaging.MessagingException; -import org.springframework.messaging.converter.AbstractMessageConverter; -import org.springframework.messaging.converter.MessageConversionException; -import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.messaging.support.GenericMessage; -import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.MimeType; -import org.springframework.util.MimeTypeUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Sort of a TCK test suite to validate payload conversion is done properly by interacting - * with binder's input/output destinations instead of its bridged channels. This means - * that all payloads (sent/received) must be expressed in the wire format (byte[]) - * - * @author Oleg Zhurakousky - * @author Gary Russell - * - */ -public class ContentTypeTckTests { - - @Test - public void stringToMapStreamListener() { - ApplicationContext context = new SpringApplicationBuilder( - StringToMapStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload())).isEqualTo("oleg"); - } - - @Test - public void stringToMapMessageStreamListener() { - ApplicationContext context = new SpringApplicationBuilder( - StringToMapMessageStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload())).isEqualTo("oleg"); - } - - @Test - public void withInternalPipeline() { - ApplicationContext context = new SpringApplicationBuilder(InternalPipeLine.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload())).isEqualTo("OLEG"); - } - - @Test - public void pojoToPojo() { - ApplicationContext context = new SpringApplicationBuilder( - PojoToPojoStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void pojoToString() { - ApplicationContext context = new SpringApplicationBuilder( - PojoToStringStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void pojoToStringOutboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - PojoToStringStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.TEXT_PLAIN); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void pojoToByteArray() { - ApplicationContext context = new SpringApplicationBuilder( - PojoToByteArrayStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void pojoToByteArrayOutboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - PojoToByteArrayStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void stringToPojoInboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - StringToPojoStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void typelessToPojoInboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessToPojoStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void typelessToPojoInboundContentTypeBindingJson() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessToPojoStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.input.contentType=application/json", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void typelessMessageToPojoInboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessMessageToPojoStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void typelessMessageToPojoInboundContentTypeBindingJson() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessMessageToPojoStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.cloud.stream.bindings.input.contentType=application/json", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void typelessToPojoWithTextHeaderContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessToPojoStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeType.valueOf("text/plain")) - .build()); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void typelessToPojoOutboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessToMessageStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) - .setHeader("contentType", new MimeType("text", "plain")).build()); - - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.TEXT_PLAIN); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void outboundMessageWithTextContentTypeOnly() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessToMessageTextOnlyContentTypeStreamListener.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) - .setHeader("contentType", new MimeType("text")).build()); - - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE).toString()) - .isEqualTo("text/plain"); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void stringToPojoInboundContentTypeHeader() { - ApplicationContext context = new SpringApplicationBuilder( - StringToPojoStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes(), - new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, - MimeTypeUtils.TEXT_PLAIN)))); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void byteArrayToPojoInboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - ByteArrayToPojoStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void byteArrayToPojoInboundContentTypeHeader() { - ApplicationContext context = new SpringApplicationBuilder( - StringToPojoStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes(), - new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, - MimeTypeUtils.TEXT_PLAIN)))); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void byteArrayToByteArray() { - ApplicationContext context = new SpringApplicationBuilder( - ByteArrayToByteArrayStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void byteArrayToByteArrayInboundOutboundContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - ByteArrayToByteArrayStreamListener.class).web(WebApplicationType.NONE) - .run("--spring.cloud.stream.bindings.input.contentType=text/plain", - "--spring.cloud.stream.bindings.output.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void pojoMessageToStringMessage() { - ApplicationContext context = new SpringApplicationBuilder( - PojoMessageToStringMessageStreamListener.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.TEXT_PLAIN); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void pojoMessageToStringMessageServiceActivator() { - ApplicationContext context = new SpringApplicationBuilder( - PojoMessageToStringMessageServiceActivator.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.TEXT_PLAIN); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void byteArrayMessageToStringJsonMessageStreamListener() { - ApplicationContext context = new SpringApplicationBuilder( - ByteArrayMessageToStringJsonMessageStreamListener.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.APPLICATION_JSON); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("{\"name\":\"bob\"}"); - } - - @Test - public void byteArrayMessageToStringMessageStreamListener() { - ApplicationContext context = new SpringApplicationBuilder( - StringMessageToStringMessageStreamListener.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeTypeUtils.TEXT_PLAIN); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("oleg"); - } - - @Test - public void customMessageConverter_defaultContentTypeBinding() { - ApplicationContext context = new SpringApplicationBuilder( - StringToStringStreamListener.class, CustomConverters.class) - .web(WebApplicationType.NONE) - .run("--spring.cloud.stream.default.contentType=foo/bar", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage).isNotNull(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("FooBarMessageConverter"); - assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) - .isEqualTo(MimeType.valueOf("foo/bar")); - } - - // Failure tests - - @Test - public void _jsonToPojoWrongDefaultContentTypeProperty() { - ApplicationContext context = new SpringApplicationBuilder( - PojoToPojoStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.default.contentType=text/plain", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - TestChannelBinder binder = context.getBean(TestChannelBinder.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - assertThat(binder.getLastError().getPayload() instanceof MessagingException) - .isTrue(); - } - - @Test - @Ignore - public void _toStringDefaultContentTypePropertyUnknownContentType() { - ApplicationContext context = new SpringApplicationBuilder( - StringToStringStreamListener.class).web(WebApplicationType.NONE).run( - "--spring.cloud.stream.default.contentType=foo/bar", - "--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - TestChannelBinder binder = context.getBean(TestChannelBinder.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - assertThat( - binder.getLastError().getPayload() instanceof MessageConversionException) - .isTrue(); - } - - @Test - public void toCollectionWithParameterizedType() { - ApplicationContext context = new SpringApplicationBuilder( - CollectionWithParameterizedTypes.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "[{\"person\":{\"name\":\"jon\"},\"id\":123},{\"person\":{\"name\":\"jane\"},\"id\":456}]"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(outputMessage.getPayload()).isEqualTo(jsonPayload.getBytes()); - } - - // ====== - @Test - public void testWithMapInputParameter() { - ApplicationContext context = new SpringApplicationBuilder( - MapInputConfiguration.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void testWithMapPayloadParameter() { - ApplicationContext context = new SpringApplicationBuilder( - MapInputConfiguration.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void testWithListInputParameter() { - ApplicationContext context = new SpringApplicationBuilder( - ListInputConfiguration.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "[\"foo\",\"bar\"]"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void testWithMessageHeadersInputParameter() { - ApplicationContext context = new SpringApplicationBuilder( - MessageHeadersInputConfiguration.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "{\"name\":\"oleg\"}"; - source.send(new GenericMessage<>(jsonPayload.getBytes())); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isNotEqualTo(jsonPayload); - assertThat(outputMessage.getHeaders().containsKey(MessageHeaders.ID)).isTrue(); - assertThat(outputMessage.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE)) - .isTrue(); - } - - @Test - public void testWithTypelessInputParameterAndOctetStream() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessPayloadConfiguration.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "[\"foo\",\"bar\"]"; - source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) - .setHeader(MessageHeaders.CONTENT_TYPE, - MimeTypeUtils.APPLICATION_OCTET_STREAM) - .build()); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void testWithTypelessInputParameterAndServiceActivator() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessPayloadConfigurationSA.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "[\"foo\",\"bar\"]"; - source.send(MessageBuilder.withPayload(jsonPayload.getBytes()).build()); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @Test - public void testWithTypelessMessageInputParameterAndServiceActivator() { - ApplicationContext context = new SpringApplicationBuilder( - TypelessMessageConfigurationSA.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - String jsonPayload = "[\"foo\",\"bar\"]"; - source.send(MessageBuilder.withPayload(jsonPayload.getBytes()).build()); - Message outputMessage = target.receive(); - assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo(jsonPayload); - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class CollectionWithParameterizedTypes { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public List> echo(List> value) { - assertThat(value.get(0) != null).isTrue(); - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TextInJsonOutListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Message echo(String value) { - return MessageBuilder.withPayload(value).setHeader( - MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON).build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class PojoToPojoStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Person echo(Person value) { - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class PojoToStringStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String echo(Person value) { - return value.toString(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class PojoToByteArrayStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public byte[] echo(Person value) { - return value.toString().getBytes(StandardCharsets.UTF_8); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class ByteArrayToPojoStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Person echo(byte[] value) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - return mapper.readValue(value, Person.class); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class StringToPojoStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Person echo(String value) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - return mapper.readValue(value, Person.class); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessToPojoStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Person echo(Object value) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - // assume it is string because CT is text/plain - return value instanceof byte[] - ? mapper.readValue((byte[]) value, Person.class) - : mapper.readValue((String) value, Person.class); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessMessageToPojoStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Person echo(Message message) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - // assume it is string because CT is text/plain - return message.getPayload() instanceof byte[] - ? mapper.readValue((byte[]) message.getPayload(), Person.class) - : mapper.readValue((String) message.getPayload(), Person.class); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessToMessageStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Message echo(Object value) throws Exception { - return MessageBuilder.withPayload(value.toString()) - .setHeader("contentType", new MimeType("text", "plain")).build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessToMessageTextOnlyContentTypeStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Message echo(Object value) throws Exception { - return MessageBuilder.withPayload(value.toString()) - .setHeader("contentType", new MimeType("text")).build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class ByteArrayToByteArrayStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public byte[] echo(byte[] value) { - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class StringToStringStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String echo(String value) { - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - /* - * Uncomment to test MBean name quoting for ":" in bean name component of ObjectName. - * Commented to avoid "InstanceAlreadyExistsException" in other tests. - */ - // @EnableIntegrationMBeanExport - public static class StringToMapStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String echo(@Payload Map value) { - return (String) value.get("name"); - } - - @ServiceActivator(inputChannel = "input:foo.myGroup.errors") - public void error(Message message) { - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class StringToMapMessageStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String echo(Message> value) { - assertThat(value.getPayload() instanceof Map).isTrue(); - return (String) value.getPayload().get("name"); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class PojoMessageToStringMessageStreamListener { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Message echo(Message value) { - return MessageBuilder.withPayload(value.getPayload().toString()) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class PojoMessageToStringMessageServiceActivator { - - @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) - public Message echo(Message value) { - return MessageBuilder.withPayload(value.getPayload().toString()) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class StringMessageToStringMessageStreamListener { - - @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) - public Message echo(Message value) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - Person person = mapper.readValue(value.getPayload(), Person.class); - return MessageBuilder.withPayload(person.toString()) - .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) - .build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class ByteArrayMessageToStringJsonMessageStreamListener { - - @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) - public Message echo(Message value) throws Exception { - ObjectMapper mapper = new ObjectMapper(); - Person person = mapper.readValue(value.getPayload(), Person.class); - person.setName("bob"); - String json = mapper.writeValueAsString(person); - return MessageBuilder.withPayload(json).build(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class InternalPipeLine { - - @StreamListener(Processor.INPUT) - @SendTo("internalChannel") - public String handleA(Person value) { - return "{\"name\":\"" + value.getName().toUpperCase() + "\"}"; - } - - @Bean - public MessageChannel internalChannel() { - return new DirectChannel(); - } - - @StreamListener("internalChannel") - @SendTo(Processor.OUTPUT) - public String handleB(Person value) { - return value.toString(); - } - - } - - public static class Employee

{ - - private P person; - - private int id; - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - public P getPerson() { - return this.person; - } - - public void setPerson(P person) { - this.person = person; - } - - } - - public static class Person { - - private String name; - - public Person() { - this(null); - } - - public Person(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return this.name; - } - - } - - @Configuration - public static class CustomConverters { - - @Bean - public FooBarMessageConverter fooBarMessageConverter() { - return new FooBarMessageConverter(MimeType.valueOf("foo/bar")); - } - - @Bean - public AlwaysStringKryoMessageConverter kryoOverrideMessageConverter() { - return new AlwaysStringKryoMessageConverter( - MimeType.valueOf("application/x-java-object")); - } - - /** - * Even though this MessageConverter has nothing to do with Kryo it still shows - * how Kryo conversion can be customized/overriden since it simply overriding a - * converter for contentType 'application/x-java-object'. - * - */ - public static class AlwaysStringKryoMessageConverter - extends AbstractMessageConverter { - - public AlwaysStringKryoMessageConverter(MimeType supportedMimeType) { - super(supportedMimeType); - } - - @Override - protected boolean supports(Class clazz) { - return clazz == null || String.class.isAssignableFrom(clazz); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, - @Nullable Object conversionHint) { - return this.getClass().getSimpleName(); - } - - @Override - protected Object convertToInternal(Object payload, - @Nullable MessageHeaders headers, @Nullable Object conversionHint) { - return ((String) payload).getBytes(StandardCharsets.UTF_8); - } - - } - - public static class FooBarMessageConverter extends AbstractMessageConverter { - - protected FooBarMessageConverter(MimeType supportedMimeType) { - super(supportedMimeType); - } - - @Override - protected boolean supports(Class clazz) { - return clazz != null && String.class.isAssignableFrom(clazz); - } - - @Override - protected Object convertFromInternal(Message message, Class targetClass, - @Nullable Object conversionHint) { - return this.getClass().getSimpleName(); - } - - @Override - protected Object convertToInternal(Object payload, - @Nullable MessageHeaders headers, @Nullable Object conversionHint) { - return ((String) payload).getBytes(StandardCharsets.UTF_8); - } - - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class MapInputConfiguration { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Map echo(Map value) throws Exception { - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class MapPayloadConfiguration { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Map echo(Message> value) throws Exception { - return value.getPayload(); - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class ListInputConfiguration { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public List echo(List value) throws Exception { - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class MessageHeadersInputConfiguration { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Map echo(MessageHeaders value) throws Exception { - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessPayloadConfiguration { - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public Object echo(Object value) throws Exception { - System.out.println(value); - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessPayloadConfigurationSA { - - @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) - public Object echo(Object value) throws Exception { - System.out.println(value); - return value; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class TypelessMessageConfigurationSA { - - @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) - public Object echo(Message value) throws Exception { - System.out.println(value.getPayload()); - return value.getPayload(); - } - - } - -} diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java.todo b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java.todo new file mode 100644 index 000000000..2edf3f3f0 --- /dev/null +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ContentTypeTckTests.java.todo @@ -0,0 +1,1163 @@ +///* +// * Copyright 2017-2018 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 +// * +// * https://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.binder.tck; +// +//import java.nio.charset.StandardCharsets; +//import java.util.Collections; +//import java.util.List; +//import java.util.Map; +// +//import com.fasterxml.jackson.databind.ObjectMapper; +//import org.junit.Ignore; +//import org.junit.Test; +// +//import org.springframework.boot.WebApplicationType; +//import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +//import org.springframework.boot.builder.SpringApplicationBuilder; +//import org.springframework.cloud.stream.annotation.EnableBinding; +//import org.springframework.cloud.stream.annotation.StreamListener; +//import org.springframework.cloud.stream.binder.test.InputDestination; +//import org.springframework.cloud.stream.binder.test.OutputDestination; +//import org.springframework.cloud.stream.binder.test.TestChannelBinder; +//import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; +//import org.springframework.cloud.stream.messaging.Processor; +//import org.springframework.context.ApplicationContext; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.context.annotation.Import; +//import org.springframework.integration.annotation.ServiceActivator; +//import org.springframework.integration.channel.DirectChannel; +//import org.springframework.lang.Nullable; +//import org.springframework.messaging.Message; +//import org.springframework.messaging.MessageChannel; +//import org.springframework.messaging.MessageHeaders; +//import org.springframework.messaging.MessagingException; +//import org.springframework.messaging.converter.AbstractMessageConverter; +//import org.springframework.messaging.converter.MessageConversionException; +//import org.springframework.messaging.handler.annotation.Payload; +//import org.springframework.messaging.handler.annotation.SendTo; +//import org.springframework.messaging.support.GenericMessage; +//import org.springframework.messaging.support.MessageBuilder; +//import org.springframework.util.MimeType; +//import org.springframework.util.MimeTypeUtils; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +///** +// * Sort of a TCK test suite to validate payload conversion is done properly by interacting +// * with binder's input/output destinations instead of its bridged channels. This means +// * that all payloads (sent/received) must be expressed in the wire format (byte[]) +// * +// * @author Oleg Zhurakousky +// * @author Gary Russell +// * +// */ +//public class ContentTypeTckTests { +// +// @Test +// public void stringToMapStreamListener() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToMapStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload())).isEqualTo("oleg"); +// } +// +// @Test +// public void stringToMapMessageStreamListener() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToMapMessageStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload())).isEqualTo("oleg"); +// } +// +// @Test +// public void withInternalPipeline() { +// ApplicationContext context = new SpringApplicationBuilder(InternalPipeLine.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload())).isEqualTo("OLEG"); +// } +// +// @Test +// public void pojoToPojo() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoToPojoStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void pojoToString() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoToStringStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void pojoToStringOutboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoToStringStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.output.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.TEXT_PLAIN); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void pojoToByteArray() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoToByteArrayStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void pojoToByteArrayOutboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoToByteArrayStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.output.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void stringToPojoInboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToPojoStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.input.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void typelessToPojoInboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessToPojoStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.input.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void typelessToPojoInboundContentTypeBindingJson() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessToPojoStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.input.contentType=application/json", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void typelessMessageToPojoInboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessMessageToPojoStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.cloud.stream.bindings.input.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void typelessMessageToPojoInboundContentTypeBindingJson() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessMessageToPojoStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.cloud.stream.bindings.input.contentType=application/json", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void typelessToPojoWithTextHeaderContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessToPojoStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeType.valueOf("text/plain")) +// .build()); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void typelessToPojoOutboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessToMessageStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.output.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) +// .setHeader("contentType", new MimeType("text", "plain")).build()); +// +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.TEXT_PLAIN); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void outboundMessageWithTextContentTypeOnly() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessToMessageTextOnlyContentTypeStreamListener.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) +// .setHeader("contentType", new MimeType("text")).build()); +// +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE).toString()) +// .isEqualTo("text/plain"); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void stringToPojoInboundContentTypeHeader() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToPojoStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes(), +// new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, +// MimeTypeUtils.TEXT_PLAIN)))); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void byteArrayToPojoInboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// ByteArrayToPojoStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.bindings.input.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void byteArrayToPojoInboundContentTypeHeader() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToPojoStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes(), +// new MessageHeaders(Collections.singletonMap(MessageHeaders.CONTENT_TYPE, +// MimeTypeUtils.TEXT_PLAIN)))); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void byteArrayToByteArray() { +// ApplicationContext context = new SpringApplicationBuilder( +// ByteArrayToByteArrayStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void byteArrayToByteArrayInboundOutboundContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// ByteArrayToByteArrayStreamListener.class).web(WebApplicationType.NONE) +// .run("--spring.cloud.stream.bindings.input.contentType=text/plain", +// "--spring.cloud.stream.bindings.output.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void pojoMessageToStringMessage() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoMessageToStringMessageStreamListener.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.TEXT_PLAIN); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void pojoMessageToStringMessageServiceActivator() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoMessageToStringMessageServiceActivator.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.TEXT_PLAIN); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void byteArrayMessageToStringJsonMessageStreamListener() { +// ApplicationContext context = new SpringApplicationBuilder( +// ByteArrayMessageToStringJsonMessageStreamListener.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.APPLICATION_JSON); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("{\"name\":\"bob\"}"); +// } +// +// @Test +// public void byteArrayMessageToStringMessageStreamListener() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringMessageToStringMessageStreamListener.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeTypeUtils.TEXT_PLAIN); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("oleg"); +// } +// +// @Test +// public void customMessageConverter_defaultContentTypeBinding() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToStringStreamListener.class, CustomConverters.class) +// .web(WebApplicationType.NONE) +// .run("--spring.cloud.stream.default.contentType=foo/bar", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage).isNotNull(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("FooBarMessageConverter"); +// assertThat(outputMessage.getHeaders().get(MessageHeaders.CONTENT_TYPE)) +// .isEqualTo(MimeType.valueOf("foo/bar")); +// } +// +// // Failure tests +// +// @Test +// public void _jsonToPojoWrongDefaultContentTypeProperty() { +// ApplicationContext context = new SpringApplicationBuilder( +// PojoToPojoStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.default.contentType=text/plain", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// TestChannelBinder binder = context.getBean(TestChannelBinder.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// assertThat(binder.getLastError().getPayload() instanceof MessagingException) +// .isTrue(); +// } +// +// @Test +// @Ignore +// public void _toStringDefaultContentTypePropertyUnknownContentType() { +// ApplicationContext context = new SpringApplicationBuilder( +// StringToStringStreamListener.class).web(WebApplicationType.NONE).run( +// "--spring.cloud.stream.default.contentType=foo/bar", +// "--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// TestChannelBinder binder = context.getBean(TestChannelBinder.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// assertThat( +// binder.getLastError().getPayload() instanceof MessageConversionException) +// .isTrue(); +// } +// +// @Test +// public void toCollectionWithParameterizedType() { +// ApplicationContext context = new SpringApplicationBuilder( +// CollectionWithParameterizedTypes.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "[{\"person\":{\"name\":\"jon\"},\"id\":123},{\"person\":{\"name\":\"jane\"},\"id\":456}]"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(outputMessage.getPayload()).isEqualTo(jsonPayload.getBytes()); +// } +// +// // ====== +// @Test +// public void testWithMapInputParameter() { +// ApplicationContext context = new SpringApplicationBuilder( +// MapInputConfiguration.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void testWithMapPayloadParameter() { +// ApplicationContext context = new SpringApplicationBuilder( +// MapInputConfiguration.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void testWithListInputParameter() { +// ApplicationContext context = new SpringApplicationBuilder( +// ListInputConfiguration.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "[\"foo\",\"bar\"]"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void testWithMessageHeadersInputParameter() { +// ApplicationContext context = new SpringApplicationBuilder( +// MessageHeadersInputConfiguration.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "{\"name\":\"oleg\"}"; +// source.send(new GenericMessage<>(jsonPayload.getBytes())); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isNotEqualTo(jsonPayload); +// assertThat(outputMessage.getHeaders().containsKey(MessageHeaders.ID)).isTrue(); +// assertThat(outputMessage.getHeaders().containsKey(MessageHeaders.CONTENT_TYPE)) +// .isTrue(); +// } +// +// @Test +// public void testWithTypelessInputParameterAndOctetStream() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessPayloadConfiguration.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "[\"foo\",\"bar\"]"; +// source.send(MessageBuilder.withPayload(jsonPayload.getBytes()) +// .setHeader(MessageHeaders.CONTENT_TYPE, +// MimeTypeUtils.APPLICATION_OCTET_STREAM) +// .build()); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void testWithTypelessInputParameterAndServiceActivator() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessPayloadConfigurationSA.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "[\"foo\",\"bar\"]"; +// source.send(MessageBuilder.withPayload(jsonPayload.getBytes()).build()); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @Test +// public void testWithTypelessMessageInputParameterAndServiceActivator() { +// ApplicationContext context = new SpringApplicationBuilder( +// TypelessMessageConfigurationSA.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// String jsonPayload = "[\"foo\",\"bar\"]"; +// source.send(MessageBuilder.withPayload(jsonPayload.getBytes()).build()); +// Message outputMessage = target.receive(); +// assertThat(new String(outputMessage.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo(jsonPayload); +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class CollectionWithParameterizedTypes { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public List> echo(List> value) { +// assertThat(value.get(0) != null).isTrue(); +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TextInJsonOutListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Message echo(String value) { +// return MessageBuilder.withPayload(value).setHeader( +// MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON).build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class PojoToPojoStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Person echo(Person value) { +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class PojoToStringStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public String echo(Person value) { +// return value.toString(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class PojoToByteArrayStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public byte[] echo(Person value) { +// return value.toString().getBytes(StandardCharsets.UTF_8); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class ByteArrayToPojoStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Person echo(byte[] value) throws Exception { +// ObjectMapper mapper = new ObjectMapper(); +// return mapper.readValue(value, Person.class); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class StringToPojoStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Person echo(String value) throws Exception { +// ObjectMapper mapper = new ObjectMapper(); +// return mapper.readValue(value, Person.class); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessToPojoStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Person echo(Object value) throws Exception { +// ObjectMapper mapper = new ObjectMapper(); +// // assume it is string because CT is text/plain +// return value instanceof byte[] +// ? mapper.readValue((byte[]) value, Person.class) +// : mapper.readValue((String) value, Person.class); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessMessageToPojoStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Person echo(Message message) throws Exception { +// ObjectMapper mapper = new ObjectMapper(); +// // assume it is string because CT is text/plain +// return message.getPayload() instanceof byte[] +// ? mapper.readValue((byte[]) message.getPayload(), Person.class) +// : mapper.readValue((String) message.getPayload(), Person.class); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessToMessageStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Message echo(Object value) throws Exception { +// return MessageBuilder.withPayload(value.toString()) +// .setHeader("contentType", new MimeType("text", "plain")).build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessToMessageTextOnlyContentTypeStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Message echo(Object value) throws Exception { +// return MessageBuilder.withPayload(value.toString()) +// .setHeader("contentType", new MimeType("text")).build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class ByteArrayToByteArrayStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public byte[] echo(byte[] value) { +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class StringToStringStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public String echo(String value) { +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// /* +// * Uncomment to test MBean name quoting for ":" in bean name component of ObjectName. +// * Commented to avoid "InstanceAlreadyExistsException" in other tests. +// */ +// // @EnableIntegrationMBeanExport +// public static class StringToMapStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public String echo(@Payload Map value) { +// return (String) value.get("name"); +// } +// +// @ServiceActivator(inputChannel = "input:foo.myGroup.errors") +// public void error(Message message) { +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class StringToMapMessageStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public String echo(Message> value) { +// assertThat(value.getPayload() instanceof Map).isTrue(); +// return (String) value.getPayload().get("name"); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class PojoMessageToStringMessageStreamListener { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Message echo(Message value) { +// return MessageBuilder.withPayload(value.getPayload().toString()) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) +// .build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class PojoMessageToStringMessageServiceActivator { +// +// @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) +// public Message echo(Message value) { +// return MessageBuilder.withPayload(value.getPayload().toString()) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) +// .build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class StringMessageToStringMessageStreamListener { +// +// @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) +// public Message echo(Message value) throws Exception { +// ObjectMapper mapper = new ObjectMapper(); +// Person person = mapper.readValue(value.getPayload(), Person.class); +// return MessageBuilder.withPayload(person.toString()) +// .setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN) +// .build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class ByteArrayMessageToStringJsonMessageStreamListener { +// +// @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) +// public Message echo(Message value) throws Exception { +// ObjectMapper mapper = new ObjectMapper(); +// Person person = mapper.readValue(value.getPayload(), Person.class); +// person.setName("bob"); +// String json = mapper.writeValueAsString(person); +// return MessageBuilder.withPayload(json).build(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class InternalPipeLine { +// +// @StreamListener(Processor.INPUT) +// @SendTo("internalChannel") +// public String handleA(Person value) { +// return "{\"name\":\"" + value.getName().toUpperCase() + "\"}"; +// } +// +// @Bean +// public MessageChannel internalChannel() { +// return new DirectChannel(); +// } +// +// @StreamListener("internalChannel") +// @SendTo(Processor.OUTPUT) +// public String handleB(Person value) { +// return value.toString(); +// } +// +// } +// +// public static class Employee

{ +// +// private P person; +// +// private int id; +// +// public int getId() { +// return this.id; +// } +// +// public void setId(int id) { +// this.id = id; +// } +// +// public P getPerson() { +// return this.person; +// } +// +// public void setPerson(P person) { +// this.person = person; +// } +// +// } +// +// public static class Person { +// +// private String name; +// +// public Person() { +// this(null); +// } +// +// public Person(String name) { +// this.name = name; +// } +// +// public String getName() { +// return this.name; +// } +// +// public void setName(String name) { +// this.name = name; +// } +// +// @Override +// public String toString() { +// return this.name; +// } +// +// } +// +// @Configuration +// public static class CustomConverters { +// +// @Bean +// public FooBarMessageConverter fooBarMessageConverter() { +// return new FooBarMessageConverter(MimeType.valueOf("foo/bar")); +// } +// +// @Bean +// public AlwaysStringKryoMessageConverter kryoOverrideMessageConverter() { +// return new AlwaysStringKryoMessageConverter( +// MimeType.valueOf("application/x-java-object")); +// } +// +// /** +// * Even though this MessageConverter has nothing to do with Kryo it still shows +// * how Kryo conversion can be customized/overriden since it simply overriding a +// * converter for contentType 'application/x-java-object'. +// * +// */ +// public static class AlwaysStringKryoMessageConverter +// extends AbstractMessageConverter { +// +// public AlwaysStringKryoMessageConverter(MimeType supportedMimeType) { +// super(supportedMimeType); +// } +// +// @Override +// protected boolean supports(Class clazz) { +// return clazz == null || String.class.isAssignableFrom(clazz); +// } +// +// @Override +// protected Object convertFromInternal(Message message, Class targetClass, +// @Nullable Object conversionHint) { +// return this.getClass().getSimpleName(); +// } +// +// @Override +// protected Object convertToInternal(Object payload, +// @Nullable MessageHeaders headers, @Nullable Object conversionHint) { +// return ((String) payload).getBytes(StandardCharsets.UTF_8); +// } +// +// } +// +// public static class FooBarMessageConverter extends AbstractMessageConverter { +// +// protected FooBarMessageConverter(MimeType supportedMimeType) { +// super(supportedMimeType); +// } +// +// @Override +// protected boolean supports(Class clazz) { +// return clazz != null && String.class.isAssignableFrom(clazz); +// } +// +// @Override +// protected Object convertFromInternal(Message message, Class targetClass, +// @Nullable Object conversionHint) { +// return this.getClass().getSimpleName(); +// } +// +// @Override +// protected Object convertToInternal(Object payload, +// @Nullable MessageHeaders headers, @Nullable Object conversionHint) { +// return ((String) payload).getBytes(StandardCharsets.UTF_8); +// } +// +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class MapInputConfiguration { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Map echo(Map value) throws Exception { +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class MapPayloadConfiguration { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Map echo(Message> value) throws Exception { +// return value.getPayload(); +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class ListInputConfiguration { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public List echo(List value) throws Exception { +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class MessageHeadersInputConfiguration { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Map echo(MessageHeaders value) throws Exception { +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessPayloadConfiguration { +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public Object echo(Object value) throws Exception { +// System.out.println(value); +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessPayloadConfigurationSA { +// +// @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) +// public Object echo(Object value) throws Exception { +// System.out.println(value); +// return value; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class TypelessMessageConfigurationSA { +// +// @ServiceActivator(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT) +// public Object echo(Message value) throws Exception { +// System.out.println(value.getPayload()); +// return value.getPayload(); +// } +// +// } +// +//} diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java deleted file mode 100644 index f7134c610..000000000 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019-2019 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 - * - * https://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.binder.tck; - -import org.junit.Test; - -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binder.test.InputDestination; -import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Import; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.GenericMessage; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Oleg Zhurakousky - * - */ -public class ErrorHandlingTests { - - @Test - public void testGlobalErrorWithMessage() { - ApplicationContext context = new SpringApplicationBuilder( - GlobalErrorHandlerWithErrorMessageConfig.class) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - source.send(new GenericMessage<>("foo".getBytes())); - GlobalErrorHandlerWithErrorMessageConfig config = context - .getBean(GlobalErrorHandlerWithErrorMessageConfig.class); - assertThat(config.globalErroInvoked).isTrue(); - } - - @Test - public void testGlobalErrorWithThrowable() { - ApplicationContext context = new SpringApplicationBuilder( - GlobalErrorHandlerWithThrowableConfig.class).web(WebApplicationType.NONE) - .run("--spring.jmx.enabled=false"); - InputDestination source = context.getBean(InputDestination.class); - source.send(new GenericMessage<>("foo".getBytes())); - GlobalErrorHandlerWithThrowableConfig config = context - .getBean(GlobalErrorHandlerWithThrowableConfig.class); - assertThat(config.globalErroInvoked).isTrue(); - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class GlobalErrorHandlerWithErrorMessageConfig { - - private boolean globalErroInvoked; - - @StreamListener(target = Processor.INPUT) - public void input(final String value) { - throw new RuntimeException("test exception"); - } - - @StreamListener("errorChannel") - public void generalError(Message message) { - this.globalErroInvoked = true; - } - - } - - @EnableBinding(Processor.class) - @Import(TestChannelBinderConfiguration.class) - @EnableAutoConfiguration - public static class GlobalErrorHandlerWithThrowableConfig { - - private boolean globalErroInvoked; - - @StreamListener(target = Processor.INPUT) - public void input(final String value) { - throw new RuntimeException("test exception"); - } - - @StreamListener("errorChannel") - public void generalError(Throwable exception) { - this.globalErroInvoked = true; - } - - } - -} diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java.todo b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java.todo new file mode 100644 index 000000000..848ec84ce --- /dev/null +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/tck/ErrorHandlingTests.java.todo @@ -0,0 +1,104 @@ +///* +// * Copyright 2019-2019 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 +// * +// * https://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.binder.tck; +// +//import org.junit.Test; +// +//import org.springframework.boot.WebApplicationType; +//import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +//import org.springframework.boot.builder.SpringApplicationBuilder; +//import org.springframework.cloud.stream.annotation.EnableBinding; +//import org.springframework.cloud.stream.annotation.StreamListener; +//import org.springframework.cloud.stream.binder.test.InputDestination; +//import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration; +//import org.springframework.cloud.stream.messaging.Processor; +//import org.springframework.context.ApplicationContext; +//import org.springframework.context.annotation.Import; +//import org.springframework.messaging.Message; +//import org.springframework.messaging.support.GenericMessage; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +///** +// * @author Oleg Zhurakousky +// * +// */ +//public class ErrorHandlingTests { +// +// @Test +// public void testGlobalErrorWithMessage() { +// ApplicationContext context = new SpringApplicationBuilder( +// GlobalErrorHandlerWithErrorMessageConfig.class) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// source.send(new GenericMessage<>("foo".getBytes())); +// GlobalErrorHandlerWithErrorMessageConfig config = context +// .getBean(GlobalErrorHandlerWithErrorMessageConfig.class); +// assertThat(config.globalErroInvoked).isTrue(); +// } +// +// @Test +// public void testGlobalErrorWithThrowable() { +// ApplicationContext context = new SpringApplicationBuilder( +// GlobalErrorHandlerWithThrowableConfig.class).web(WebApplicationType.NONE) +// .run("--spring.jmx.enabled=false"); +// InputDestination source = context.getBean(InputDestination.class); +// source.send(new GenericMessage<>("foo".getBytes())); +// GlobalErrorHandlerWithThrowableConfig config = context +// .getBean(GlobalErrorHandlerWithThrowableConfig.class); +// assertThat(config.globalErroInvoked).isTrue(); +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class GlobalErrorHandlerWithErrorMessageConfig { +// +// private boolean globalErroInvoked; +// +// @StreamListener(target = Processor.INPUT) +// public void input(final String value) { +// throw new RuntimeException("test exception"); +// } +// +// @StreamListener("errorChannel") +// public void generalError(Message message) { +// this.globalErroInvoked = true; +// } +// +// } +// +// @EnableBinding(Processor.class) +// @Import(TestChannelBinderConfiguration.class) +// @EnableAutoConfiguration +// public static class GlobalErrorHandlerWithThrowableConfig { +// +// private boolean globalErroInvoked; +// +// @StreamListener(target = Processor.INPUT) +// public void input(final String value) { +// throw new RuntimeException("test exception"); +// } +// +// @StreamListener("errorChannel") +// public void generalError(Throwable exception) { +// this.globalErroInvoked = true; +// } +// +// } +// +//} diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java deleted file mode 100644 index f6b0dfae3..000000000 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2017-2018 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 - * - * https://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.binder.test; - -import java.nio.charset.StandardCharsets; - -import org.springframework.boot.ApplicationRunner; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.Input; -import org.springframework.cloud.stream.annotation.StreamListener; -import org.springframework.cloud.stream.binder.PollableMessageSource; -import org.springframework.cloud.stream.messaging.Processor; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.integration.annotation.ServiceActivator; -import org.springframework.messaging.Message; -import org.springframework.messaging.handler.annotation.SendTo; -import org.springframework.messaging.support.GenericMessage; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Sample spring cloud stream application that demonstrates the usage of - * {@link TestChannelBinder}. - * - * @author Oleg Zhurakousky - * @author Gary Russell - * - */ -@SpringBootApplication -@EnableBinding(SampleStreamApp.PolledConsumer.class) -@Import(TestChannelBinderConfiguration.class) -public class SampleStreamApp { - - public static void main(String[] args) { - ApplicationContext context = new SpringApplicationBuilder(SampleStreamApp.class) - .web(WebApplicationType.NONE).run("--server.port=0"); - InputDestination source = context.getBean(InputDestination.class); - OutputDestination target = context.getBean(OutputDestination.class); - source.send(new GenericMessage("Hello".getBytes())); - - Message message = target.receive(); - assertThat(new String((byte[]) message.getPayload(), StandardCharsets.UTF_8)) - .isEqualTo("Hello"); - } - - @Bean - public ApplicationRunner runner(PollableMessageSource pollableSource) { - return args -> pollableSource.poll(message -> { - System.out.println("Polled payload: " + message.getPayload()); - }); - } - - @StreamListener(Processor.INPUT) - @SendTo(Processor.OUTPUT) - public String receive(String value) { - System.out.println("Handling payload: " + value); - return value; - } - - @ServiceActivator(inputChannel = "input.anonymous.errors") - public void error(String value) { - System.out.println("Handling ERROR payload: " + value); - } - - public interface PolledConsumer extends Processor { - - @Input - PollableMessageSource pollableSource(); - - } - -} diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java.todo b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java.todo new file mode 100644 index 000000000..0975cad92 --- /dev/null +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/binder/test/SampleStreamApp.java.todo @@ -0,0 +1,91 @@ +///* +// * Copyright 2017-2018 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 +// * +// * https://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.binder.test; +// +//import java.nio.charset.StandardCharsets; +// +//import org.springframework.boot.ApplicationRunner; +//import org.springframework.boot.WebApplicationType; +//import org.springframework.boot.autoconfigure.SpringBootApplication; +//import org.springframework.boot.builder.SpringApplicationBuilder; +//import org.springframework.cloud.stream.annotation.EnableBinding; +//import org.springframework.cloud.stream.annotation.Input; +//import org.springframework.cloud.stream.annotation.StreamListener; +//import org.springframework.cloud.stream.binder.PollableMessageSource; +//import org.springframework.cloud.stream.messaging.Processor; +//import org.springframework.context.ApplicationContext; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Import; +//import org.springframework.integration.annotation.ServiceActivator; +//import org.springframework.messaging.Message; +//import org.springframework.messaging.handler.annotation.SendTo; +//import org.springframework.messaging.support.GenericMessage; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +///** +// * Sample spring cloud stream application that demonstrates the usage of +// * {@link TestChannelBinder}. +// * +// * @author Oleg Zhurakousky +// * @author Gary Russell +// * +// */ +//@SpringBootApplication +//@EnableBinding(SampleStreamApp.PolledConsumer.class) +//@Import(TestChannelBinderConfiguration.class) +//public class SampleStreamApp { +// +// public static void main(String[] args) { +// ApplicationContext context = new SpringApplicationBuilder(SampleStreamApp.class) +// .web(WebApplicationType.NONE).run("--server.port=0"); +// InputDestination source = context.getBean(InputDestination.class); +// OutputDestination target = context.getBean(OutputDestination.class); +// source.send(new GenericMessage("Hello".getBytes())); +// +// Message message = target.receive(); +// assertThat(new String((byte[]) message.getPayload(), StandardCharsets.UTF_8)) +// .isEqualTo("Hello"); +// } +// +// @Bean +// public ApplicationRunner runner(PollableMessageSource pollableSource) { +// return args -> pollableSource.poll(message -> { +// System.out.println("Polled payload: " + message.getPayload()); +// }); +// } +// +// @StreamListener(Processor.INPUT) +// @SendTo(Processor.OUTPUT) +// public String receive(String value) { +// System.out.println("Handling payload: " + value); +// return value; +// } +// +// @ServiceActivator(inputChannel = "input.anonymous.errors") +// public void error(String value) { +// System.out.println("Handling ERROR payload: " + value); +// } +// +// public interface PolledConsumer extends Processor { +// +// @Input +// PollableMessageSource pollableSource(); +// +// } +// +//} diff --git a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/ImplicitFunctionBindingTests.java b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/ImplicitFunctionBindingTests.java index 523634436..7f225cc57 100644 --- a/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/ImplicitFunctionBindingTests.java +++ b/spring-cloud-stream/src/test/java/org/springframework/cloud/stream/function/ImplicitFunctionBindingTests.java @@ -45,8 +45,6 @@ import org.springframework.cloud.function.context.FunctionType; import org.springframework.cloud.function.context.catalog.FunctionAroundWrapper; import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper; import org.springframework.cloud.function.context.config.ContextFunctionCatalogAutoConfiguration; -import org.springframework.cloud.stream.annotation.EnableBinding; -import org.springframework.cloud.stream.annotation.StreamListener; import org.springframework.cloud.stream.binder.Binding; import org.springframework.cloud.stream.binder.BindingCreatedEvent; import org.springframework.cloud.stream.binder.test.FunctionBindingTestUtils; @@ -56,7 +54,6 @@ import org.springframework.cloud.stream.binder.test.TestChannelBinderConfigurati import org.springframework.cloud.stream.binding.BindingsLifecycleController; import org.springframework.cloud.stream.binding.BindingsLifecycleController.State; import org.springframework.cloud.stream.messaging.DirectWithAttributesChannel; -import org.springframework.cloud.stream.messaging.Sink; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -466,16 +463,16 @@ public class ImplicitFunctionBindingTests { } } - @Test - public void testFunctionConfigDisabledIfStreamListenerIsUsed() { - System.clearProperty("spring.cloud.function.definition"); - try (ConfigurableApplicationContext context = new SpringApplicationBuilder( - TestChannelBinderConfiguration.getCompleteConfiguration(LegacyConfiguration.class)) - .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false")) { - - assertThat(context.getBean("supplierInitializer").getClass().getSimpleName()).isEqualTo("NullBean"); - } - } +// @Test +// public void testFunctionConfigDisabledIfStreamListenerIsUsed() { +// System.clearProperty("spring.cloud.function.definition"); +// try (ConfigurableApplicationContext context = new SpringApplicationBuilder( +// TestChannelBinderConfiguration.getCompleteConfiguration(LegacyConfiguration.class)) +// .web(WebApplicationType.NONE).run("--spring.jmx.enabled=false")) { +// +// assertThat(context.getBean("supplierInitializer").getClass().getSimpleName()).isEqualTo("NullBean"); +// } +// } @Test public void testDeclaredTypeVsActualInstance() { @@ -1340,16 +1337,6 @@ public class ImplicitFunctionBindingTests { } } - @EnableAutoConfiguration - @EnableBinding(Sink.class) - public static class LegacyConfiguration { - - @StreamListener(Sink.INPUT) - public void handle(String value) { - - } - } - @EnableAutoConfiguration public static class EmptyConfiguration {