diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java index 200d018f15..eb2e0b37c6 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aggregator/AbstractCorrelatingMessageHandler.java @@ -57,7 +57,6 @@ import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.scheduling.TaskScheduler; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; /** * Abstract Message handler that holds a buffer of correlated messages in a @@ -187,6 +186,7 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH } public void setOutputChannelName(String outputChannelName) { + Assert.hasText(outputChannelName, "'outputChannelName' must not be empty"); this.outputChannelName = outputChannelName; } @@ -215,27 +215,11 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH BeanFactory beanFactory = this.getBeanFactory(); if (beanFactory != null) { this.messagingTemplate.setBeanFactory(beanFactory); - if (StringUtils.hasText(this.discardChannelName)) { - Assert.isNull(this.discardChannel, "'outputChannelName' and 'discardChannel' are mutually exclusive."); - try { - this.discardChannel = beanFactory.getBean(this.discardChannelName, MessageChannel.class); - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.discardChannelName + "' in the BeanFactory."); - } - } + Assert.state(!(this.discardChannelName != null && this.discardChannel != null), + "'discardChannelName' and 'discardChannel' are mutually exclusive."); - if (StringUtils.hasText(this.outputChannelName)) { - Assert.isNull(this.outputChannel, "'outputChannelName' and 'outputChannel' are mutually exclusive."); - try { - this.outputChannel = this.getBeanFactory().getBean(this.outputChannelName, MessageChannel.class); - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.outputChannelName + "' in the BeanFactory."); - } - } + Assert.state(!(this.outputChannelName != null && this.outputChannel != null), + "'outputChannelName' and 'outputChannel' are mutually exclusive."); if (this.outputProcessor instanceof BeanFactoryAware) { ((BeanFactoryAware) this.outputProcessor).setBeanFactory(beanFactory); @@ -272,6 +256,7 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH } public void setDiscardChannelName(String discardChannelName) { + Assert.hasText(discardChannelName, "'discardChannelName' must not be empty"); this.discardChannelName = discardChannelName; } @@ -291,7 +276,6 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH * schedule than expiring partial groups, set this property. Empty groups will * then not be removed from the MessageStore until they have not been modified * for at least this number of milliseconds. - * * @param minimumTimeoutForEmptyGroups The minimum timeout. */ public void setMinimumTimeoutForEmptyGroups(long minimumTimeoutForEmptyGroups) { @@ -461,7 +445,7 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH } } else { - discardChannel.send(message); + discardMessage(message); } } finally { @@ -469,6 +453,24 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH } } + private void discardMessage(Message message) { + if (this.discardChannelName != null) { + synchronized (this) { + if (this.discardChannelName != null) { + try { + this.discardChannel = getBeanFactory().getBean(this.discardChannelName, MessageChannel.class); + this.discardChannelName = null; + } + catch (BeansException e) { + throw new DestinationResolutionException("Failed to look up MessageChannel with name '" + + this.discardChannelName + "' in the BeanFactory."); + } + } + } + } + this.discardChannel.send(message); + } + /** * Allows you to provide additional logic that needs to be performed after the MessageGroup was released. * @param group The group. @@ -591,17 +593,19 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH if (sendPartialResultOnExpiry) { if (logger.isDebugEnabled()) { logger.debug("Prematurely releasing partially complete group with key [" - + correlationKey + "] to: " + outputChannel); + + correlationKey + "] to: " + + (this.outputChannelName != null ? this.outputChannelName : this.outputChannel)); } completeGroup(correlationKey, group); } else { if (logger.isDebugEnabled()) { logger.debug("Discarding messages of partially complete group with key [" - + correlationKey + "] to: " + discardChannel); + + correlationKey + "] to: " + + (this.discardChannelName != null ? this.discardChannelName : this.discardChannel)); } for (Message message : group.getMessages()) { - discardChannel.send(message); + discardMessage(message); } } if (this.applicationEventPublisher != null) { @@ -645,6 +649,22 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH if (message != null) { replyChannelHeader = message.getHeaders().getReplyChannel(); } + + if (this.outputChannelName != null) { + synchronized (this) { + if (this.outputChannelName != null) { + try { + this.outputChannel = getBeanFactory().getBean(this.outputChannelName, MessageChannel.class); + this.outputChannelName = null; + } + catch (BeansException e) { + throw new DestinationResolutionException("Failed to look up MessageChannel with name '" + + this.outputChannelName + "' in the BeanFactory."); + } + } + } + } + Object replyChannel = this.outputChannel; if (this.outputChannel == null) { replyChannel = replyChannelHeader; @@ -718,12 +738,8 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH Integer messageSequenceNumber = messageHeaderAccessor.getSequenceNumber(); if (messageSequenceNumber != null && messageSequenceNumber > 0) { Integer messageSequenceSize = messageHeaderAccessor.getSequenceSize(); - if (!messageSequenceSize.equals(this.getSequenceSize())) { - return false; - } - else { - return !this.containsSequenceNumber(this.getMessages(), messageSequenceNumber); - } + return messageSequenceSize.equals(this.getSequenceSize()) + && !this.containsSequenceNumber(this.getMessages(), messageSequenceNumber); } return true; } @@ -738,4 +754,5 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH return false; } } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/annotation/Filter.java b/spring-integration-core/src/main/java/org/springframework/integration/annotation/Filter.java index c4c6cc3ab1..524c66015c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/annotation/Filter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/annotation/Filter.java @@ -54,7 +54,7 @@ public @interface Filter { String[] adviceChain() default {}; - boolean discardWithinAdvice() default true; + String discardWithinAdvice() default "true"; /* {@code SmartLifecycle} options. diff --git a/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java index 7399cdcc65..5c0afe0aa9 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java @@ -70,6 +70,7 @@ public class PublisherAnnotationBeanPostProcessor extends ProxyConfig /** * Set the default channel where Messages should be sent if the annotation * itself does not provide a channel. + * @param defaultChannelName the publisher interceptor defaultChannel * @since 4.0.3 */ public void setDefaultChannelName(String defaultChannelName) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java index 271e807ccb..67d4716231 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java @@ -319,7 +319,7 @@ public abstract class AbstractMethodAnnotationPostProcessor annotations, AbstractReplyProducingMessageHandler handler) { String outputChannelName = MessagingAnnotationUtils.resolveAttribute(annotations, "outputChannel", String.class); if (StringUtils.hasText(outputChannelName)) { - handler.setOutputChannel(this.channelResolver.resolveDestination(outputChannelName)); + handler.setOutputChannelName(outputChannelName); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AggregatorAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AggregatorAnnotationPostProcessor.java index fefdbf2a2c..f157c4d62f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AggregatorAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/AggregatorAnnotationPostProcessor.java @@ -30,9 +30,7 @@ import org.springframework.integration.annotation.Aggregator; import org.springframework.integration.annotation.CorrelationStrategy; import org.springframework.integration.annotation.ReleaseStrategy; import org.springframework.integration.store.SimpleMessageStore; -import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; -import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -72,13 +70,11 @@ public class AggregatorAnnotationPostProcessor extends AbstractMethodAnnotationP String discardChannelName = MessagingAnnotationUtils.resolveAttribute(annotations, "discardChannel", String.class); if (StringUtils.hasText(discardChannelName)) { - MessageChannel discardChannel = this.channelResolver.resolveDestination(discardChannelName); - Assert.notNull(discardChannel, "failed to resolve discardChannel '" + discardChannelName + "'"); - handler.setDiscardChannel(discardChannel); + handler.setDiscardChannelName(discardChannelName); } String outputChannelName = MessagingAnnotationUtils.resolveAttribute(annotations, "outputChannel", String.class); if (StringUtils.hasText(outputChannelName)) { - handler.setOutputChannel(this.channelResolver.resolveDestination(outputChannelName)); + handler.setOutputChannelName(outputChannelName); } Long sendTimeout = MessagingAnnotationUtils.resolveAttribute(annotations, "sendTimeout", Long.class); if (sendTimeout != null) { @@ -90,7 +86,6 @@ public class AggregatorAnnotationPostProcessor extends AbstractMethodAnnotationP handler.setSendPartialResultOnExpiry(sendPartialResultsOnExpiry); } handler.setBeanFactory(this.beanFactory); - handler.afterPropertiesSet(); return handler; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/BridgeToAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/BridgeToAnnotationPostProcessor.java index 898381e4b9..af4e71a50e 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/BridgeToAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/BridgeToAnnotationPostProcessor.java @@ -31,6 +31,7 @@ import org.springframework.integration.handler.BridgeHandler; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Post-processor for the {@link BridgeTo @BridgeTo} annotation. @@ -64,7 +65,9 @@ public class BridgeToAnnotationPostProcessor extends AbstractMethodAnnotationPos protected MessageHandler createHandler(Object bean, Method method, List annotations) { BridgeHandler handler = new BridgeHandler(); String outputChannelName = MessagingAnnotationUtils.resolveAttribute(annotations, "value", String.class); - handler.setOutputChannelName(outputChannelName); + if (StringUtils.hasText(outputChannelName)) { + handler.setOutputChannelName(outputChannelName); + } return handler; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessor.java index d039a9ac9d..8c6fded2c4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessor.java @@ -70,28 +70,29 @@ public class FilterAnnotationPostProcessor extends AbstractMethodAnnotationPostP MessageFilter filter = new MessageFilter(selector); - /* TODO will be revised in the future String discardWithinAdvice = MessagingAnnotationUtils.resolveAttribute(annotations, "discardWithinAdvice", String.class); if (StringUtils.hasText(discardWithinAdvice)) { - String discardWithinAdviceValue = this.environment.resolvePlaceholders(discardWithinAdvice); - if (StringUtils.hasText(discardWithinAdviceValue)) { - filter.setDiscardWithinAdvice(Boolean.parseBoolean(discardWithinAdviceValue)); + discardWithinAdvice = this.environment.resolvePlaceholders(discardWithinAdvice); + if (StringUtils.hasText(discardWithinAdvice)) { + filter.setDiscardWithinAdvice(Boolean.parseBoolean(discardWithinAdvice)); } - }*/ + } - filter.setDiscardWithinAdvice(MessagingAnnotationUtils.resolveAttribute(annotations, "discardWithinAdvice", - Boolean.class)); String throwExceptionOnRejection = MessagingAnnotationUtils.resolveAttribute(annotations, "throwExceptionOnRejection", String.class); if (StringUtils.hasText(throwExceptionOnRejection)) { String throwExceptionOnRejectionValue = this.environment.resolvePlaceholders(throwExceptionOnRejection); - filter.setThrowExceptionOnRejection(Boolean.parseBoolean(throwExceptionOnRejectionValue)); + if (StringUtils.hasText(throwExceptionOnRejectionValue)) { + filter.setThrowExceptionOnRejection(Boolean.parseBoolean(throwExceptionOnRejectionValue)); + } } String discardChannelName = MessagingAnnotationUtils.resolveAttribute(annotations, "discardChannel", String.class); - filter.setDiscardChannelName(discardChannelName); + if (StringUtils.hasText(discardChannelName)) { + filter.setDiscardChannelName(discardChannelName); + } this.setOutputChannelIfPresent(annotations, filter); return filter; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/RouterAnnotationPostProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/RouterAnnotationPostProcessor.java index 4a962bb35b..4cdfc3eec8 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/RouterAnnotationPostProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/annotation/RouterAnnotationPostProcessor.java @@ -75,7 +75,9 @@ public class RouterAnnotationPostProcessor extends AbstractMethodAnnotationPostP } String defaultOutputChannelName = MessagingAnnotationUtils.resolveAttribute(annotations, "defaultOutputChannel", String.class); - router.setDefaultOutputChannelName(defaultOutputChannelName); + if (StringUtils.hasText(defaultOutputChannelName)) { + router.setDefaultOutputChannelName(defaultOutputChannelName); + } String applySequence = MessagingAnnotationUtils.resolveAttribute(annotations, "applySequence", String.class); if (StringUtils.hasText(applySequence)) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/filter/MessageFilter.java b/spring-integration-core/src/main/java/org/springframework/integration/filter/MessageFilter.java index 70be1124c4..060ec3a9db 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/filter/MessageFilter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/filter/MessageFilter.java @@ -25,7 +25,6 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** * Message Handler that delegates to a {@link MessageSelector}. If and only if @@ -52,9 +51,7 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa private volatile String discardChannelName; /** - * Create a MessageFilter that will delegate to the given - * {@link MessageSelector}. - * + * Create a MessageFilter that will delegate to the given {@link MessageSelector}. * @param selector The message selector. */ public MessageFilter(MessageSelector selector) { @@ -72,9 +69,8 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa * a discard channel is provided, but if so, it will still apply * (in such a case, the Message will be sent to the discard channel, * and then the exception will be thrown). - * @see #setDiscardChannel(MessageChannel) - * * @param throwExceptionOnRejection true if an exception should be thrown. + * @see #setDiscardChannel(MessageChannel) */ public void setThrowExceptionOnRejection(boolean throwExceptionOnRejection) { this.throwExceptionOnRejection = throwExceptionOnRejection; @@ -86,9 +82,7 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa * the 'throwExceptionOnRejection' flag determines whether rejected Messages * trigger an exception. That value is evaluated regardless of the presence * of a discard channel. - * * @param discardChannel The discard channel. - * * @see #setThrowExceptionOnRejection(boolean) */ public void setDiscardChannel(MessageChannel discardChannel) { @@ -96,6 +90,7 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa } public void setDiscardChannelName(String discardChannelName) { + Assert.hasText(discardChannelName, "'discardChannelName' must not be empty"); this.discardChannelName = discardChannelName; } @@ -103,7 +98,6 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa * Set to 'true' if you wish the discard processing to occur within any * request handler advice applied to this filter. Also applies to * throwing an exception on rejection. Default: true. - * * @param discardWithinAdvice true to discard within the advice. */ public void setDiscardWithinAdvice(boolean discardWithinAdvice) { @@ -117,16 +111,8 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa @Override protected void doInit() { - if (StringUtils.hasText(this.discardChannelName)) { - Assert.isNull(this.discardChannel, "'outputChannelName' and 'discardChannel' are mutually exclusive."); - try { - this.discardChannel = this.getBeanFactory().getBean(this.discardChannelName, MessageChannel.class); - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.discardChannelName + "' in the BeanFactory."); - } - } + Assert.state(!(this.discardChannelName != null && this.discardChannel != null), + "'discardChannelName' and 'discardChannel' are mutually exclusive."); if (this.selector instanceof AbstractMessageProcessingSelector) { ((AbstractMessageProcessingSelector) this.selector).setConversionService(this.getConversionService()); } @@ -148,11 +134,27 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa @Override public Object postProcess(Message message, Object result) { if (result == null) { + if (this.discardChannelName != null) { + synchronized (this) { + if (this.discardChannelName != null) { + try { + this.discardChannel = this.getBeanFactory() + .getBean(this.discardChannelName, MessageChannel.class); + this.discardChannelName = null; + } + catch (BeansException e) { + throw new DestinationResolutionException("Failed to look up MessageChannel with name '" + + this.discardChannelName + "' in the BeanFactory."); + } + } + } + } if (this.discardChannel != null) { this.getMessagingTemplate().send(this.discardChannel, message); } if (this.throwExceptionOnRejection) { - throw new MessageRejectedException(message, "MessageFilter '" + this.getComponentName() + "' rejected Message"); + throw new MessageRejectedException(message, "MessageFilter '" + this.getComponentName() + + "' rejected Message"); } } return result; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java index dc37a28ac4..97f99ff447 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractReplyProducingMessageHandler.java @@ -35,7 +35,6 @@ import org.springframework.messaging.core.DestinationResolver; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; /** * Base class for MessageHandlers that are capable of producing replies. @@ -44,6 +43,7 @@ import org.springframework.util.StringUtils; * @author Iwein Fuld * @author Oleg Zhurakousky * @author Gary Russell + * @author Artem Bilan */ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessageHandler implements MessageProducer, BeanClassLoaderAware { @@ -75,12 +75,12 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa } public void setOutputChannelName(String outputChannelName) { + Assert.hasText(outputChannelName, "'outputChannelName' must not be empty"); this.outputChannelName = outputChannelName; } /** * Set the timeout for sending reply Messages. - * * @param sendTimeout The send timeout. */ public void setSendTimeout(long sendTimeout) { @@ -89,7 +89,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa /** * Set the DestinationResolver<MessageChannel> to be used when there is no default output channel. - * * @param channelResolver The channel resolver. */ public void setChannelResolver(DestinationResolver channelResolver) { @@ -100,7 +99,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa /** * Flag whether a reply is required. If true an incoming message MUST result in a reply message being sent. * If false an incoming message MAY result in a reply message being sent. Default is false. - * * @param requiresReply true if a reply is required. */ public void setRequiresReply(boolean requiresReply) { @@ -109,7 +107,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa /** * Provides access to the {@link MessagingTemplate} for subclasses. - * * @return The messaging template. */ protected MessagingTemplate getMessagingTemplate() { @@ -134,18 +131,10 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa @Override protected final void onInit() { + Assert.state(!(this.outputChannelName != null && this.outputChannel != null), + "'outputChannelName' and 'outputChannel' are mutually exclusive."); if (this.getBeanFactory() != null) { this.messagingTemplate.setBeanFactory(getBeanFactory()); - if (StringUtils.hasText(this.outputChannelName)) { - Assert.isNull(this.outputChannel, "'outputChannelName' and 'outputChannel' are mutually exclusive."); - try { - this.outputChannel = this.getBeanFactory().getBean(this.outputChannelName, MessageChannel.class); - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.outputChannelName + "' in the BeanFactory."); - } - } } if (!CollectionUtils.isEmpty(this.adviceChain)) { ProxyFactory proxyFactory = new ProxyFactory(new AdvisedRequestHandler()); @@ -229,7 +218,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa * Send a reply Message. The 'replyChannelHeaderValue' will be considered only if this handler's * 'outputChannel' is null. In that case, the header value must not also be * null, and it must be an instance of either String or {@link MessageChannel}. - * * @param replyMessage the reply Message to send * @param replyChannelHeaderValue the 'replyChannel' header value from the original request */ @@ -237,6 +225,22 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa if (logger.isDebugEnabled()) { logger.debug("handler '" + this + "' sending reply Message: " + replyMessage); } + + if (this.outputChannelName != null) { + synchronized (this) { + if (this.outputChannelName != null) { + try { + this.outputChannel = this.getBeanFactory().getBean(this.outputChannelName, MessageChannel.class); + this.outputChannelName = null; + } + catch (BeansException e) { + throw new DestinationResolutionException("Failed to look up MessageChannel with name '" + + this.outputChannelName + "' in the BeanFactory."); + } + } + } + } + if (this.outputChannel != null) { this.sendMessage(replyMessage, this.outputChannel); } @@ -251,7 +255,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa /** * Send the message to the given channel. The channel must be a String or * {@link MessageChannel} instance, never null. - * * @param message The message. * @param channel The channel to which to send the message. */ @@ -279,7 +282,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa /** * Subclasses may override this. True by default. - * * @return true if the request headers should be copied. */ protected boolean shouldCopyRequestHeaders() { @@ -291,7 +293,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa * value may be a Message, a MessageBuilder, or any plain Object. The base class * will handle the final creation of a reply Message from any of those starting * points. If the return value is null, the Message flow will end here. - * * @param requestMessage The request message. * @return The result of handling the message, or {@code null}. */ @@ -318,7 +319,6 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa return AbstractReplyProducingMessageHandler.this.toString(); } - } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageRouter.java index 88775122db..daff80fe29 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageRouter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageRouter.java @@ -31,7 +31,6 @@ import org.springframework.messaging.MessageDeliveryException; import org.springframework.messaging.MessagingException; import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** * Base class for all Message Routers. @@ -62,9 +61,8 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { * fails to return any channels. If no default channel is provided and channel * resolution fails to return any channels, the router will throw an * {@link MessageDeliveryException}. - * + *

* If messages shall be ignored (dropped) instead, please provide a {@link NullChannel}. - * * @param defaultOutputChannel The default output channel. */ public void setDefaultOutputChannel(MessageChannel defaultOutputChannel) { @@ -72,13 +70,13 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { } public void setDefaultOutputChannelName(String defaultOutputChannelName) { + Assert.hasText(defaultOutputChannelName, "'defaultOutputChannelName' must not be empty"); this.defaultOutputChannelName = defaultOutputChannelName; } /** * Set the timeout for sending a message to the resolved channel. By default, there is no timeout, meaning the send * will block indefinitely. - * * @param timeout The timeout. */ public void setTimeout(long timeout) { @@ -89,7 +87,6 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { * Specify whether send failures for one or more of the recipients should be ignored. By default this is * false meaning that an Exception will be thrown whenever a send fails. To override this and suppress * Exceptions, set the value to true. - * * @param ignoreSendFailures true to ignore send failures. */ public void setIgnoreSendFailures(boolean ignoreSendFailures) { @@ -101,7 +98,6 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { * channels. By default, this value is false meaning that sequence headers will not be * applied. If planning to use an Aggregator downstream with the default correlation and completion strategies, you * should set this flag to true. - * * @param applySequence true to apply sequence information. */ public void setApplySequence(boolean applySequence) { @@ -115,7 +111,6 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { /** * Provides {@link MessagingTemplate} access for subclasses - * * @return The messaging template. */ protected MessagingTemplate getMessagingTemplate() { @@ -136,25 +131,16 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { @Override protected void onInit() throws Exception { super.onInit(); + Assert.state(!(this.defaultOutputChannelName != null && this.defaultOutputChannel != null), + "'defaultOutputChannelName' and 'defaultOutputChannel' are mutually exclusive."); if (this.getBeanFactory() != null) { this.messagingTemplate.setBeanFactory(this.getBeanFactory()); - if (StringUtils.hasText(this.defaultOutputChannelName)) { - Assert.isNull(this.defaultOutputChannel, "'defaultOutputChannelName' and 'defaultOutputChannel' are mutually exclusive."); - try { - this.defaultOutputChannel = this.getBeanFactory().getBean(this.defaultOutputChannelName, MessageChannel.class); - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.defaultOutputChannelName + "' in the BeanFactory."); - } - } } } /** * Subclasses must implement this method to return a Collection of zero or more * MessageChannels to which the given Message should be routed. - * * @param message The message. * @return The collection of message channels. */ @@ -168,8 +154,11 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { int sequenceSize = results.size(); int sequenceNumber = 1; for (MessageChannel channel : results) { - final Message messageToSend = (!this.applySequence) ? message : this.getMessageBuilderFactory().fromMessage(message) - .pushSequenceDetails(message.getHeaders().getId(), sequenceNumber++, sequenceSize).build(); + final Message messageToSend = + !this.applySequence ? message : (this.getMessageBuilderFactory() + .fromMessage(message) + .pushSequenceDetails(message.getHeaders().getId(), sequenceNumber++, sequenceSize) + .build()); if (channel != null) { try { this.messagingTemplate.send(channel, messageToSend); @@ -187,6 +176,21 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { } } if (!sent) { + if (this.defaultOutputChannelName != null) { + synchronized (this) { + if (this.defaultOutputChannelName != null) { + try { + this.defaultOutputChannel = getBeanFactory() + .getBean(this.defaultOutputChannelName, MessageChannel.class); + this.defaultOutputChannelName = null; + } + catch (BeansException e) { + throw new DestinationResolutionException("Failed to look up MessageChannel with name '" + + this.defaultOutputChannelName + "' in the BeanFactory."); + } + } + } + } if (this.defaultOutputChannel != null) { this.messagingTemplate.send(this.defaultOutputChannel, message); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java index 5e4090effb..946d477aa4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transformer/ContentEnricher.java @@ -198,7 +198,6 @@ public class ContentEnricher extends AbstractReplyProducingMessageHandler * object. *

* For instance the following SpEL expressions (among others) are possible: - *

*

    *
  • payload.foo
  • *
  • headers.foobar
  • diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/AggregatorAnnotationTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/AggregatorAnnotationTests.java index 14ea5a95f0..b482fd6f55 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/AggregatorAnnotationTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/AggregatorAnnotationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -37,11 +37,8 @@ import org.springframework.integration.aggregator.MethodInvokingReleaseStrategy; import org.springframework.integration.aggregator.SequenceSizeReleaseStrategy; import org.springframework.integration.channel.NullChannel; import org.springframework.integration.endpoint.EventDrivenConsumer; -import org.springframework.integration.support.channel.BeanFactoryChannelResolver; import org.springframework.integration.test.util.TestUtils; -import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; -import org.springframework.messaging.core.DestinationResolver; /** * @author Marius Bogoevici @@ -71,10 +68,8 @@ public class AggregatorAnnotationTests { final String endpointName = "endpointWithCustomizedAnnotation"; MessageHandler aggregator = this.getAggregator(context, endpointName); assertTrue(getPropertyValue(aggregator, "releaseStrategy") instanceof SequenceSizeReleaseStrategy); - DestinationResolver channelResolver = new BeanFactoryChannelResolver(context); - assertEquals(channelResolver.resolveDestination("outputChannel"), getPropertyValue(aggregator, "outputChannel")); - assertEquals(channelResolver.resolveDestination("discardChannel"), getPropertyValue(aggregator, - "discardChannel")); + assertEquals("outputChannel", getPropertyValue(aggregator, "outputChannelName")); + assertEquals("discardChannel", getPropertyValue(aggregator, "discardChannelName")); assertEquals(98765432l, getPropertyValue(aggregator, "messagingTemplate.sendTimeout")); assertEquals(true, getPropertyValue(aggregator, "sendPartialResultOnExpiry")); } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessorTests.java index 88053c0941..7fad4cba82 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessorTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/annotation/FilterAnnotationPostProcessorTests.java @@ -198,7 +198,7 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithBooleanPrimitive { - @Filter(inputChannel="input", outputChannel="output") + @Filter(inputChannel = "input", outputChannel = "output") public boolean filter(String s) { return !s.contains("bad"); } @@ -207,7 +207,7 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithAdviceDiscardWithin { - @Filter(inputChannel="input", outputChannel="output", adviceChain="adviceChain") + @Filter(inputChannel = "input", outputChannel = "output", adviceChain = "adviceChain") public boolean filter(String s) { return !s.contains("bad"); } @@ -216,7 +216,7 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithAdviceDiscardWithinTwice { - @Filter(inputChannel="input", outputChannel="output", adviceChain={"adviceChain1", "adviceChain2"}) + @Filter(inputChannel = "input", outputChannel = "output", adviceChain = {"adviceChain1", "adviceChain2"}) public boolean filter(String s) { return !s.contains("bad"); } @@ -225,8 +225,8 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithAdviceDiscardWithout { - @Filter(inputChannel="input", outputChannel="output", - adviceChain="adviceChain", discardWithinAdvice=false) + @Filter(inputChannel = "input", outputChannel = "output", + adviceChain = "adviceChain", discardWithinAdvice = "false") public boolean filter(String s) { return !s.contains("bad"); } @@ -235,7 +235,7 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithBooleanWrapperClass { - @Filter(inputChannel="input", outputChannel="output") + @Filter(inputChannel = "input", outputChannel = "output") public Boolean filter(String s) { return !s.contains("bad"); } @@ -245,7 +245,7 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithStringReturnType { - @Filter(inputChannel="input", outputChannel="output") + @Filter(inputChannel = "input", outputChannel = "output") public String filter(String s) { return s; } @@ -255,7 +255,7 @@ public class FilterAnnotationPostProcessorTests { @MessageEndpoint private static class TestFilterWithVoidReturnType { - @Filter(inputChannel="input", outputChannel="output") + @Filter(inputChannel = "input", outputChannel = "output") public void filter(String s) { } } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests4-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests4-context.xml index e26bf16362..d21ac1587b 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests4-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/EnricherParserTests4-context.xml @@ -26,7 +26,7 @@ diff --git a/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java b/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java index c522e65c05..7a3c8af121 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/configuration/EnableIntegrationTests.java @@ -17,7 +17,15 @@ package org.springframework.integration.configuration; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import java.lang.annotation.ElementType; @@ -402,19 +410,19 @@ public class EnableIntegrationTests { assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class)); assertEquals(23, TestUtils.getPropertyValue(consumer, "phase")); assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName")); assertSame(context.getBean("annAdvice"), TestUtils.getPropertyValue(consumer, "handler.adviceChain", List.class).get(0)); assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period")); consumer = this.context.getBean( - "enableIntegrationTests.AnnotationTestService.annCount1.serviceActivator", - PollingConsumer.class); + "enableIntegrationTests.AnnotationTestService.annCount1.serviceActivator", + PollingConsumer.class); consumer.stop(); assertTrue(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class)); assertEquals(23, TestUtils.getPropertyValue(consumer, "phase")); assertSame(context.getBean("annInput1"), TestUtils.getPropertyValue(consumer, "inputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName")); assertSame(context.getBean("annAdvice1"), TestUtils.getPropertyValue(consumer, "handler.adviceChain", List.class).get(0)); assertEquals(2000L, TestUtils.getPropertyValue(consumer, "trigger.period")); @@ -425,7 +433,7 @@ public class EnableIntegrationTests { assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class)); assertEquals(23, TestUtils.getPropertyValue(consumer, "phase")); assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName")); assertSame(context.getBean("annAdvice"), TestUtils.getPropertyValue(consumer, "handler.adviceChain", List.class).get(0)); assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period")); @@ -437,7 +445,7 @@ public class EnableIntegrationTests { assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class)); assertEquals(23, TestUtils.getPropertyValue(consumer, "phase")); assertSame(context.getBean("annInput3"), TestUtils.getPropertyValue(consumer, "inputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName")); assertSame(context.getBean("annAdvice"), TestUtils.getPropertyValue(consumer, "handler.adviceChain", List.class).get(0)); assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period")); @@ -448,8 +456,8 @@ public class EnableIntegrationTests { assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class)); assertEquals(23, TestUtils.getPropertyValue(consumer, "phase")); assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.discardChannel")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.discardChannelName")); assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period")); assertEquals(1000L, TestUtils.getPropertyValue(consumer, "handler.messagingTemplate.sendTimeout")); assertFalse(TestUtils.getPropertyValue(consumer, "handler.sendPartialResultOnExpiry", Boolean.class)); @@ -460,8 +468,8 @@ public class EnableIntegrationTests { assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class)); assertEquals(23, TestUtils.getPropertyValue(consumer, "phase")); assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel")); - assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.discardChannel")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName")); + assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.discardChannelName")); assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period")); assertEquals(75L, TestUtils.getPropertyValue(consumer, "handler.messagingTemplate.sendTimeout")); assertTrue(TestUtils.getPropertyValue(consumer, "handler.sendPartialResultOnExpiry", Boolean.class)); @@ -795,8 +803,8 @@ public class EnableIntegrationTests { return new MessageHandler() { @Override public void handleMessage(Message message) throws MessagingException { - asyncAnnotationProcessLatch().countDown(); - asyncAnnotationProcessThread().set(Thread.currentThread()); + asyncAnnotationProcessLatch().countDown(); + asyncAnnotationProcessThread().set(Thread.currentThread()); } }; } @@ -996,7 +1004,7 @@ public class EnableIntegrationTests { } @MyServiceActivator1(inputChannel = "annInput1", autoStartup = "true", - adviceChain = { "annAdvice1" }, poller = @Poller(fixedRate = "2000") ) + adviceChain = {"annAdvice1"}, poller = @Poller(fixedRate = "2000")) public Integer annCount1() { return 0; } @@ -1074,11 +1082,11 @@ public class EnableIntegrationTests { @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @ServiceActivator(autoStartup = "false", - phase = "23", - inputChannel = "annInput", - outputChannel = "annOutput", - adviceChain = { "annAdvice" }, - poller = @Poller(fixedDelay = "1000")) + phase = "23", + inputChannel = "annInput", + outputChannel = "annOutput", + adviceChain = {"annAdvice"}, + poller = @Poller(fixedDelay = "1000")) public static @interface MyServiceActivator { String inputChannel() default ""; @@ -1181,22 +1189,22 @@ public class EnableIntegrationTests { @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @ServiceActivator(autoStartup = "false", - phase = "23", - inputChannel = "annInput", - outputChannel = "annOutput", - adviceChain = { "annAdvice" }, - poller = @Poller(fixedDelay = "1000")) + phase = "23", + inputChannel = "annInput", + outputChannel = "annOutput", + adviceChain = {"annAdvice"}, + poller = @Poller(fixedDelay = "1000")) public static @interface MyServiceActivatorNoLocalAtts { } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Aggregator(autoStartup = "false", - phase = "23", - inputChannel = "annInput", - outputChannel = "annOutput", - discardChannel = "annOutput", - poller = @Poller(fixedDelay = "1000")) + phase = "23", + inputChannel = "annInput", + outputChannel = "annOutput", + discardChannel = "annOutput", + poller = @Poller(fixedDelay = "1000")) public static @interface MyAggregator { String inputChannel() default ""; @@ -1219,13 +1227,13 @@ public class EnableIntegrationTests { @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Aggregator(autoStartup = "false", - phase = "23", - inputChannel = "annInput", - outputChannel = "annOutput", - discardChannel = "annOutput", - sendPartialResultsOnExpiry = false, - sendTimeout = 1000L, - poller = @Poller(fixedDelay = "1000")) + phase = "23", + inputChannel = "annInput", + outputChannel = "annOutput", + discardChannel = "annOutput", + sendPartialResultsOnExpiry = false, + sendTimeout = 1000L, + poller = @Poller(fixedDelay = "1000")) public static @interface MyAggregatorDefaultOverrideDefaults { boolean sendPartialResultsOnExpiry() default true; diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/RecipientListRouterTests.java b/spring-integration-core/src/test/java/org/springframework/integration/router/RecipientListRouterTests.java index 5b6a0dc725..45a5250ab9 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/RecipientListRouterTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/RecipientListRouterTests.java @@ -16,8 +16,12 @@ package org.springframework.integration.router; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collections; @@ -333,7 +337,7 @@ public class RecipientListRouterTests { assertNotNull(result1a); assertNotNull(result1b); assertEquals("test", result1a.getPayload()); - assertEquals(1,new IntegrationMessageHeaderAccessor(result1a).getSequenceNumber().intValue()); + assertEquals(1, new IntegrationMessageHeaderAccessor(result1a).getSequenceNumber().intValue()); assertEquals(2, new IntegrationMessageHeaderAccessor(result1a).getSequenceSize().intValue()); assertEquals(message.getHeaders().getId(), new IntegrationMessageHeaderAccessor(result1a).getCorrelationId()); assertEquals("test", result1b.getPayload()); @@ -426,6 +430,8 @@ public class RecipientListRouterTests { router.setBeanFactory(beanFactory); router.afterPropertiesSet(); + router.handleMessage(new GenericMessage("foo")); + assertSame(defaultChannel, TestUtils.getPropertyValue(router, "defaultOutputChannel")); Mockito.verify(beanFactory).getBean(Mockito.eq("defaultChannel"), Mockito.eq(MessageChannel.class)); }