From 45eaadd6ac587ef9adba8fcd15aa21474889213f Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Fri, 16 Jan 2015 16:43:18 +0200 Subject: [PATCH] INT-3601: Use `ChannelResolver` instead of BF JIRA: https://jira.spring.io/browse/INT-3601 * Move `setChannelResolver(DestinationResolver channelResolver)` to the `IntegrationObjectSupport` * Introduce `IntegrationObjectSupport#getChannelResolver()` * Change all `IntegrationObjectSupport` inheritors to use `getChannelResolver()` instead of direct `beanFactory` usage * Fix `ServiceActivatorEndpointTests` do not fall INT-3601: Addressing PR (JIRA) comments Fixes failing tests INT-3601: Address PR comments --- .../AbstractCorrelatingMessageHandler.java | 12 ++--- .../config/ConsumerEndpointFactoryBean.java | 26 ++++++++-- ...ourcePollingChannelAdapterFactoryBean.java | 37 +++++++++++---- .../context/IntegrationObjectSupport.java | 24 +++++++++- .../integration/filter/MessageFilter.java | 13 ++--- .../gateway/MessagingGatewaySupport.java | 40 +++------------- .../AbstractMessageProducingHandler.java | 24 ++-------- .../router/AbstractMappingMessageRouter.java | 47 ++----------------- .../AbstractMessageProcessingRouter.java | 2 +- .../router/AbstractMessageRouter.java | 11 +---- .../router/RecipientListRouter.java | 8 ++-- ...TransactionSynchronizationFactoryBean.java | 29 ++++++++++-- .../ServiceActivatorEndpointTests.java | 9 +++- .../handler/MessageHandlerChainTests.java | 5 +- .../advice/AdvisedMessageHandlerTests.java | 1 + 15 files changed, 134 insertions(+), 154 deletions(-) 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 b10f882834..5cb6243d19 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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 @@ -461,14 +461,8 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageP 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 = getChannelResolver().resolveDestination(this.discardChannelName); + this.discardChannelName = null; } } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/ConsumerEndpointFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/config/ConsumerEndpointFactoryBean.java index c298f97a17..facdc2c567 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/ConsumerEndpointFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/ConsumerEndpointFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -45,6 +45,8 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.SubscribableChannel; +import org.springframework.messaging.core.BeanFactoryMessageChannelDestinationResolver; +import org.springframework.messaging.core.DestinationResolver; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -92,6 +94,8 @@ public class ConsumerEndpointFactoryBean private volatile List adviceChain; + private volatile DestinationResolver channelResolver; + public void setHandler(MessageHandler handler) { Assert.notNull(handler, "handler must not be null"); synchronized (this.handlerMonitor) { @@ -112,6 +116,17 @@ public class ConsumerEndpointFactoryBean this.pollerMetadata = pollerMetadata; } + /** + * Specify the {@link DestinationResolver} strategy to use. + * The default is a BeanFactoryChannelResolver. + * @param channelResolver The channel resolver. + * @since 4.1.3 + */ + public void setChannelResolver(DestinationResolver channelResolver) { + Assert.notNull(channelResolver, "'channelResolver' must not be null"); + this.channelResolver = channelResolver; + } + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; @@ -190,7 +205,10 @@ public class ConsumerEndpointFactoryBean } } } - this.initializeEndpoint(); + if (this.channelResolver == null) { + this.channelResolver = new BeanFactoryMessageChannelDestinationResolver(this.beanFactory); + } + initializeEndpoint(); } @Override @@ -221,9 +239,7 @@ public class ConsumerEndpointFactoryBean } MessageChannel channel = null; if (StringUtils.hasText(this.inputChannelName)) { - Assert.isTrue(this.beanFactory.containsBean(this.inputChannelName), "no such input channel '" - + this.inputChannelName + "' for endpoint '" + this.beanName + "'"); - channel = this.beanFactory.getBean(this.inputChannelName, MessageChannel.class); + channel = this.channelResolver.resolveDestination(this.inputChannelName); } if (this.inputChannel != null) { channel = this.inputChannel; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/SourcePollingChannelAdapterFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/config/SourcePollingChannelAdapterFactoryBean.java index 1f6a01a86c..b1399f6133 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/SourcePollingChannelAdapterFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/SourcePollingChannelAdapterFactoryBean.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. @@ -29,7 +29,9 @@ import org.springframework.integration.core.MessageSource; import org.springframework.integration.endpoint.SourcePollingChannelAdapter; import org.springframework.integration.scheduling.PollerMetadata; import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.core.BeanFactoryMessageChannelDestinationResolver; import org.springframework.messaging.core.DestinationResolutionException; +import org.springframework.messaging.core.DestinationResolver; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -39,6 +41,7 @@ import org.springframework.util.StringUtils; * @author Mark Fisher * @author Oleg Zhurakousky * @author Gary Russell + * @author Artem Bilan */ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean, BeanFactoryAware, BeanNameAware, BeanClassLoaderAware, InitializingBean, SmartLifecycle { @@ -67,6 +70,8 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean channelResolver; + private final Object initializationMonitor = new Object(); public void setSource(MessageSource source) { @@ -97,27 +102,45 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean channelResolver) { + Assert.notNull(channelResolver, "'channelResolver' must not be null"); + this.channelResolver = channelResolver; + } + + @Override public void setBeanFactory(BeanFactory beanFactory) { Assert.isInstanceOf(ConfigurableBeanFactory.class, beanFactory, "a ConfigurableBeanFactory is required"); this.beanFactory = (ConfigurableBeanFactory) beanFactory; } + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } + @Override public void setBeanName(String beanName) { this.beanName = beanName; } + @Override public void afterPropertiesSet() throws Exception { - this.initializeAdapter(); + if (this.channelResolver == null) { + this.channelResolver = new BeanFactoryMessageChannelDestinationResolver(this.beanFactory); + } + initializeAdapter(); } public SourcePollingChannelAdapter getObject() throws Exception { if (this.adapter == null) { - this.initializeAdapter(); + initializeAdapter(); } return this.adapter; } @@ -139,13 +162,7 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean channelResolver; + private volatile String beanName; private volatile String componentName; @@ -126,6 +131,16 @@ public abstract class IntegrationObjectSupport implements BeanNameAware, NamedCo this.applicationContext = applicationContext; } + /** + * Specify the {@link DestinationResolver} strategy to use. + * The default is a BeanFactoryChannelResolver. + * @param channelResolver The channel resolver. + */ + public void setChannelResolver(DestinationResolver channelResolver) { + Assert.notNull(channelResolver, "'channelResolver' must not be null"); + this.channelResolver = channelResolver; + } + @Override public final void afterPropertiesSet() { try { @@ -160,6 +175,13 @@ public abstract class IntegrationObjectSupport implements BeanNameAware, NamedCo return this.taskScheduler; } + protected DestinationResolver getChannelResolver() { + if (this.channelResolver == null) { + this.channelResolver = new BeanFactoryChannelResolver(this.beanFactory); + } + return this.channelResolver; + } + protected void setTaskScheduler(TaskScheduler taskScheduler) { Assert.notNull(taskScheduler, "taskScheduler must not be null"); this.taskScheduler = taskScheduler; 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 ccb7a9f4fa..a066a8448a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -158,15 +158,8 @@ public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHa 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."); - } + this.discardChannel = getChannelResolver().resolveDestination(this.discardChannelName); + this.discardChannelName = null; } } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java index 3259e6abd5..b437fd9712 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/MessagingGatewaySupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -16,7 +16,6 @@ package org.springframework.integration.gateway; -import org.springframework.beans.BeansException; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.endpoint.EventDrivenConsumer; @@ -34,7 +33,6 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessagingException; import org.springframework.messaging.PollableChannel; import org.springframework.messaging.SubscribableChannel; -import org.springframework.messaging.core.DestinationResolutionException; import org.springframework.messaging.support.ErrorMessage; import org.springframework.util.Assert; @@ -236,16 +234,8 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint implement if (this.requestChannelName != null) { synchronized (this) { if (this.requestChannelName != null) { - try { - Assert.state(getBeanFactory() != null, - "A bean factory is required to resolve the requestChannel at runtime."); - this.requestChannel = getBeanFactory().getBean(this.requestChannelName, MessageChannel.class); - this.requestChannelName = null; - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.requestChannelName + "' in the BeanFactory."); - } + this.requestChannel = getChannelResolver().resolveDestination(this.requestChannelName); + this.requestChannelName = null; } } } @@ -256,16 +246,8 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint implement if (this.replyChannelName != null) { synchronized (this) { if (this.replyChannelName != null) { - try { - Assert.state(getBeanFactory() != null, - "A bean factory is required to resolve the replyChannel at runtime."); - this.replyChannel = getBeanFactory().getBean(this.replyChannelName, MessageChannel.class); - this.replyChannelName = null; - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.replyChannelName + "' in the BeanFactory."); - } + this.replyChannel = getChannelResolver().resolveDestination(this.replyChannelName); + this.replyChannelName = null; } } } @@ -276,16 +258,8 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint implement if (this.errorChannelName != null) { synchronized (this) { if (this.errorChannelName != null) { - try { - Assert.state(getBeanFactory() != null, - "A bean factory is required to resolve the errorChannel at runtime."); - this.errorChannel = getBeanFactory().getBean(this.errorChannelName, MessageChannel.class); - this.errorChannelName = null; - } - catch (BeansException e) { - throw new DestinationResolutionException("Failed to look up MessageChannel with name '" - + this.errorChannelName + "' in the BeanFactory."); - } + this.errorChannel = getChannelResolver().resolveDestination(this.errorChannelName); + this.errorChannelName = null; } } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageProducingHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageProducingHandler.java index f7870a8d0f..aaa034e5eb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageProducingHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageProducingHandler.java @@ -21,7 +21,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import org.springframework.beans.BeansException; import org.springframework.integration.IntegrationMessageHeaderAccessor; import org.springframework.integration.core.MessageProducer; import org.springframework.integration.core.MessagingTemplate; @@ -32,7 +31,6 @@ import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.messaging.core.DestinationResolutionException; -import org.springframework.messaging.core.DestinationResolver; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -71,15 +69,6 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan this.outputChannelName = outputChannelName;//NOSONAR (inconsistent sync) } - /** - * Set the DestinationResolver<MessageChannel> to be used when there is no default output channel. - * @param channelResolver The channel resolver. - */ - public void setChannelResolver(DestinationResolver channelResolver) { - Assert.notNull(channelResolver, "'channelResolver' must not be null"); - this.messagingTemplate.setDestinationResolver(channelResolver); - } - @Override protected void onInit() throws Exception { super.onInit(); @@ -88,22 +77,15 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan if (getBeanFactory() != null) { this.messagingTemplate.setBeanFactory(getBeanFactory()); } + this.messagingTemplate.setDestinationResolver(getChannelResolver()); } public MessageChannel getOutputChannel() { if (this.outputChannelName != null) { synchronized (this) { if (this.outputChannelName != null) { - try { - Assert.state(getBeanFactory() != null, - "A bean factory is required to resolve the outputChannel at runtime."); - 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."); - } + this.outputChannel = getChannelResolver().resolveDestination(this.outputChannelName); + this.outputChannelName = null; } } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMappingMessageRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMappingMessageRouter.java index 5e3667c2d8..7eea927970 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMappingMessageRouter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMappingMessageRouter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -46,14 +46,13 @@ import org.springframework.util.StringUtils; * @author Oleg Zhurakousky * @author Gunnar Hillert * @author Gary Russell + * @author Artem Bilan * @since 2.1 */ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter implements MappingMessageRouterManagement { private volatile Map channelMappings = new ConcurrentHashMap(); - private volatile DestinationResolver channelResolver; - private volatile String prefix; private volatile String suffix; @@ -64,7 +63,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter /** * Provide mappings from channel keys to channel names. * Channel names will be resolved by the {@link DestinationResolver}. - * * @param channelMappings The channel mappings. */ @Override @@ -76,22 +74,8 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter this.doSetChannelMappings(newChannelMappings); } - /** - * Specify the {@link DestinationResolver} strategy to use. - * The default is a BeanFactoryChannelResolver. - * This is considered an infrastructural configuration option and - * as of 2.1 has been deprecated as a configuration-driven attribute. - * - * @param channelResolver The channel resolver. - */ - public void setChannelResolver(DestinationResolver channelResolver) { - Assert.notNull(channelResolver, "'channelResolver' must not be null"); - this.channelResolver = channelResolver; - } - /** * Specify a prefix to be added to each channel name prior to resolution. - * * @param prefix The prefix. */ public void setPrefix(String prefix) { @@ -100,7 +84,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter /** * Specify a suffix to be added to each channel name prior to resolution. - * * @param suffix The suffix. */ public void setSuffix(String suffix) { @@ -110,7 +93,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter /** * Specify whether this router should ignore any failure to resolve a channel name to * an actual MessageChannel instance when delegating to the ChannelResolver strategy. - * * @param resolutionRequired true if resolution is required. */ public void setResolutionRequired(boolean resolutionRequired) { @@ -120,7 +102,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter /** * Returns an unmodifiable version of the channel mappings. * This is intended for use by subclasses only. - * * @return The channel mappings. */ @Override @@ -131,7 +112,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter /** * Add a channel mapping from the provided key to channel name. - * * @param key The key. * @param channelName The channel name. */ @@ -143,7 +123,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter /** * Remove a channel mapping for the given key if present. - * * @param key The key. */ @Override @@ -152,25 +131,10 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter this.channelMappings.remove(key); } - @Override - public void onInit() { - try { - super.onInit(); - } - catch (Exception e) { - throw new IllegalStateException(e); - } - BeanFactory beanFactory = this.getBeanFactory(); - if (this.channelResolver == null && beanFactory != null) { - this.channelResolver = new BeanFactoryChannelResolver(beanFactory); - } - } - /** * Subclasses must implement this method to return the channel keys. * A "key" might be present in this router's "channelMappings", or it * could be the channel's name or even the Message Channel instance itself. - * * @param message The message. * @return The channel keys. */ @@ -193,7 +157,6 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter *

