Avoid eager creation of bound target beans

- At StreamListenerBeanPostProcessor, avoid eager creation of inbound/outbound target beans whenever possible
  - Use `applicationContext.getType(targetName)` instead of `applicationContext.getBean(targetName)` which checks the type of target beans from bean factory instead of creating the bean eagerly.
  - For declarative method invocation, `applicationContext.getBean` is needed as it requires the actual bean as its argument

Resolves #767

Update the test

 - ignore bean definition not found exception when the bean definition doesn't exist
This commit is contained in:
Ilayaperumal Gopinathan
2017-03-22 15:46:07 +05:30
committed by Marius Bogoevici
parent d250022250
commit ba18c01602
3 changed files with 71 additions and 21 deletions

View File

@@ -30,10 +30,14 @@ 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;
@@ -84,7 +88,22 @@ public class StreamListenerHandlerMethodTests {
MessageCollector messageCollector = context.getBean(MessageCollector.class);
Message<?> result = messageCollector.forChannel(processor.output()).poll(1000, TimeUnit.MILLISECONDS);
assertThat(result).isNotNull();
assertThat(result.getPayload()).isEqualTo(result.getPayload().toString().toUpperCase());
assertThat(result.getPayload()).isEqualTo(testMessage.toUpperCase());
context.close();
}
@Test
public void testStreamListenerMethodWithTargetBeanFromOutside() throws Exception {
ConfigurableApplicationContext context = SpringApplication.run(TestStreamListenerMethodWithTargetBeanFromOutside.class, "--server.port=0");
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 = 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();
}
@@ -139,8 +158,8 @@ public class StreamListenerHandlerMethodTests {
fail("Exception expected on using invalid inbound name");
}
catch (BeanCreationException e) {
assertThat(e.getCause()).isInstanceOf(NoSuchBeanDefinitionException.class);
assertThat(e.getCause()).hasMessageContaining("'invalid'");
assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
assertThat(e.getCause()).hasMessageContaining(StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS);
}
}
@@ -303,6 +322,24 @@ public class StreamListenerHandlerMethodTests {
}
}
@EnableBinding(Sink.class)
@EnableAutoConfiguration
public static class TestStreamListenerMethodWithTargetBeanFromOutside {
private static final String ROUTER_QUEUE = "routeInstruction";
@StreamListener(Sink.INPUT)
@SendTo(ROUTER_QUEUE)
public Message<String> convertMessageBody(Message<String> 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 {

View File

@@ -20,13 +20,14 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
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.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;
@@ -57,9 +58,9 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
public void testInputOutputArgsWithMoreParameters() {
try {
SpringApplication.run(TestInputOutputArgsWithMoreParameters.class, "--server.port=0");
fail("Expected exception: "+ INVALID_DECLARATIVE_METHOD_PARAMETERS);
fail("Expected exception: " + INVALID_DECLARATIVE_METHOD_PARAMETERS);
}
catch (Exception e) {
catch (BeanCreationException e) {
assertThat(e.getMessage()).contains(INVALID_DECLARATIVE_METHOD_PARAMETERS);
}
}
@@ -70,9 +71,9 @@ public class StreamListenerWithAnnotatedInputOutputArgsTests {
SpringApplication.run(TestInputOutputArgsWithInvalidBindableTarget.class, "--server.port=0");
fail("Exception expected on using invalid bindable target as method parameter");
}
catch (Exception e) {
assertThat(e.getCause()).isInstanceOf(NoSuchBeanDefinitionException.class);
assertThat(e.getCause()).hasMessageContaining("'invalid'");
catch (BeanCreationException e) {
assertThat(e.getCause()).isInstanceOf(IllegalArgumentException.class);
assertThat(e.getCause()).hasMessageContaining(StreamListenerErrorMessages.INVALID_DECLARATIVE_METHOD_PARAMETERS);
}
}