From 996e6bb96916857654e4907eb069886167e76a10 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Tue, 12 Jan 2016 12:16:33 -0500 Subject: [PATCH] INT-3910: MessageProducerSupport.outputChannelName JIRA: https://jira.spring.io/browse/INT-3910 - Support channel name on `MessageProducerSupport`. - Defer validation until the endpoint is `start()`ed. --- .../endpoint/MessageProducerSupport.java | 28 +++++++++++++++---- .../endpoint/MessageProducerSupportTests.java | 19 ++++++++++++- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java index efb79f5c49..70ed970656 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -25,6 +25,7 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.ErrorMessage; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * A support class for producer endpoints that provides a setter for the @@ -36,14 +37,16 @@ import org.springframework.util.Assert; */ public abstract class MessageProducerSupport extends AbstractEndpoint implements MessageProducer, TrackableComponent { + private final MessagingTemplate messagingTemplate = new MessagingTemplate(); + private volatile MessageChannel outputChannel; + private volatile String outputChannelName; + private volatile MessageChannel errorChannel; private volatile boolean shouldTrack = false; - private final MessagingTemplate messagingTemplate = new MessagingTemplate(); - protected MessageProducerSupport() { this.setPhase(Integer.MAX_VALUE / 2); } @@ -53,6 +56,17 @@ public abstract class MessageProducerSupport extends AbstractEndpoint implements this.outputChannel = outputChannel; } + /** + * Set the output channel name; overrides + * {@link #setOutputChannel(MessageChannel) outputChannel} if provided. + * @param outputChannelName the channel name. + * @since 4.3 + */ + public void setOutputChannelName(String outputChannelName) { + Assert.hasText(outputChannelName, "'outputChannelName' must not be null or empty"); + this.outputChannelName = outputChannelName; + } + public void setErrorChannel(MessageChannel errorChannel) { this.errorChannel = errorChannel; } @@ -72,7 +86,6 @@ public abstract class MessageProducerSupport extends AbstractEndpoint implements @Override protected void onInit() { - Assert.notNull(this.outputChannel, "outputChannel is required"); if (this.getBeanFactory() != null) { this.messagingTemplate.setBeanFactory(this.getBeanFactory()); } @@ -80,10 +93,15 @@ public abstract class MessageProducerSupport extends AbstractEndpoint implements /** * Takes no action by default. Subclasses may override this if they - * need lifecycle-managed behavior. + * need lifecycle-managed behavior. Protected by 'lifecycleLock'. */ @Override protected void doStart() { + Assert.state(this.outputChannel != null || StringUtils.hasText(this.outputChannelName), + "'outputChannel' or 'outputChannelName' is required"); + if (this.outputChannelName != null) { + this.outputChannel = getChannelResolver().resolveDestination(this.outputChannelName); + } } /** diff --git a/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java b/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java index 8443c167b5..f6500030a5 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/endpoint/MessageProducerSupportTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package org.springframework.integration.endpoint; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -25,11 +26,13 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; + import org.springframework.beans.factory.BeanFactory; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.PublishSubscribeChannel; import org.springframework.integration.handler.ServiceActivatingHandler; import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.test.util.TestUtils.TestApplicationContext; import org.springframework.messaging.Message; import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.MessageHandler; @@ -119,6 +122,20 @@ public class MessageProducerSupportTests { assertEquals(message, exception.getFailedMessage()); } + @Test + public void testWithChannelName() { + DirectChannel outChannel = new DirectChannel(); + MessageProducerSupport mps = new MessageProducerSupport() {}; + mps.setOutputChannelName("foo"); + TestApplicationContext testApplicationContext = TestUtils.createTestApplicationContext(); + testApplicationContext.registerBean("foo", outChannel); + testApplicationContext.refresh(); + mps.setBeanFactory(testApplicationContext); + mps.afterPropertiesSet(); + mps.start(); + assertSame(outChannel, TestUtils.getPropertyValue(mps, "outputChannel")); + } + @Test public void customDoStop() { final CustomEndpoint endpoint = new CustomEndpoint();