Mappings must be delimited with newlines, for example: *

{@code "@'myRouter.handler'.replaceChannelMappings('foo=qux \n baz=bar')"}. * @param channelMappings The channel mappings. - * * @since 4.0 */ @Override @@ -218,13 +181,9 @@ public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter } private MessageChannel resolveChannelForName(String channelName, Message message) { - if (this.channelResolver == null) { - this.onInit(); - } - Assert.state(this.channelResolver != null, "unable to resolve channel names, no ChannelResolver available"); MessageChannel channel = null; try { - channel = this.channelResolver.resolveDestination(channelName); + channel = getChannelResolver().resolveDestination(channelName); } catch (DestinationResolutionException e) { if (this.resolutionRequired) { diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageProcessingRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageProcessingRouter.java index fbeb34a6b2..9210fcea95 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageProcessingRouter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractMessageProcessingRouter.java @@ -46,7 +46,7 @@ class AbstractMessageProcessingRouter extends AbstractMappingMessageRouter @Override - public final void onInit() { + public final void onInit() throws Exception { super.onInit(); if (this.messageProcessor instanceof AbstractMessageProcessor) { ((AbstractMessageProcessor) this.messageProcessor).setConversionService(this.getConversionService()); 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 74dc293fa3..51c22cbb4c 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 @@ -181,15 +181,8 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler { 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."); - } + this.defaultOutputChannel = getChannelResolver().resolveDestination(this.defaultOutputChannelName); + this.defaultOutputChannelName = null; } } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/RecipientListRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/RecipientListRouter.java index b9d8a647bc..9796820461 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/router/RecipientListRouter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/RecipientListRouter.java @@ -148,7 +148,7 @@ public class RecipientListRouter extends AbstractMessageRouter public void addRecipient(String channelName, String selectorExpression) { Assert.hasText(channelName, "'channelName' must not be empty."); Assert.hasText(selectorExpression, "'selectorExpression' must not be empty."); - MessageChannel channel = this.getBeanFactory().getBean(channelName, MessageChannel.class); + MessageChannel channel = getChannelResolver().resolveDestination(channelName); ExpressionEvaluatingSelector expressionEvaluatingSelector = new ExpressionEvaluatingSelector(selectorExpression); expressionEvaluatingSelector.setBeanFactory(this.getBeanFactory()); this.recipients.add(new Recipient(channel, expressionEvaluatingSelector)); @@ -158,7 +158,7 @@ public class RecipientListRouter extends AbstractMessageRouter @ManagedOperation public void addRecipient(String channelName) { Assert.hasText(channelName, "'channelName' must not be empty."); - MessageChannel channel = this.getBeanFactory().getBean(channelName, MessageChannel.class); + MessageChannel channel = getChannelResolver().resolveDestination(channelName); this.recipients.add(new Recipient(channel)); } @@ -166,7 +166,7 @@ public class RecipientListRouter extends AbstractMessageRouter @ManagedOperation public int removeRecipient(String channelName) { int counter = 0; - MessageChannel channel = this.getBeanFactory().getBean(channelName, MessageChannel.class); + MessageChannel channel = getChannelResolver().resolveDestination(channelName); for (Iterator it = this.recipients.iterator(); it.hasNext(); ) { if (it.next().getChannel() == channel) { it.remove(); @@ -180,7 +180,7 @@ public class RecipientListRouter extends AbstractMessageRouter @ManagedOperation public int removeRecipient(String channelName, String selectorExpression) { int counter = 0; - MessageChannel targetChannel = this.getBeanFactory().getBean(channelName, MessageChannel.class); + MessageChannel targetChannel = getChannelResolver().resolveDestination(channelName); for (Iterator it = this.recipients.iterator(); it.hasNext(); ) { Recipient next = it.next(); MessageSelector selector = next.getSelector(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transaction/TransactionSynchronizationFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/transaction/TransactionSynchronizationFactoryBean.java index 4d7451ef7b..769b7f22db 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transaction/TransactionSynchronizationFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transaction/TransactionSynchronizationFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2014-2015 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. @@ -23,6 +23,8 @@ import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.core.BeanFactoryMessageChannelDestinationResolver; +import org.springframework.messaging.core.DestinationResolver; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -58,11 +60,27 @@ public class TransactionSynchronizationFactoryBean implements FactoryBean channelResolver; + @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } + /** + * Specify the {@link DestinationResolver} strategy to use. + * The default is a BeanFactoryChannelResolver. + * @param channelResolver The channel resolver. + * @return current TransactionSynchronizationFactoryBean + * @since 4.1.3 + */ + public TransactionSynchronizationFactoryBean channelResolver(DestinationResolver channelResolver) { + Assert.notNull(channelResolver, "'channelResolver' must not be null"); + this.channelResolver = channelResolver; + return this; + } + + public TransactionSynchronizationFactoryBean beforeCommit(String expression) { return beforeCommit(expression, this.beforeCommitChannel); } @@ -143,6 +161,9 @@ public class TransactionSynchronizationFactoryBean implements FactoryBean message = MessageBuilder.withPayload("foo") .setReplyChannelName("testChannel").build(); endpoint.handleMessage(message); @@ -113,6 +116,8 @@ public class ServiceActivatorEndpointTests { TestChannelResolver channelResolver = new TestChannelResolver(); channelResolver.addChannel("replyChannel2", replyChannel2); endpoint.setChannelResolver(channelResolver); + endpoint.setBeanFactory(mock(BeanFactory.class)); + endpoint.afterPropertiesSet(); Message testMessage1 = MessageBuilder.withPayload("bar") .setReplyChannel(replyChannel1).build(); endpoint.handleMessage(testMessage1); @@ -209,7 +214,7 @@ public class ServiceActivatorEndpointTests { @Test public void testBeanFactoryPopulation() { ServiceActivatingHandler endpoint = this.createEndpoint(); - BeanFactory mock = Mockito.mock(BeanFactory.class); + BeanFactory mock = mock(BeanFactory.class); endpoint.setBeanFactory(mock); endpoint.afterPropertiesSet(); Object beanFactory = TestUtils.getPropertyValue(endpoint, "processor.beanFactory"); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/MessageHandlerChainTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/MessageHandlerChainTests.java index 4545935034..eca818cde5 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/MessageHandlerChainTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/MessageHandlerChainTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -85,6 +85,7 @@ public class MessageHandlerChainTests { chain.setBeanName("testChain"); chain.setHandlers(handlers); chain.setOutputChannel(outputChannel); + chain.setBeanFactory(mock(BeanFactory.class)); chain.handleMessage(message); Mockito.verify(outputChannel).send(Mockito.eq(message)); } @@ -112,6 +113,7 @@ public class MessageHandlerChainTests { MessageHandlerChain chain = new MessageHandlerChain(); chain.setBeanName("testChain"); chain.setHandlers(handlers); + chain.setBeanFactory(mock(BeanFactory.class)); chain.handleMessage(message); } @@ -125,6 +127,7 @@ public class MessageHandlerChainTests { MessageHandlerChain chain = new MessageHandlerChain(); chain.setBeanName("testChain"); chain.setHandlers(handlers); + chain.setBeanFactory(mock(BeanFactory.class)); chain.handleMessage(message); Mockito.verify(outputChannel).send(Mockito.any(Message.class)); } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java index 5d1e531445..8ed174913d 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/advice/AdvisedMessageHandlerTests.java @@ -153,6 +153,7 @@ public class AdvisedMessageHandlerTests { List adviceChain = new ArrayList(); adviceChain.add(advice); handler.setAdviceChain(adviceChain); + handler.setBeanFactory(mock(BeanFactory.class)); handler.afterPropertiesSet(); // advice with success