Message Endpoints and the SimpleTaskScheduler now manage their own lifecycles. The ApplicationContextMessageBus is no longer necessary (part of INT-462). The MessagePublishingErrorHandler now detects the default error channel within the beanFactory if necessary (INT-464).

This commit is contained in:
Mark Fisher
2008-11-11 20:11:21 +00:00
parent 7c28053b0f
commit f4ccde6257
52 changed files with 759 additions and 1076 deletions

View File

@@ -16,175 +16,7 @@
package org.springframework.integration.bus;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.generic.GenericBeanFactoryAccessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.Lifecycle;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.integration.scheduling.TaskSchedulerAware;
import org.springframework.util.Assert;
/**
* Spring Integration's standard Message Bus implementation. Serves as a
* registry for Messages Endpoints. Manages their lifecycle, activates
* subscriptions, and schedules pollers by delegating to a
* {@link TaskScheduler}. Retrieves MessageChannels from the
* ApplicationContext based on bean name.
*
* @author Mark Fisher
* @author Marius Bogoevici
*/
public class ApplicationContextMessageBus implements ApplicationContextAware, ApplicationListener, Lifecycle, DisposableBean {
public static final String ERROR_CHANNEL_BEAN_NAME = "errorChannel";
private final Log logger = LogFactory.getLog(this.getClass());
private volatile TaskScheduler taskScheduler;
private volatile ApplicationContext applicationContext;
private volatile boolean autoStartup = true;
private volatile boolean running;
private final Object lifecycleMonitor = new Object();
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Assert.notNull(applicationContext, "'applicationContext' must not be null");
Assert.state(!(applicationContext.getBeanNamesForType(this.getClass()).length > 1),
"Only one instance of '" + this.getClass().getSimpleName() + "' is allowed per ApplicationContext.");
this.applicationContext = applicationContext;
}
/**
* Set the {@link TaskScheduler} to use for scheduling message dispatchers.
*/
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
/**
* Set whether to automatically start the bus after initialization.
* <p>Default is 'true'; set this to 'false' to allow for manual startup
* through the {@link #start()} method.
*/
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
private Collection<MessageEndpoint> getEndpoints() {
GenericBeanFactoryAccessor accessor = new GenericBeanFactoryAccessor(this.applicationContext);
return accessor.getBeansOfType(MessageEndpoint.class).values();
}
private void activateEndpoints() {
for (MessageEndpoint endpoint : this.getEndpoints()) {
if (endpoint != null) {
this.activateEndpoint(endpoint);
}
}
}
private void deactivateEndpoints() {
for (MessageEndpoint endpoint : this.getEndpoints()) {
if (endpoint != null) {
this.deactivateEndpoint(endpoint);
}
}
}
private void activateEndpoint(MessageEndpoint endpoint) {
Assert.notNull(endpoint, "'endpoint' must not be null");
if (endpoint instanceof TaskSchedulerAware) {
((TaskSchedulerAware) endpoint).setTaskScheduler(this.taskScheduler);
}
if (endpoint instanceof Lifecycle) {
((Lifecycle) endpoint).start();
}
if (logger.isInfoEnabled()) {
logger.info("activated endpoint '" + endpoint + "'");
}
}
private void deactivateEndpoint(MessageEndpoint endpoint) {
Assert.notNull(endpoint, "'endpoint' must not be null");
if (endpoint instanceof Lifecycle) {
((Lifecycle) endpoint).stop();
if (this.logger.isInfoEnabled()) {
logger.info("deactivated endpoint '" + endpoint + "'");
}
}
}
// Lifecycle implementation
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return this.running;
}
}
public void start() {
if (this.running) {
return;
}
Assert.notNull(this.applicationContext, "ApplicationContext must not be null");
Assert.notNull(this.taskScheduler, "TaskScheduler must not be null");
synchronized (this.lifecycleMonitor) {
this.activateEndpoints();
this.taskScheduler.start();
}
this.running = true;
this.applicationContext.publishEvent(new MessageBusStartedEvent(this));
if (logger.isInfoEnabled()) {
logger.info("message bus started");
}
}
public void stop() {
if (!this.isRunning()) {
return;
}
synchronized (this.lifecycleMonitor) {
this.deactivateEndpoints();
this.running = false;
this.taskScheduler.stop();
}
this.applicationContext.publishEvent(new MessageBusStoppedEvent(this));
if (logger.isInfoEnabled()) {
logger.info("message bus stopped");
}
}
// ApplicationListener implementation
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent && this.autoStartup) {
this.start();
}
}
// DisposableBean implementation
public void destroy() throws Exception {
this.stop();
if (this.taskScheduler instanceof DisposableBean) {
((DisposableBean) this.taskScheduler).destroy();
}
}
// TODO: placeholder only, delete after handling all dependencies
public class ApplicationContextMessageBus {
}

View File

@@ -21,6 +21,7 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessagingException;
@@ -97,6 +98,10 @@ public class MessagePublishingErrorHandler implements ErrorHandler, BeanFactoryA
}
private MessageChannel resolveErrorChannel(Message<?> failedMessage) {
if (this.defaultErrorChannel == null && this.channelResolver != null) {
this.defaultErrorChannel = this.channelResolver.resolveChannelName(
IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME);
}
if (failedMessage == null || failedMessage.getHeaders().getErrorChannel() == null) {
return this.defaultErrorChannel;
}

View File

@@ -22,11 +22,13 @@ import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.channel.SubscribableChannel;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.message.MessageHandler;
@@ -39,7 +41,7 @@ import org.springframework.util.Assert;
/**
* @author Mark Fisher
*/
public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAware, BeanNameAware, InitializingBean {
public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAware, BeanNameAware, InitializingBean, ApplicationListener {
private final MessageHandler handler;
@@ -61,7 +63,7 @@ public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAwar
private volatile ConfigurableBeanFactory beanFactory;
private volatile MessageEndpoint endpoint;
private volatile AbstractEndpoint endpoint;
private volatile boolean initialized;
@@ -74,10 +76,6 @@ public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAwar
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public void setInputChannelName(String inputChannelName) {
this.inputChannelName = inputChannelName;
}
@@ -106,14 +104,22 @@ public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAwar
this.transactionDefinition = transactionDefinition;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ConfigurableBeanFactory.class, beanFactory,
"a ConfigurableBeanFactory is required");
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
}
public void afterPropertiesSet() {
Assert.hasText(this.inputChannelName, "inputChannelName is required");
public void afterPropertiesSet() throws Exception {
this.initializeEndpoint();
}
public boolean isSingleton() {
return true;
}
public Object getObject() throws Exception {
@@ -125,20 +131,17 @@ public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAwar
public Class<?> getObjectType() {
if (this.endpoint == null) {
return MessageEndpoint.class;
return AbstractEndpoint.class;
}
return endpoint.getClass();
return this.endpoint.getClass();
}
public boolean isSingleton() {
return true;
}
private void initializeEndpoint() {
private void initializeEndpoint() throws Exception {
synchronized (this.initializationMonitor) {
if (this.initialized) {
return;
}
Assert.hasText(this.inputChannelName, "inputChannelName is required");
Assert.isTrue(this.beanFactory.containsBean(this.inputChannelName),
"no such input channel '" + this.inputChannelName + "' for endpoint '" + this.beanName + "'");
MessageChannel channel = (MessageChannel)
@@ -166,8 +169,17 @@ public class ConsumerEndpointFactoryBean implements FactoryBean, BeanFactoryAwar
throw new IllegalArgumentException(
"unsupported channel type: [" + channel.getClass() + "]");
}
this.endpoint.setBeanName(this.beanName);
this.endpoint.setBeanFactory(this.beanFactory);
if (this.endpoint instanceof InitializingBean) {
((InitializingBean) this.endpoint).afterPropertiesSet();
}
this.initialized = true;
}
}
public void onApplicationEvent(ApplicationEvent event) {
this.endpoint.onApplicationEvent(event);
}
}

View File

@@ -20,7 +20,6 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.generic.GenericBeanFactoryAccessor;
import org.springframework.core.annotation.AnnotationUtils;
@@ -64,15 +63,6 @@ public abstract class AbstractMethodAnnotationPostProcessor<T extends Annotation
Poller pollerAnnotation = AnnotationUtils.findAnnotation(method, Poller.class);
MessageEndpoint endpoint = this.createEndpoint(handler, annotation, pollerAnnotation);
if (endpoint != null) {
if (endpoint instanceof InitializingBean) {
try {
((InitializingBean) endpoint).afterPropertiesSet();
}
catch (Exception e) {
throw new IllegalStateException(
"failed to initialize annotation-based consumer", e);
}
}
return endpoint;
}
return handler;

View File

@@ -18,6 +18,9 @@ package org.springframework.integration.config.annotation;
import java.lang.reflect.Method;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.integration.annotation.ChannelAdapter;
@@ -83,6 +86,18 @@ public class ChannelAdapterAnnotationPostProcessor implements MethodAnnotationPo
String annotationName = ClassUtils.getShortNameAsProperty(annotation.annotationType());
String endpointName = beanName + "." + method.getName() + "." + annotationName;
this.beanFactory.registerSingleton(endpointName, endpoint);
// TODO: move this to IntegrationContextUtils?... common with MAPP
if (endpoint instanceof BeanFactoryAware) {
((BeanFactoryAware) endpoint).setBeanFactory(beanFactory);
}
if (endpoint instanceof InitializingBean) {
try {
((InitializingBean) endpoint).afterPropertiesSet();
}
catch (Exception e) {
throw new BeanInitializationException("failed to initialize annotated channel adapter", e);
}
}
}
return bean;
}

View File

@@ -21,18 +21,22 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.Lifecycle;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.integration.annotation.Aggregator;
import org.springframework.integration.annotation.ChannelAdapter;
@@ -40,7 +44,6 @@ import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Splitter;
import org.springframework.integration.annotation.Transformer;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
@@ -55,9 +58,7 @@ import org.springframework.util.StringUtils;
* @author Mark Fisher
* @author Marius Bogoevici
*/
public class MessagingAnnotationPostProcessor implements BeanPostProcessor, BeanFactoryAware, InitializingBean {
private volatile Lifecycle messageBus;
public class MessagingAnnotationPostProcessor implements BeanPostProcessor, BeanFactoryAware, InitializingBean, ApplicationListener {
private volatile ConfigurableListableBeanFactory beanFactory;
@@ -65,6 +66,8 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
private final Map<Class<? extends Annotation>, MethodAnnotationPostProcessor<?>> postProcessors =
new HashMap<Class<? extends Annotation>, MethodAnnotationPostProcessor<?>>();
private Set<ApplicationListener> listeners = new HashSet<ApplicationListener>();
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isAssignable(ConfigurableListableBeanFactory.class, beanFactory.getClass(),
@@ -74,7 +77,6 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
public void afterPropertiesSet() {
Assert.notNull(this.beanFactory, "BeanFactory must not be null");
this.messageBus = (Lifecycle) this.beanFactory.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
postProcessors.put(Aggregator.class, new AggregatorAnnotationPostProcessor(this.beanFactory));
postProcessors.put(ChannelAdapter.class, new ChannelAdapterAnnotationPostProcessor(this.beanFactory));
postProcessors.put(Router.class, new RouterAnnotationPostProcessor(this.beanFactory));
@@ -108,8 +110,19 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
((BeanNameAware) result).setBeanName(endpointBeanName);
}
beanFactory.registerSingleton(endpointBeanName, result);
if (messageBus.isRunning() && result instanceof Lifecycle) {
((Lifecycle) result).start();
if (result instanceof BeanFactoryAware) {
((BeanFactoryAware) result).setBeanFactory(beanFactory);
}
if (result instanceof InitializingBean) {
try {
((InitializingBean) result).afterPropertiesSet();
}
catch (Exception e) {
throw new BeanInitializationException("failed to initialize annotated component", e);
}
}
if (result instanceof ApplicationListener) {
listeners.add((ApplicationListener) result);
}
}
}
@@ -158,4 +171,10 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
return name;
}
public void onApplicationEvent(ApplicationEvent event) {
for (ApplicationListener listener : listeners) {
listener.onApplicationEvent(event);
}
}
}

View File

@@ -87,6 +87,7 @@ public abstract class AbstractConsumerEndpointParser extends AbstractSingleBeanD
@Override
protected final void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
IntegrationNamespaceUtils.registerTaskSchedulerIfNecessary(parserContext.getRegistry());
BeanDefinitionBuilder consumerBuilder = this.parseConsumer(element, parserContext);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(consumerBuilder, element, OUTPUT_CHANNEL_ATTRIBUTE);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(consumerBuilder, element, SELECTOR_ATTRIBUTE);

View File

@@ -23,6 +23,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.scheduling.IntervalTrigger;
import org.springframework.integration.util.LifecycleSupport.AutoStartMode;
import org.springframework.util.Assert;
import org.springframework.util.xml.DomUtils;
@@ -52,6 +53,10 @@ public abstract class AbstractPollingInboundChannelAdapterParser extends Abstrac
else {
adapterBuilder.addPropertyValue("trigger", new IntervalTrigger(this.getDefaultPollInterval()));
}
String autoStart = element.getAttribute("auto-startup");
if ("false".equals(autoStart)) {
adapterBuilder.addPropertyValue("autoStartMode", AutoStartMode.NONE);
}
return adapterBuilder.getBeanDefinition();
}

View File

@@ -23,11 +23,19 @@ import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.channel.MessagePublishingErrorHandler;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.scheduling.CronTrigger;
import org.springframework.integration.scheduling.IntervalTrigger;
import org.springframework.integration.scheduling.SimpleTaskScheduler;
import org.springframework.integration.scheduling.Trigger;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert;
@@ -195,4 +203,32 @@ public abstract class IntegrationNamespaceUtils {
targetBuilder.addPropertyValue("transactionDefinition", txDefinition);
}
/**
* Register a TaskScheduler in the given BeanDefinitionRegistry if not yet present.
* The bean name for which this is checking is defined by the constant
* {@link IntegrationContextUtils#TASK_SCHEDULER_BEAN_NAME}.
*/
public static synchronized void registerTaskSchedulerIfNecessary(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME)) {
RootBeanDefinition errorChannelDef = new RootBeanDefinition(QueueChannel.class);
BeanDefinitionHolder errorChannelHolder = new BeanDefinitionHolder(
errorChannelDef, IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(errorChannelHolder, registry);
}
TaskExecutor taskExecutor = null;
if (!registry.containsBeanDefinition(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME)) {
taskExecutor = IntegrationContextUtils.createTaskExecutor(2, 100, 0, "integration-main-");
BeanDefinitionBuilder schedulerBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleTaskScheduler.class);
schedulerBuilder.addConstructorArgValue(taskExecutor);
BeanDefinitionBuilder errorHandlerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MessagePublishingErrorHandler.class);
errorHandlerBuilder.addPropertyReference("defaultErrorChannel", IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME);
String errorHandlerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(
errorHandlerBuilder.getBeanDefinition(), registry);
schedulerBuilder.addPropertyReference("errorHandler", errorHandlerBeanName);
BeanDefinitionHolder schedulerHolder = new BeanDefinitionHolder(
schedulerBuilder.getBeanDefinition(), IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(schedulerHolder, registry);
}
}
}

View File

@@ -17,7 +17,6 @@
package org.springframework.integration.config.xml;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import org.w3c.dom.Element;
@@ -27,21 +26,14 @@ import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.MessagePublishingErrorHandler;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor;
import org.springframework.integration.scheduling.SimpleTaskScheduler;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.integration.context.IntegrationContextUtils;
/**
* Parser for the &lt;message-bus&gt; element of the integration namespace.
@@ -51,35 +43,27 @@ import org.springframework.util.StringUtils;
*/
public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
public static final String MESSAGE_BUS_BEAN_NAME = "internal.MessageBus";
public static final String TASK_SCHEDULER_BEAN_NAME = "taskScheduler";
private static final String MESSAGING_ANNOTATION_POST_PROCESSOR_BEAN_NAME =
"internal.MessagingAnnotationPostProcessor";
private static final String TASK_SCHEDULER_ATTRIBUTE = "task-scheduler";
private static final String ASYNC_EVENT_MULTICASTER_ATTRIBUTE = "configure-async-event-multicaster";
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
Assert.state(!parserContext.getRegistry().containsBeanDefinition(MESSAGE_BUS_BEAN_NAME),
"Only one Message Bus is allowed per ApplicationContext.");
return MESSAGE_BUS_BEAN_NAME;
}
@Override
protected Class<?> getBeanClass(Element element) {
return ApplicationContextMessageBus.class;
}
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException {
return "messageBus";
}
@Override
protected boolean isEligibleAttribute(String attributeName) {
return !TASK_SCHEDULER_ATTRIBUTE.equals(attributeName) &&
!ASYNC_EVENT_MULTICASTER_ATTRIBUTE.equals(attributeName) &&
return !ASYNC_EVENT_MULTICASTER_ATTRIBUTE.equals(attributeName) &&
!"enable-annotations".equals(attributeName) &&
super.isEligibleAttribute(attributeName);
}
@@ -87,35 +71,9 @@ public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
String taskSchedulerRef = element.getAttribute(TASK_SCHEDULER_ATTRIBUTE);
TaskExecutor taskExecutor= null;
if (!parserContext.getRegistry().containsBeanDefinition(ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME)) {
RootBeanDefinition errorChannelDef = new RootBeanDefinition(QueueChannel.class);
BeanDefinitionHolder errorChannelHolder = new BeanDefinitionHolder(
errorChannelDef, ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(errorChannelHolder, parserContext.getRegistry());
}
if (StringUtils.hasText(taskSchedulerRef)) {
builder.addPropertyReference("taskScheduler", taskSchedulerRef);
}
else {
taskExecutor = this.createTaskExecutor(2, 100, 0, "message-bus-");
BeanDefinitionBuilder schedulerBuilder = BeanDefinitionBuilder.genericBeanDefinition(SimpleTaskScheduler.class);
schedulerBuilder.addConstructorArgValue(taskExecutor);
BeanDefinitionBuilder errorHandlerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MessagePublishingErrorHandler.class);
errorHandlerBuilder.addPropertyReference("defaultErrorChannel", ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME);
String errorHandlerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(
errorHandlerBuilder.getBeanDefinition(), parserContext.getRegistry());
schedulerBuilder.addPropertyReference("errorHandler", errorHandlerBeanName);
BeanDefinitionHolder schedulerHolder = new BeanDefinitionHolder(
schedulerBuilder.getBeanDefinition(), TASK_SCHEDULER_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(schedulerHolder, parserContext.getRegistry());
builder.addPropertyReference("taskScheduler", TASK_SCHEDULER_BEAN_NAME);
}
IntegrationNamespaceUtils.registerTaskSchedulerIfNecessary(parserContext.getRegistry());
if ("true".equals(element.getAttribute(ASYNC_EVENT_MULTICASTER_ATTRIBUTE).toLowerCase())) {
if (taskExecutor == null) {
taskExecutor = this.createTaskExecutor(1, 10, 0, "event-multicaster-");
}
TaskExecutor taskExecutor = IntegrationContextUtils.createTaskExecutor(1, 10, 0, "event-multicaster-");
BeanDefinitionBuilder eventMulticasterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
SimpleApplicationEventMulticaster.class);
eventMulticasterBuilder.addPropertyValue("taskExecutor", taskExecutor);
@@ -127,19 +85,6 @@ public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
this.addPostProcessors(element, parserContext);
}
private TaskExecutor createTaskExecutor(int coreSize, int maxSize, int queueCapacity, String threadPrefix) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(coreSize);
executor.setMaxPoolSize(maxSize);
executor.setQueueCapacity(queueCapacity);
if (StringUtils.hasText(threadPrefix)) {
executor.setThreadFactory(new CustomizableThreadFactory(threadPrefix));
}
executor.setRejectedExecutionHandler(new CallerRunsPolicy());
executor.afterPropertiesSet();
return executor;
}
/**
* Adds extra post-processors to the context, to inject the objects configured by the MessageBus
*/

View File

@@ -24,8 +24,6 @@
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="enable-annotations" type="xsd:boolean"/>
<xsd:attribute name="task-scheduler" type="xsd:string"/>
<xsd:attribute name="auto-startup" type="xsd:boolean"/>
<xsd:attribute name="configure-async-event-multicaster" type="xsd:boolean"/>
</xsd:complexType>
</xsd:element>
@@ -175,6 +173,7 @@
<xsd:attribute name="channel" type="xsd:string"/>
<xsd:attribute name="ref" type="xsd:string" use="required"/>
<xsd:attribute name="method" type="xsd:string"/>
<xsd:attribute name="auto-startup" type="xsd:string" default="true"/>
</xsd:complexType>
<xsd:element name="service-activator" type="inputOutputEndpointType">

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2002-2008 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.context;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author Mark Fisher
*/
public abstract class IntegrationContextUtils {
public static final String TASK_SCHEDULER_BEAN_NAME = "taskScheduler";
public static final String ERROR_CHANNEL_BEAN_NAME = "errorChannel";
public static MessageChannel getErrorChannel(BeanFactory beanFactory) {
return getBeanOfType(beanFactory, ERROR_CHANNEL_BEAN_NAME, MessageChannel.class);
}
public static TaskScheduler getTaskScheduler(BeanFactory beanFactory) {
return getBeanOfType(beanFactory, TASK_SCHEDULER_BEAN_NAME, TaskScheduler.class);
}
public static TaskScheduler getRequiredTaskScheduler(BeanFactory beanFactory) {
TaskScheduler taskScheduler = getTaskScheduler(beanFactory);
Assert.state(taskScheduler != null, "No such bean '" + TASK_SCHEDULER_BEAN_NAME + "'");
return taskScheduler;
}
@SuppressWarnings("unchecked")
private static <T> T getBeanOfType(BeanFactory beanFactory, String beanName, Class<T> type) {
if (!beanFactory.containsBean(beanName)) {
return null;
}
Object bean = beanFactory.getBean(beanName);
Assert.state(type.isAssignableFrom(bean.getClass()), "incorrect type for bean '" + beanName
+ "' expected [" + type + "], but actual type is [" + bean.getClass() + "].");
return (T) bean;
}
public static TaskExecutor createTaskExecutor(int coreSize, int maxSize, int queueCapacity, String threadPrefix) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(coreSize);
executor.setMaxPoolSize(maxSize);
executor.setQueueCapacity(queueCapacity);
if (StringUtils.hasText(threadPrefix)) {
executor.setThreadFactory(new CustomizableThreadFactory(threadPrefix));
}
executor.setRejectedExecutionHandler(new CallerRunsPolicy());
executor.afterPropertiesSet();
return executor;
}
}

View File

@@ -16,29 +16,58 @@
package org.springframework.integration.endpoint;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.integration.util.LifecycleSupport;
import org.springframework.util.Assert;
/**
* The base class for Message Endpoint implementations.
*
* @author Mark Fisher
*/
public abstract class AbstractEndpoint implements MessageEndpoint, BeanNameAware {
public abstract class AbstractEndpoint extends LifecycleSupport implements MessageEndpoint, BeanNameAware, BeanFactoryAware {
protected final Log logger = LogFactory.getLog(this.getClass());
private volatile String beanName;
private volatile String name;
private volatile BeanFactory beanFactory;
private volatile TaskScheduler taskScheduler;
public void setBeanName(String name) {
this.name = name;
public void setBeanName(String beanName) {
this.beanName = beanName;
}
// TODO: make this final (see TODO in GatewayProxyFactoryBean)
public void setBeanFactory(BeanFactory beanFactory) {
Assert.notNull(beanFactory, "beanFactory must not be null");
this.beanFactory = beanFactory;
TaskScheduler taskScheduler = IntegrationContextUtils.getTaskScheduler(beanFactory);
if (taskScheduler != null) {
this.setTaskScheduler(taskScheduler);
}
}
protected BeanFactory getBeanFactory() {
return this.beanFactory;
}
public void setTaskScheduler(TaskScheduler taskScheduler) {
Assert.notNull(taskScheduler, "taskScheduler must not be null");
this.taskScheduler = taskScheduler;
}
protected TaskScheduler getTaskScheduler() {
return this.taskScheduler;
}
@Override
public String toString() {
return (this.name != null) ? this.name : super.toString();
return (this.beanName != null) ? this.beanName : super.toString();
}
}

View File

@@ -25,11 +25,8 @@ import org.aopalliance.aop.Advice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.scheduling.IntervalTrigger;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.integration.scheduling.TaskSchedulerAware;
import org.springframework.integration.scheduling.Trigger;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
@@ -43,8 +40,7 @@ import org.springframework.util.ClassUtils;
/**
* @author Mark Fisher
*/
public abstract class AbstractPollingEndpoint extends AbstractEndpoint
implements TaskSchedulerAware, Lifecycle, InitializingBean, BeanClassLoaderAware {
public abstract class AbstractPollingEndpoint extends AbstractEndpoint implements InitializingBean, BeanClassLoaderAware {
public static final int MAX_MESSAGES_UNBOUNDED = -1;
@@ -65,15 +61,13 @@ public abstract class AbstractPollingEndpoint extends AbstractEndpoint
private volatile ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
private volatile TaskScheduler taskScheduler;
private volatile ScheduledFuture<?> runningTask;
private volatile Runnable poller;
private volatile boolean initialized;
private final Object lifecycleMonitor = new Object();
private final Object initializationMonitor = new Object();
public void setTrigger(Trigger trigger) {
@@ -93,10 +87,6 @@ public abstract class AbstractPollingEndpoint extends AbstractEndpoint
this.maxMessagesPerPoll = maxMessagesPerPoll;
}
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@@ -126,13 +116,14 @@ public abstract class AbstractPollingEndpoint extends AbstractEndpoint
private TransactionTemplate getTransactionTemplate() {
if (!this.initialized) {
this.afterPropertiesSet();
this.onInit();
}
return this.transactionTemplate;
}
public void afterPropertiesSet() {
synchronized (this.lifecycleMonitor) {
@Override
protected void onInit() {
synchronized (this.initializationMonitor) {
if (this.initialized) {
return;
}
@@ -163,35 +154,24 @@ public abstract class AbstractPollingEndpoint extends AbstractEndpoint
}
// Lifecycle implementation
// LifecycleSupport implementation
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return this.runningTask != null;
@Override // guarded by super#lifecycleLock
protected void doStart() {
if (!this.initialized) {
this.onInit();
}
Assert.state(this.getTaskScheduler() != null,
"unable to start polling, no taskScheduler available");
this.runningTask = this.getTaskScheduler().schedule(this.poller, this.trigger);
}
public void start() {
synchronized (this.lifecycleMonitor) {
if (!this.initialized) {
this.afterPropertiesSet();
}
if (this.isRunning()) {
return;
}
Assert.state(this.taskScheduler != null,
"unable to start polling, no taskScheduler available");
this.runningTask = this.taskScheduler.schedule(this.poller, this.trigger);
}
}
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.runningTask != null) {
this.runningTask.cancel(true);
}
this.runningTask = null;
@Override // guarded by super#lifecycleLock
protected void doStop() {
if (this.runningTask != null) {
this.runningTask.cancel(true);
}
this.runningTask = null;
}

View File

@@ -16,7 +16,6 @@
package org.springframework.integration.endpoint;
import org.springframework.context.Lifecycle;
import org.springframework.integration.channel.SubscribableChannel;
import org.springframework.integration.message.MessageHandler;
import org.springframework.util.Assert;
@@ -27,16 +26,12 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public class EventDrivenConsumer extends AbstractEndpoint implements Lifecycle {
public class EventDrivenConsumer extends AbstractEndpoint {
private final SubscribableChannel inputChannel;
private final MessageHandler handler;
private volatile boolean running;
private final Object lifecycleMonitor = new Object();
public EventDrivenConsumer(SubscribableChannel inputChannel, MessageHandler handler) {
Assert.notNull(inputChannel, "inputChannel must not be null");
@@ -46,28 +41,14 @@ public class EventDrivenConsumer extends AbstractEndpoint implements Lifecycle {
}
public boolean isRunning() {
synchronized (this.lifecycleMonitor) {
return this.running;
}
@Override // guarded by super#lifecycleLock
protected void doStart() {
this.inputChannel.subscribe(this.handler);
}
public void start() {
synchronized (this.lifecycleMonitor) {
if (!this.running) {
this.inputChannel.subscribe(this.handler);
this.running = true;
}
}
}
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.running) {
this.inputChannel.unsubscribe(this.handler);
this.running = false;
}
}
@Override // guarded by super#lifecycleLock
protected void doStop() {
this.inputChannel.unsubscribe(this.handler);
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.integration.endpoint;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.channel.MessageChannelTemplate;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
@@ -28,7 +27,7 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public abstract class MessageProducerSupport extends AbstractEndpoint implements InitializingBean {
public abstract class MessageProducerSupport extends AbstractEndpoint {
private volatile MessageChannel outputChannel;
@@ -43,7 +42,8 @@ public abstract class MessageProducerSupport extends AbstractEndpoint implements
this.channelTemplate.setSendTimeout(sendTimeout);
}
public void afterPropertiesSet() {
@Override
protected void onInit() {
Assert.notNull(this.outputChannel, "outputChannel is required");
}

View File

@@ -59,15 +59,16 @@ public class SourcePollingChannelAdapter extends AbstractPollingEndpoint {
this.channelTemplate.setSendTimeout(sendTimeout);
}
public void afterPropertiesSet() {
@Override
protected void onInit() {
Assert.notNull(this.source, "source must not be null");
Assert.notNull(this.outputChannel, "outputChannel must not be null");
super.afterPropertiesSet();
if (this.maxMessagesPerPoll < 0) {
// the default is 1 since a source might return
// a non-null value every time it is invoked
this.setMaxMessagesPerPoll(1);
}
super.onInit();
}
@Override

View File

@@ -23,6 +23,7 @@ import org.springframework.integration.channel.SubscribableChannel;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessagingException;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.endpoint.EventDrivenConsumer;
@@ -31,8 +32,6 @@ import org.springframework.integration.handler.ReplyMessageHolder;
import org.springframework.integration.message.ErrorMessage;
import org.springframework.integration.message.MessageHandler;
import org.springframework.integration.message.MessageDeliveryException;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.integration.scheduling.TaskSchedulerAware;
import org.springframework.util.Assert;
/**
@@ -43,7 +42,7 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public abstract class AbstractMessagingGateway implements MessagingGateway, MessageEndpoint, TaskSchedulerAware, Lifecycle {
public abstract class AbstractMessagingGateway extends AbstractEndpoint implements MessagingGateway {
private volatile MessageChannel requestChannel;
@@ -53,16 +52,10 @@ public abstract class AbstractMessagingGateway implements MessagingGateway, Mess
private volatile boolean shouldThrowErrors = true;
private volatile TaskScheduler taskScheduler;
private volatile MessageEndpoint replyMessageCorrelator;
private final Object replyMessageCorrelatorMonitor = new Object();
private volatile boolean running;
private final Object lifecycleMonitor = new Object();
/**
* Set the request channel.
@@ -113,10 +106,6 @@ public abstract class AbstractMessagingGateway implements MessagingGateway, Mess
this.shouldThrowErrors = shouldThrowErrors;
}
public void setTaskScheduler(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
public void send(Object object) {
Assert.state(this.requestChannel != null,
"send is not supported, because no request channel has been configured");
@@ -190,7 +179,7 @@ public abstract class AbstractMessagingGateway implements MessagingGateway, Mess
else if (this.replyChannel instanceof PollableChannel) {
PollingConsumer endpoint = new PollingConsumer(
(PollableChannel) this.replyChannel, handler);
endpoint.setTaskScheduler(this.taskScheduler);
endpoint.setBeanFactory(this.getBeanFactory());
endpoint.afterPropertiesSet();
correlator = endpoint;
}
@@ -201,25 +190,17 @@ public abstract class AbstractMessagingGateway implements MessagingGateway, Mess
}
}
public boolean isRunning() {
return this.running;
}
public void start() {
synchronized (this.lifecycleMonitor) {
if (this.replyMessageCorrelator != null && this.replyMessageCorrelator instanceof Lifecycle) {
((Lifecycle) this.replyMessageCorrelator).start();
}
this.running = true;
@Override // guarded by super#lifecycleLock
protected void doStart() {
if (this.replyMessageCorrelator != null && this.replyMessageCorrelator instanceof Lifecycle) {
((Lifecycle) this.replyMessageCorrelator).start();
}
}
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.replyMessageCorrelator != null && this.replyMessageCorrelator instanceof Lifecycle) {
((Lifecycle) this.replyMessageCorrelator).stop();
}
this.running = false;
@Override // guarded by super#lifecycleLock
protected void doStop() {
if (this.replyMessageCorrelator != null && this.replyMessageCorrelator instanceof Lifecycle) {
((Lifecycle) this.replyMessageCorrelator).stop();
}
}

View File

@@ -37,11 +37,10 @@ import org.springframework.integration.annotation.Gateway;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.channel.ChannelResolver;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.message.MethodParameterMessageMapper;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -52,8 +51,8 @@ import org.springframework.util.StringUtils;
*
* @author Mark Fisher
*/
public class GatewayProxyFactoryBean implements FactoryBean, MethodInterceptor, BeanClassLoaderAware, BeanFactoryAware,
InitializingBean, Lifecycle {
public class GatewayProxyFactoryBean extends AbstractEndpoint implements FactoryBean, MethodInterceptor, BeanClassLoaderAware, BeanFactoryAware,
InitializingBean {
private volatile Class<?> serviceInterface;
@@ -73,18 +72,12 @@ public class GatewayProxyFactoryBean implements FactoryBean, MethodInterceptor,
private final Map<Method, MessagingGateway> gatewayMap = new HashMap<Method, MessagingGateway>();
private volatile TaskScheduler taskScheduler;
private volatile ChannelResolver channelResolver;
private volatile boolean initialized;
private volatile boolean running;
private final Object initializationMonitor = new Object();
private final Object lifecycleMonitor = new Object();
public void setServiceInterface(Class<?> serviceInterface) {
if (serviceInterface != null && !serviceInterface.isInterface()) {
@@ -144,12 +137,14 @@ public class GatewayProxyFactoryBean implements FactoryBean, MethodInterceptor,
this.beanClassLoader = beanClassLoader;
}
@Override // TODO: remove this and move channelResolver to parent class
public void setBeanFactory(BeanFactory beanFactory) {
this.taskScheduler = (TaskScheduler) beanFactory.getBean(MessageBusParser.TASK_SCHEDULER_BEAN_NAME);
super.setBeanFactory(beanFactory);
this.channelResolver = new BeanFactoryChannelResolver(beanFactory);
}
public void afterPropertiesSet() throws Exception {
@Override
protected void onInit() throws Exception {
synchronized (this.initializationMonitor) {
if (this.initialized) {
return;
@@ -226,7 +221,9 @@ public class GatewayProxyFactoryBean implements FactoryBean, MethodInterceptor,
private MessagingGateway createGatewayForMethod(Method method) throws Exception {
SimpleMessagingGateway gateway = new SimpleMessagingGateway(
new MethodParameterMessageMapper(method), new SimpleMessageMapper());
gateway.setTaskScheduler(this.taskScheduler);
if (this.getTaskScheduler() != null) {
gateway.setTaskScheduler(this.getTaskScheduler());
}
Gateway gatewayAnnotation = method.getAnnotation(Gateway.class);
MessageChannel requestChannel = this.defaultRequestChannel;
MessageChannel replyChannel = this.defaultReplyChannel;
@@ -251,37 +248,28 @@ public class GatewayProxyFactoryBean implements FactoryBean, MethodInterceptor,
gateway.setReplyChannel(replyChannel);
gateway.setRequestTimeout(requestTimeout);
gateway.setReplyTimeout(replyTimeout);
if (this.getBeanFactory() != null) {
gateway.setBeanFactory(this.getBeanFactory());
}
return gateway;
}
// Lifecycle implementation
public boolean isRunning() {
return this.running;
}
public void start() {
synchronized (this.lifecycleMonitor) {
if (!this.running) {
for (MessagingGateway gateway : this.gatewayMap.values()) {
if (gateway instanceof Lifecycle) {
((Lifecycle) gateway).start();
}
}
this.running = true;
@Override // guarded by super#lifecycleLock
protected void doStart() {
for (MessagingGateway gateway : this.gatewayMap.values()) {
if (gateway instanceof Lifecycle) {
((Lifecycle) gateway).start();
}
}
}
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.running) {
for (MessagingGateway gateway : this.gatewayMap.values()) {
if (gateway instanceof Lifecycle) {
((Lifecycle) gateway).stop();
}
}
this.running = false;
@Override // guarded by super#lifecycleLock
protected void doStop() {
for (MessagingGateway gateway : this.gatewayMap.values()) {
if (gateway instanceof Lifecycle) {
((Lifecycle) gateway).stop();
}
}
}

View File

@@ -26,14 +26,18 @@ import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.channel.MessagePublishingErrorHandler;
import org.springframework.integration.util.ErrorHandler;
import org.springframework.integration.util.LifecycleSupport;
import org.springframework.scheduling.SchedulingException;
import org.springframework.util.Assert;
@@ -43,7 +47,7 @@ import org.springframework.util.Assert;
* @author Mark Fisher
* @author Marius Bogoevici
*/
public class SimpleTaskScheduler implements TaskScheduler, DisposableBean {
public class SimpleTaskScheduler extends LifecycleSupport implements TaskScheduler, BeanFactoryAware, DisposableBean {
private final Log logger = LogFactory.getLog(this.getClass());
@@ -57,14 +61,11 @@ public class SimpleTaskScheduler implements TaskScheduler, DisposableBean {
private final Set<TriggeredTask<?>> executingTasks = Collections.synchronizedSet(new TreeSet<TriggeredTask<?>>());
private volatile boolean running;
private final ReentrantLock lifecycleLock = new ReentrantLock();
public SimpleTaskScheduler(TaskExecutor executor) {
Assert.notNull(executor, "executor must not be null");
this.executor = executor;
this.setAutoStartMode(AutoStartMode.ON_CONTEXT_REFRESH);
}
@@ -72,7 +73,14 @@ public class SimpleTaskScheduler implements TaskScheduler, DisposableBean {
this.errorHandler = errorHandler;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (this.errorHandler == null) {
this.errorHandler = new MessagePublishingErrorHandler(new BeanFactoryChannelResolver(beanFactory));
}
}
public final ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
Assert.notNull(task, "task must not be null");
TriggeredTask<Void> triggeredTask = new TriggeredTask<Void>(task, trigger);
return this.schedule(triggeredTask, null, null);
}
@@ -87,56 +95,28 @@ public class SimpleTaskScheduler implements TaskScheduler, DisposableBean {
}
// Lifecycle implementation
// LifecycleSupport implementation
public boolean isRunning() {
this.lifecycleLock.lock();
try {
return this.running;
}
finally {
this.lifecycleLock.unlock();
}
@Override // guarded by super#lifecycleLock
protected void doStart() {
this.executor.execute(this.schedulerTask = new SchedulerTask());
}
public void start() {
this.lifecycleLock.lock();
try {
if (this.running) {
return;
}
this.running = true;
this.executor.execute(this.schedulerTask = new SchedulerTask());
@Override // guarded by super#lifecycleLock
protected void doStop() {
this.schedulerTask.deactivate();
Thread executingThread = this.schedulerTask.executingThread.get();
if (executingThread != null) {
executingThread.interrupt();
}
finally {
this.lifecycleLock.unlock();
}
}
public void stop() {
this.lifecycleLock.lock();
try {
if (!this.running) {
return;
this.scheduledTasks.clear();
synchronized (this.executingTasks) {
for (TriggeredTask<?> task : this.executingTasks) {
task.cancel(true);
}
this.running = false;
this.schedulerTask.deactivate();
Thread executingThread = this.schedulerTask.executingThread.get();
if (executingThread != null) {
executingThread.interrupt();
}
this.scheduledTasks.clear();
synchronized (this.executingTasks) {
for (TriggeredTask<?> task : this.executingTasks) {
task.cancel(true);
}
this.executingTasks.clear();
}
this.schedulerTask = null;
}
finally {
this.lifecycleLock.unlock();
this.executingTasks.clear();
}
this.schedulerTask = null;
}
public void destroy() throws Exception {
@@ -236,7 +216,7 @@ public class SimpleTaskScheduler implements TaskScheduler, DisposableBean {
public long getDelay(TimeUnit unit) {
long now = new Date().getTime();
long scheduled = this.scheduledTime.getTime();
long scheduled = (this.scheduledTime != null) ? this.scheduledTime.getTime() : now;
return (scheduled > now) ? unit.convert(scheduled - now, TimeUnit.MILLISECONDS) : 0;
}

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2002-2008 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.util;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.Lifecycle;
import org.springframework.context.event.ContextRefreshedEvent;
/**
* A convenience base class for Lifecycle components that supports an
* "auto-startup" mode property. Depending on the mode, the component can
* be started either upon initialization, upon receiving the
* {@link ContextRefreshedEvent}, or may require an explicit start invocation.
* The timing of the startup is determined by the value of {@link #autoStartMode}.
* The default value is {@link AutoStartMode#ON_INIT}. To require explicit startup,
* set the mode to {@link AutoStartMode#NONE} using the
* {@link #setAutoStartMode(AutoStartMode)} method.
*
* @author Mark Fisher
*/
public abstract class LifecycleSupport implements Lifecycle, InitializingBean, ApplicationListener {
public static enum AutoStartMode { ON_INIT, ON_CONTEXT_REFRESH, NONE }
protected final Log logger = LogFactory.getLog(this.getClass());
private volatile AutoStartMode autoStartMode = AutoStartMode.ON_INIT;
private volatile boolean running;
private final ReentrantLock lifecycleLock = new ReentrantLock();
public void setAutoStartMode(AutoStartMode autoStartMode) {
this.autoStartMode = (autoStartMode != null) ? autoStartMode : AutoStartMode.NONE;
}
public final void afterPropertiesSet() {
try {
this.onInit();
if (this.autoStartMode == AutoStartMode.ON_INIT) {
this.start();
}
}
catch (Exception e) {
throw new BeanInitializationException("failed to initialize", e);
}
}
public final void onApplicationEvent(ApplicationEvent event) {
this.onEvent(event);
if (event instanceof ContextRefreshedEvent && this.autoStartMode == AutoStartMode.ON_CONTEXT_REFRESH) {
this.start();
}
}
// Lifecycle implementation
public final boolean isRunning() {
this.lifecycleLock.lock();
try {
return this.running;
}
finally {
this.lifecycleLock.unlock();
}
}
public final void start() {
this.lifecycleLock.lock();
try {
if (!this.running) {
this.doStart();
this.running = true;
if (logger.isInfoEnabled()) {
logger.info("started " + this);
}
}
}
finally {
this.lifecycleLock.unlock();
}
}
public final void stop() {
this.lifecycleLock.lock();
try {
if (this.running) {
this.doStop();
this.running = false;
if (logger.isInfoEnabled()) {
logger.info("stopped " + this);
}
}
}
finally {
this.lifecycleLock.unlock();
}
}
protected void onInit() throws Exception {
}
protected void onEvent(ApplicationEvent event) {
}
/**
* Subclasses must implement this method with the start behavior.
* This method will be invoked while holding the {@link #lifecycleLock}.
*/
protected abstract void doStart();
/**
* Subclasses must implement this method with the stop behavior.
* This method will be invoked while holding the {@link #lifecycleLock}.
*/
protected abstract void doStop();
}

View File

@@ -26,21 +26,18 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.Lifecycle;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.channel.ChannelResolver;
import org.springframework.integration.channel.MessagePublishingErrorHandler;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.channel.PublishSubscribeChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.core.Message;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.handler.ReplyMessageHolder;
import org.springframework.integration.message.ErrorMessage;
@@ -49,8 +46,8 @@ import org.springframework.integration.message.MessageBuilder;
import org.springframework.integration.message.MessageSource;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.scheduling.IntervalTrigger;
import org.springframework.integration.scheduling.SimpleTaskScheduler;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
@@ -59,13 +56,11 @@ public class ApplicationContextMessageBusTests {
@Test
public void endpointRegistrationWithInputChannelReference() {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel sourceChannel = new QueueChannel();
QueueChannel targetChannel = new QueueChannel();
sourceChannel.setBeanName("sourceChannel");
targetChannel.setBeanName("targetChannel");
context.getBeanFactory().registerSingleton("sourceChannel", sourceChannel);
context.getBeanFactory().registerSingleton("targetChannel", targetChannel);
context.registerChannel("sourceChannel", sourceChannel);
context.registerChannel("targetChannel", targetChannel);
Message<String> message = MessageBuilder.withPayload("test")
.setReplyChannelName("targetChannel").build();
sourceChannel.send(message);
@@ -76,37 +71,25 @@ public class ApplicationContextMessageBusTests {
};
handler.setBeanFactory(context);
PollingConsumer endpoint = new PollingConsumer(sourceChannel, handler);
endpoint.afterPropertiesSet();
context.getBeanFactory().registerSingleton("testEndpoint", endpoint);
context.registerEndpoint("testEndpoint", endpoint);
context.refresh();
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
context.getBeanFactory().registerSingleton(MessageBusParser.MESSAGE_BUS_BEAN_NAME, bus);
bus.setApplicationContext(context);
bus.start();
Message<?> result = targetChannel.receive(3000);
assertEquals("test", result.getPayload());
bus.stop();
context.stop();
}
@Test
public void channelsWithoutHandlers() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
bus.setApplicationContext(context);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel sourceChannel = new QueueChannel();
sourceChannel.setBeanName("sourceChannel");
context.getBeanFactory().registerSingleton("sourceChannel", sourceChannel);
context.registerChannel("sourceChannel", sourceChannel);
sourceChannel.send(new StringMessage("test"));
QueueChannel targetChannel = new QueueChannel();
targetChannel.setBeanName("targetChannel");
context.getBeanFactory().registerSingleton("targetChannel", targetChannel);
context.registerChannel("targetChannel", targetChannel);
context.refresh();
bus.start();
Message<?> result = targetChannel.receive(100);
assertNull(result);
bus.stop();
context.stop();
}
@Test
@@ -116,15 +99,13 @@ public class ApplicationContextMessageBusTests {
PollableChannel sourceChannel = (PollableChannel) context.getBean("sourceChannel");
sourceChannel.send(new GenericMessage<String>("test"));
PollableChannel targetChannel = (PollableChannel) context.getBean("targetChannel");
Lifecycle bus = (Lifecycle) context.getBean("bus");
bus.start();
Message<?> result = targetChannel.receive(1000);
assertEquals("test", result.getPayload());
}
@Test
public void exactlyOneConsumerReceivesPointToPointMessage() {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel1 = new QueueChannel();
QueueChannel outputChannel2 = new QueueChannel();
@@ -140,35 +121,26 @@ public class ApplicationContextMessageBusTests {
replyHolder.set(message);
}
};
inputChannel.setBeanName("input");
outputChannel1.setBeanName("output1");
outputChannel2.setBeanName("output2");
context.getBeanFactory().registerSingleton("input", inputChannel);
context.getBeanFactory().registerSingleton("output1", outputChannel1);
context.getBeanFactory().registerSingleton("output2", outputChannel2);
context.registerChannel("input", inputChannel);
context.registerChannel("output1", outputChannel1);
context.registerChannel("output2", outputChannel2);
handler1.setOutputChannel(outputChannel1);
handler2.setOutputChannel(outputChannel2);
PollingConsumer endpoint1 = new PollingConsumer(inputChannel, handler1);
endpoint1.afterPropertiesSet();
PollingConsumer endpoint2 = new PollingConsumer(inputChannel, handler2);
endpoint2.afterPropertiesSet();
context.getBeanFactory().registerSingleton("testEndpoint1", endpoint1);
context.getBeanFactory().registerSingleton("testEndpoint2", endpoint2);
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint1", endpoint1);
context.registerEndpoint("testEndpoint2", endpoint2);
context.refresh();
bus.start();
inputChannel.send(new StringMessage("testing"));
Message<?> message1 = outputChannel1.receive(500);
Message<?> message2 = outputChannel2.receive(0);
bus.stop();
context.stop();
assertTrue("exactly one message should be null", message1 == null ^ message2 == null);
}
@Test
public void bothConsumersReceivePublishSubscribeMessage() throws InterruptedException {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
PublishSubscribeChannel inputChannel = new PublishSubscribeChannel();
QueueChannel outputChannel1 = new QueueChannel();
QueueChannel outputChannel2 = new QueueChannel();
@@ -187,60 +159,45 @@ public class ApplicationContextMessageBusTests {
latch.countDown();
}
};
inputChannel.setBeanName("input");
outputChannel1.setBeanName("output1");
outputChannel2.setBeanName("output2");
context.getBeanFactory().registerSingleton("input", inputChannel);
context.getBeanFactory().registerSingleton("output1", outputChannel1);
context.getBeanFactory().registerSingleton("output2", outputChannel2);
context.registerChannel("input", inputChannel);
context.registerChannel("output1", outputChannel1);
context.registerChannel("output2", outputChannel2);
handler1.setOutputChannel(outputChannel1);
handler2.setOutputChannel(outputChannel2);
EventDrivenConsumer endpoint1 = new EventDrivenConsumer(inputChannel, handler1);
EventDrivenConsumer endpoint2 = new EventDrivenConsumer(inputChannel, handler2);
context.getBeanFactory().registerSingleton("testEndpoint1", endpoint1);
context.getBeanFactory().registerSingleton("testEndpoint2", endpoint2);
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint1", endpoint1);
context.registerEndpoint("testEndpoint2", endpoint2);
context.refresh();
bus.start();
inputChannel.send(new StringMessage("testing"));
latch.await(500, TimeUnit.MILLISECONDS);
assertEquals("both handlers should have been invoked", 0, latch.getCount());
Message<?> message1 = outputChannel1.receive(500);
Message<?> message2 = outputChannel2.receive(500);
bus.stop();
context.stop();
assertNotNull("both handlers should have replied to the message", message1);
assertNotNull("both handlers should have replied to the message", message2);
}
@Test
public void errorChannelWithFailedDispatch() throws InterruptedException {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel errorChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
errorChannel.setBeanName("errorChannel");
context.getBeanFactory().registerSingleton("errorChannel", errorChannel);
context.registerChannel("errorChannel", errorChannel);
CountDownLatch latch = new CountDownLatch(1);
SourcePollingChannelAdapter channelAdapter = new SourcePollingChannelAdapter();
channelAdapter.setSource(new FailingSource(latch));
channelAdapter.setTrigger(new IntervalTrigger(1000));
channelAdapter.setOutputChannel(outputChannel);
channelAdapter.setBeanName("testChannel");
context.getBeanFactory().registerSingleton("testChannel", channelAdapter);
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
SimpleTaskScheduler taskScheduler = (SimpleTaskScheduler) TestUtils.createTaskScheduler(10);
context.registerEndpoint("testChannel", channelAdapter);
ChannelResolver channelResolver = new BeanFactoryChannelResolver(context);
MessagePublishingErrorHandler errorHandler = new MessagePublishingErrorHandler(channelResolver);
errorHandler.setDefaultErrorChannel(errorChannel);
taskScheduler.setErrorHandler(errorHandler);
bus.setTaskScheduler(taskScheduler);
bus.setApplicationContext(context);
context.refresh();
bus.start();
latch.await(2000, TimeUnit.MILLISECONDS);
Message<?> message = errorChannel.receive(5000);
bus.stop();
context.stop();
assertNull(outputChannel.receive(0));
assertNotNull("message should not be null", message);
assertTrue(message instanceof ErrorMessage);
@@ -248,17 +205,11 @@ public class ApplicationContextMessageBusTests {
assertEquals("intentional test failure", exception.getMessage());
}
@Test(expected = BeanCreationException.class)
public void multipleMessageBusBeans() {
new ClassPathXmlApplicationContext("multipleMessageBusBeans.xml", this.getClass());
}
@Test
public void consumerSubscribedToErrorChannel() throws InterruptedException {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel errorChannel = new QueueChannel();
errorChannel.setBeanName(ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME);
context.getBeanFactory().registerSingleton(ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME, errorChannel);
context.registerChannel(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, errorChannel);
final CountDownLatch latch = new CountDownLatch(1);
AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
@Override
@@ -267,16 +218,12 @@ public class ApplicationContextMessageBusTests {
}
};
PollingConsumer endpoint = new PollingConsumer(errorChannel, handler);
endpoint.afterPropertiesSet();
context.getBeanFactory().registerSingleton("testEndpoint", endpoint);
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint", endpoint);
context.refresh();
bus.start();
errorChannel.send(new ErrorMessage(new RuntimeException("test-exception")));
latch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("handler should have received error message", 0, latch.getCount());
context.stop();
}

View File

@@ -21,14 +21,13 @@ import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.channel.ThreadLocalChannel;
import org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessagingException;
import org.springframework.integration.endpoint.EventDrivenConsumer;
@@ -37,15 +36,14 @@ import org.springframework.integration.handler.ReplyMessageHolder;
import org.springframework.integration.handler.ServiceActivatingHandler;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
*/
public class DirectChannelSubscriptionTests {
private GenericApplicationContext context = new GenericApplicationContext();
private ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
private TestApplicationContext context = TestUtils.createTestApplicationContext();
private DirectChannel sourceChannel = new DirectChannel();
@@ -54,30 +52,23 @@ public class DirectChannelSubscriptionTests {
@Before
public void setupChannels() {
sourceChannel.setBeanName("sourceChannel");
targetChannel.setBeanName("targetChannel");
context.getBeanFactory().registerSingleton("sourceChannel", sourceChannel);
context.getBeanFactory().registerSingleton("targetChannel", targetChannel);
context.getBeanFactory().registerSingleton(MessageBusParser.MESSAGE_BUS_BEAN_NAME, bus);
bus.setApplicationContext(context);
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
context.registerChannel("sourceChannel", sourceChannel);
context.registerChannel("targetChannel", targetChannel);
}
@Test
public void sendAndReceiveForRegisteredEndpoint() {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
ServiceActivatingHandler serviceActivator = new ServiceActivatingHandler(new TestBean(), "handle");
serviceActivator.setOutputChannel(targetChannel);
EventDrivenConsumer endpoint = new EventDrivenConsumer(sourceChannel, serviceActivator);
context.getBeanFactory().registerSingleton("testEndpoint", endpoint);
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint", endpoint);
context.refresh();
bus.start();
this.sourceChannel.send(new StringMessage("foo"));
Message<?> response = this.targetChannel.receive();
assertEquals("foo!", response.getPayload());
bus.stop();
context.stop();
}
@Test
@@ -88,11 +79,10 @@ public class DirectChannelSubscriptionTests {
TestEndpoint endpoint = new TestEndpoint();
postProcessor.postProcessAfterInitialization(endpoint, "testEndpoint");
context.refresh();
bus.start();
this.sourceChannel.send(new StringMessage("foo"));
Message<?> response = this.targetChannel.receive();
assertEquals("foo-from-annotated-endpoint", response.getPayload());
bus.stop();
context.stop();
}
@Test(expected = MessagingException.class)
@@ -105,27 +95,32 @@ public class DirectChannelSubscriptionTests {
};
handler.setOutputChannel(targetChannel);
EventDrivenConsumer endpoint = new EventDrivenConsumer(sourceChannel, handler);
context.getBeanFactory().registerSingleton("testEndpoint", endpoint);
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint", endpoint);
context.refresh();
bus.start();
this.sourceChannel.send(new StringMessage("foo"));
try {
this.sourceChannel.send(new StringMessage("foo"));
}
finally {
context.stop();
}
}
@Test(expected = MessagingException.class)
public void exceptionThrownFromAnnotatedEndpoint() {
QueueChannel errorChannel = new QueueChannel();
errorChannel.setBeanName(ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME);
context.getBeanFactory().registerSingleton(
ApplicationContextMessageBus.ERROR_CHANNEL_BEAN_NAME, errorChannel);
context.registerChannel(IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME, errorChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
FailingTestEndpoint endpoint = new FailingTestEndpoint();
postProcessor.postProcessAfterInitialization(endpoint, "testEndpoint");
context.refresh();
bus.start();
this.sourceChannel.send(new StringMessage("foo"));
try {
this.sourceChannel.send(new StringMessage("foo"));
}
finally {
context.stop();
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2002-2008 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.bus;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.util.TestUtils;
/**
* @author Marius Bogoevici
* @author Mark Fisher
*/
public class MessageBusEventTests {
@Test
public void messageBusStartedEvent() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("listener", new RootBeanDefinition(TestMessageBusEventListener.class));
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.getBeanFactory().registerSingleton(MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestMessageBusEventListener listener = (TestMessageBusEventListener) context.getBean("listener");
assertNull(listener.startedBus);
assertNull(listener.stoppedBus);
context.refresh(); // bus will start
assertNotNull(listener.startedBus);
assertNull(listener.stoppedBus);
assertEquals(messageBus, listener.startedBus);
}
@Test
public void messageBusStoppedEvent() {
GenericApplicationContext context = new GenericApplicationContext();
context.registerBeanDefinition("listener", new RootBeanDefinition(TestMessageBusEventListener.class));
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.getBeanFactory().registerSingleton(MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestMessageBusEventListener listener = (TestMessageBusEventListener) context.getBean("listener");
assertNull(listener.startedBus);
assertNull(listener.stoppedBus);
context.refresh();
assertNotNull(listener.startedBus);
assertNull(listener.stoppedBus);
messageBus.stop();
assertNotNull(listener.stoppedBus);
assertEquals(messageBus, listener.stoppedBus);
}
public static class TestMessageBusEventListener implements ApplicationListener {
private volatile ApplicationContextMessageBus startedBus;
private volatile ApplicationContextMessageBus stoppedBus;
public ApplicationContextMessageBus getStartedBus() {
return this.startedBus;
}
public ApplicationContextMessageBus getStoppedBus() {
return this.stoppedBus;
}
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof MessageBusStartedEvent) {
this.startedBus = (ApplicationContextMessageBus) event.getSource();
}
if (event instanceof MessageBusStoppedEvent) {
this.stoppedBus = (ApplicationContextMessageBus) event.getSource();
}
}
}
}

View File

@@ -4,13 +4,9 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bus" class="org.springframework.integration.bus.ApplicationContextMessageBus">
<property name="taskScheduler">
<bean class="org.springframework.integration.util.TestUtils"
factory-method="createTaskScheduler">
<constructor-arg value="10"/>
</bean>
</property>
<bean id="taskScheduler" class="org.springframework.integration.util.TestUtils"
factory-method="createTaskScheduler">
<constructor-arg value="10"/>
</bean>
<bean id="sourceChannel" class="org.springframework.integration.channel.QueueChannel"/>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="bus1" class="org.springframework.integration.bus.ApplicationContextMessageBus"/>
<bean id="bus2" class="org.springframework.integration.bus.ApplicationContextMessageBus"/>
</beans>

View File

@@ -26,11 +26,10 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.endpoint.PollingConsumer;
@@ -39,19 +38,22 @@ import org.springframework.integration.handler.ReplyMessageHolder;
import org.springframework.integration.message.MessageBuilder;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
*/
public class MessageChannelTemplateTests {
private TestApplicationContext context = TestUtils.createTestApplicationContext();
private QueueChannel requestChannel;
@Before
public void setUp() {
this.requestChannel = new QueueChannel();
this.requestChannel.setBeanName("requestChannel");
context.registerChannel("requestChannel", requestChannel);
AbstractReplyProducingMessageHandler handler = new AbstractReplyProducingMessageHandler() {
@Override
public void handleRequestMessage(Message<?> message, ReplyMessageHolder replyHolder) {
@@ -59,17 +61,14 @@ public class MessageChannelTemplateTests {
}
};
PollingConsumer endpoint = new PollingConsumer(requestChannel, handler);
endpoint.afterPropertiesSet();
GenericApplicationContext context = new GenericApplicationContext();
context.getBeanFactory().registerSingleton("requestChannel", requestChannel);
context.getBeanFactory().registerSingleton("testEndpoint", endpoint);
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint", endpoint);
context.refresh();
bus.start();
}
@After
public void tearDown() {
context.stop();
}
@Test
public void send() {

View File

@@ -7,7 +7,7 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">
<message-bus auto-startup="false"/>
<message-bus/>
<channel id="queueChannel">
<queue capacity="10"/>
@@ -17,7 +17,7 @@
<outbound-channel-adapter id="methodInvokingConsumer" ref="testBean" method="store"/>
<inbound-channel-adapter id="methodInvokingSource" ref="testBean" method="getMessage" channel="queueChannel">
<inbound-channel-adapter id="methodInvokingSource" ref="testBean" method="getMessage" channel="queueChannel" auto-startup="false">
<poller max-messages-per-poll="1">
<interval-trigger interval="10000"/>
</poller>

View File

@@ -21,18 +21,19 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.Lifecycle;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.channel.ChannelResolutionException;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
import org.springframework.integration.message.StringMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
@@ -43,13 +44,22 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
@ContextConfiguration
public class ChannelAdapterParserTests extends AbstractJUnit4SpringContextTests {
@Before
public void startContext() {
((AbstractApplicationContext) this.applicationContext).start();
}
@After
public void stopContext() {
((AbstractApplicationContext) this.applicationContext).stop();
}
@Test
public void targetOnly() {
String beanName = "outboundWithImplicitChannel";
Object channel = this.applicationContext.getBean(beanName);
assertTrue(channel instanceof DirectChannel);
Lifecycle bus = (Lifecycle) this.applicationContext.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
bus.start();
BeanFactoryChannelResolver channelResolver = new BeanFactoryChannelResolver(this.applicationContext);
assertNotNull(channelResolver.resolveChannelName(beanName));
Object adapter = this.applicationContext.getBean(beanName + ".adapter");
@@ -61,7 +71,6 @@ public class ChannelAdapterParserTests extends AbstractJUnit4SpringContextTests
assertTrue(((MessageChannel) channel).send(message));
assertNotNull(consumer.getLastMessage());
assertEquals(message, consumer.getLastMessage());
bus.stop();
}
@Test
@@ -69,8 +78,6 @@ public class ChannelAdapterParserTests extends AbstractJUnit4SpringContextTests
String beanName = "methodInvokingConsumer";
Object channel = this.applicationContext.getBean(beanName);
assertTrue(channel instanceof DirectChannel);
Lifecycle bus = (Lifecycle) this.applicationContext.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
bus.start();
BeanFactoryChannelResolver channelResolver = new BeanFactoryChannelResolver(this.applicationContext);
assertNotNull(channelResolver.resolveChannelName(beanName));
Object adapter = this.applicationContext.getBean(beanName + ".adapter");
@@ -82,24 +89,20 @@ public class ChannelAdapterParserTests extends AbstractJUnit4SpringContextTests
assertTrue(((MessageChannel) channel).send(message));
assertNotNull(testBean.getMessage());
assertEquals("consumer test", testBean.getMessage());
bus.stop();
}
@Test
public void methodInvokingSource() {
String beanName = "methodInvokingSource";
PollableChannel channel = (PollableChannel) this.applicationContext.getBean("queueChannel");
Lifecycle bus = (Lifecycle) this.applicationContext.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
bus.start();
TestBean testBean = (TestBean) this.applicationContext.getBean("testBean");
testBean.store("source test");
Object adapter = this.applicationContext.getBean(beanName);
assertNotNull(adapter);
assertTrue(adapter instanceof SourcePollingChannelAdapter);
TestBean testBean = (TestBean) this.applicationContext.getBean("testBean");
testBean.store("source test");
Message<?> message = channel.receive(1000);
assertNotNull(message);
assertEquals("source test", testBean.getMessage());
bus.stop();
}
@Test(expected = ChannelResolutionException.class)

View File

@@ -17,25 +17,16 @@
package org.springframework.integration.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.integration.bus.MessageBusEventTests.TestMessageBusEventListener;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
@@ -60,42 +51,6 @@ public class MessageBusParserTests {
assertEquals(context.getBean("errorChannel"), resolver.resolveChannelName("errorChannel"));
}
@Test
public void testMultipleMessageBusElements() {
boolean exceptionThrown = false;
try {
new ClassPathXmlApplicationContext("multipleMessageBusElements.xml", this.getClass());
}
catch (BeanDefinitionStoreException e) {
exceptionThrown = true;
assertEquals(IllegalStateException.class, e.getCause().getClass());
}
assertTrue(exceptionThrown);
}
@Test
public void testMessageBusElementAndBean() {
boolean exceptionThrown = false;
try {
new ClassPathXmlApplicationContext("messageBusElementAndBean.xml", this.getClass());
}
catch (BeanCreationException e) {
exceptionThrown = true;
assertEquals(IllegalStateException.class, e.getCause().getClass());
assertEquals(e.getBeanName(), MessageBusParser.MESSAGE_BUS_BEAN_NAME);
}
assertTrue(exceptionThrown);
}
@Test
public void testAutoStartup() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"messageBusWithAutoStartup.xml", this.getClass());
Lifecycle bus = (Lifecycle) context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
assertTrue(bus.isRunning());
bus.stop();
}
@Test
public void testMulticasterIsSyncByDefault() {
ApplicationContext context = new ClassPathXmlApplicationContext(
@@ -131,42 +86,4 @@ public class MessageBusParserTests {
assertEquals(ThreadPoolTaskExecutor.class, taskExecutor.getClass());
}
@Test
public void testMessageBusEventListenerReceivesStartedEvent() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"messageBusWithListener.xml", this.getClass());
Lifecycle messageBus = (Lifecycle) context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
TestMessageBusEventListener listener = (TestMessageBusEventListener) context.getBean("listener");
assertNull(listener.getStartedBus());
assertNull(listener.getStoppedBus());
messageBus.start();
assertNotNull(listener.getStartedBus());
assertEquals(messageBus, listener.getStartedBus());
assertNull(listener.getStoppedBus());
}
@Test
public void testMessageBusEventListenerReceivesStoppedEvent() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"messageBusWithListener.xml", this.getClass());
Lifecycle messageBus = (Lifecycle) context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
TestMessageBusEventListener listener = (TestMessageBusEventListener) context.getBean("listener");
assertNull(listener.getStoppedBus());
messageBus.start();
messageBus.stop();
assertNotNull(listener.getStoppedBus());
assertEquals(messageBus, listener.getStoppedBus());
}
@Test
public void testMessageBusWithTaskScheduler() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"messageBusWithTaskScheduler.xml", this.getClass());
Object messageBus = context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
StubTaskScheduler schedulerBean = (StubTaskScheduler) context.getBean("testScheduler");
TaskScheduler busScheduler = (TaskScheduler) new DirectFieldAccessor(messageBus).getPropertyValue("taskScheduler");
assertNotNull(busScheduler);
assertEquals(schedulerBean, busScheduler);
}
}

View File

@@ -25,16 +25,14 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
@@ -44,19 +42,14 @@ public class ServiceActivatorAnnotationPostProcessorTests {
@Test
public void testAnnotatedMethod() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
RootBeanDefinition postProcessorDef = new RootBeanDefinition(MessagingAnnotationPostProcessor.class);
context.registerBeanDefinition("postProcessor", postProcessorDef);
context.registerBeanDefinition("testChannel", new RootBeanDefinition(QueueChannel.class));
RootBeanDefinition beanDefinition = new RootBeanDefinition(SimpleServiceActivatorAnnotationTestBean.class);
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(latch);
context.registerBeanDefinition("testBean", beanDefinition);
String busBeanName = MessageBusParser.MESSAGE_BUS_BEAN_NAME;
RootBeanDefinition busBeanDefinition = new RootBeanDefinition(ApplicationContextMessageBus.class);
busBeanDefinition.getPropertyValues().addPropertyValue("taskScheduler", TestUtils.createTaskScheduler(10));
context.registerBeanDefinition(busBeanName, busBeanDefinition);
RootBeanDefinition postProcessorDef = new RootBeanDefinition(MessagingAnnotationPostProcessor.class);
context.registerBeanDefinition("postProcessor", postProcessorDef);
context.refresh();
context.start();
SimpleServiceActivatorAnnotationTestBean testBean = (SimpleServiceActivatorAnnotationTestBean) context.getBean("testBean");
assertEquals(1, latch.getCount());
assertNull(testBean.getMessageText());

View File

@@ -26,9 +26,9 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
@@ -55,7 +55,7 @@ public class AnnotatedEndpointActivationTests {
private PollableChannel output;
@Autowired
private ApplicationContextMessageBus messageBus;
private AbstractApplicationContext applicationContext;
// This has to be static because the MessageBus registers the handler
// more than once (every time a test instance is created), but only one of
@@ -90,15 +90,15 @@ public class AnnotatedEndpointActivationTests {
}
@Test(expected = MessageDeliveryException.class)
public void stopMessageBus() {
messageBus.stop();
public void stopContext() {
applicationContext.stop();
this.input.send(new GenericMessage<String>("foo"));
}
@Test
public void stopAndRestartMessageBus() {
messageBus.stop();
messageBus.start();
public void stopAndRestartContext() {
applicationContext.stop();
applicationContext.start();
this.input.send(new GenericMessage<String>("foo"));
Message<?> message = this.output.receive(100);
assertNotNull(message);

View File

@@ -28,22 +28,18 @@ import org.junit.Test;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.annotation.ChannelAdapter;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Transformer;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.BeanFactoryChannelResolver;
import org.springframework.integration.channel.ChannelResolver;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.endpoint.PollingConsumer;
@@ -53,6 +49,7 @@ import org.springframework.integration.message.StringMessage;
import org.springframework.integration.scheduling.IntervalTrigger;
import org.springframework.integration.scheduling.Trigger;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
@@ -61,14 +58,9 @@ public class MessagingAnnotationPostProcessorTests {
@Test
public void serviceActivatorAnnotation() {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -131,12 +123,7 @@ public class MessagingAnnotationPostProcessorTests {
@Test
public void targetAnnotation() throws InterruptedException {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
TestApplicationContext context = TestUtils.createTestApplicationContext();
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -144,14 +131,13 @@ public class MessagingAnnotationPostProcessorTests {
OutboundChannelAdapterTestBean testBean = new OutboundChannelAdapterTestBean(latch);
postProcessor.postProcessAfterInitialization(testBean, "testBean");
context.refresh();
messageBus.start();
ChannelResolver channelResolver = new BeanFactoryChannelResolver(context);
MessageChannel testChannel = channelResolver.resolveChannelName("testChannel");
testChannel.send(new StringMessage("foo"));
latch.await(1000, TimeUnit.MILLISECONDS);
assertEquals(0, latch.getCount());
assertEquals("foo", testBean.getMessageText());
messageBus.stop();
context.stop();
}
@Test(expected = IllegalArgumentException.class)
@@ -161,29 +147,13 @@ public class MessagingAnnotationPostProcessorTests {
postProcessor.afterPropertiesSet();
}
@Test(expected = NoSuchBeanDefinitionException.class)
public void testPostProcessorWithoutMessageBus() {
GenericApplicationContext context = new GenericApplicationContext();
MessagingAnnotationPostProcessor postProcessor =
new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
}
@Test
public void testChannelResolution() {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
DirectChannel inputChannel = new DirectChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -195,22 +165,16 @@ public class MessagingAnnotationPostProcessorTests {
inputChannel.send(message);
Message<?> reply = outputChannel.receive(0);
assertNotNull(reply);
context.stop();
}
@Test
public void testProxiedMessageEndpointAnnotation() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -218,53 +182,37 @@ public class MessagingAnnotationPostProcessorTests {
Object proxy = proxyFactory.getProxy();
postProcessor.postProcessAfterInitialization(proxy, "proxy");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("world"));
Message<?> message = outputChannel.receive(1000);
assertEquals("hello world", message.getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testMessageEndpointAnnotationInherited() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
postProcessor.postProcessAfterInitialization(new SimpleAnnotatedEndpointSubclass(), "subclass");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("world"));
Message<?> message = outputChannel.receive(1000);
assertEquals("hello world", message.getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testMessageEndpointAnnotationInheritedWithProxy() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -272,79 +220,55 @@ public class MessagingAnnotationPostProcessorTests {
Object proxy = proxyFactory.getProxy();
postProcessor.postProcessAfterInitialization(proxy, "proxy");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("world"));
Message<?> message = outputChannel.receive(1000);
assertEquals("hello world", message.getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testMessageEndpointAnnotationInheritedFromInterface() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
postProcessor.postProcessAfterInitialization(new SimpleAnnotatedEndpointImplementation(), "impl");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("ABC"));
Message<?> message = outputChannel.receive(1000);
assertEquals("test-ABC", message.getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testMessageEndpointAnnotationInheritedFromInterfaceWithAutoCreatedChannels() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
postProcessor.postProcessAfterInitialization(new SimpleAnnotatedEndpointImplementation(), "impl");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("ABC"));
Message<?> message = outputChannel.receive(1000);
assertEquals("test-ABC", message.getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testMessageEndpointAnnotationInheritedFromInterfaceWithProxy() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel inputChannel = new QueueChannel();
QueueChannel outputChannel = new QueueChannel();
inputChannel.setBeanName("inputChannel");
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("inputChannel", inputChannel);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -352,23 +276,17 @@ public class MessagingAnnotationPostProcessorTests {
Object proxy = proxyFactory.getProxy();
postProcessor.postProcessAfterInitialization(proxy, "proxy");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("ABC"));
Message<?> message = outputChannel.receive(1000);
assertEquals("test-ABC", message.getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testEndpointWithPollerAnnotation() {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
TestApplicationContext context = TestUtils.createTestApplicationContext();
QueueChannel testChannel = new QueueChannel();
testChannel.setBeanName("testChannel");
context.getBeanFactory().registerSingleton("testChannel", testChannel);
messageBus.setApplicationContext(context);
context.registerChannel("testChannel", testChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -385,19 +303,12 @@ public class MessagingAnnotationPostProcessorTests {
@Test
public void testChannelAdapterAnnotation() throws InterruptedException {
GenericApplicationContext context = new GenericApplicationContext();
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
TestApplicationContext context = TestUtils.createTestApplicationContext();
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
ChannelAdapterAnnotationTestBean testBean = new ChannelAdapterAnnotationTestBean();
postProcessor.postProcessAfterInitialization(testBean, "testBean");
context.refresh();
messageBus.start();
ChannelResolver channelResolver = new BeanFactoryChannelResolver(context);
DirectChannel testChannel = (DirectChannel) channelResolver.resolveChannelName("testChannel");
final CountDownLatch latch = new CountDownLatch(1);
@@ -408,26 +319,21 @@ public class MessagingAnnotationPostProcessorTests {
latch.countDown();
}
});
context.refresh();
latch.await(3, TimeUnit.SECONDS);
assertEquals(0, latch.getCount());
assertNotNull(receivedMessage.get());
assertEquals("test", receivedMessage.get().getPayload());
messageBus.stop();
context.stop();
}
@Test
public void testTransformer() {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
DirectChannel inputChannel = new DirectChannel();
inputChannel.setBeanName("inputChannel");
context.getBeanFactory().registerSingleton("inputChannel", inputChannel);
context.registerChannel("inputChannel", inputChannel);
QueueChannel outputChannel = new QueueChannel();
outputChannel.setBeanName("outputChannel");
context.getBeanFactory().registerSingleton("outputChannel", outputChannel);
ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
context.getBeanFactory().registerSingleton(MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("outputChannel", outputChannel);
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
postProcessor.setBeanFactory(context.getBeanFactory());
postProcessor.afterPropertiesSet();
@@ -437,6 +343,7 @@ public class MessagingAnnotationPostProcessorTests {
inputChannel.send(new StringMessage("foo"));
Message<?> reply = outputChannel.receive(0);
assertEquals("FOO", reply.getPayload());
context.stop();
}

View File

@@ -21,25 +21,21 @@ import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.core.Message;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
*/
public class RouterAnnotationPostProcessorTests {
private GenericApplicationContext context = new GenericApplicationContext();
private ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
private TestApplicationContext context = TestUtils.createTestApplicationContext();
private DirectChannel inputChannel = new DirectChannel();
@@ -48,14 +44,8 @@ public class RouterAnnotationPostProcessorTests {
@Before
public void init() {
messageBus.setApplicationContext(context);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
inputChannel.setBeanName("input");
outputChannel.setBeanName("output");
context.getBeanFactory().registerSingleton("input", inputChannel);
context.getBeanFactory().registerSingleton("output", outputChannel);
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
context.registerChannel("input", inputChannel);
context.registerChannel("output", outputChannel);
}
@@ -67,10 +57,10 @@ public class RouterAnnotationPostProcessorTests {
TestRouter testRouter = new TestRouter();
postProcessor.postProcessAfterInitialization(testRouter, "test");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("foo"));
Message<?> replyMessage = outputChannel.receive(0);
assertEquals("foo", replyMessage.getPayload());
context.stop();
}

View File

@@ -23,25 +23,21 @@ import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Splitter;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.config.xml.MessageBusParser;
import org.springframework.integration.core.Message;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
*/
public class SplitterAnnotationPostProcessorTests {
private GenericApplicationContext context = new GenericApplicationContext();
private ApplicationContextMessageBus messageBus = new ApplicationContextMessageBus();
private TestApplicationContext context = TestUtils.createTestApplicationContext();
private DirectChannel inputChannel = new DirectChannel();
@@ -50,14 +46,8 @@ public class SplitterAnnotationPostProcessorTests {
@Before
public void init() {
inputChannel.setBeanName("input");
outputChannel.setBeanName("output");
context.getBeanFactory().registerSingleton("input", inputChannel);
context.getBeanFactory().registerSingleton("output", outputChannel);
context.getBeanFactory().registerSingleton(
MessageBusParser.MESSAGE_BUS_BEAN_NAME, messageBus);
messageBus.setTaskScheduler(TestUtils.createTaskScheduler(10));
messageBus.setApplicationContext(context);
context.registerChannel("input", inputChannel);
context.registerChannel("output", outputChannel);
}
@@ -69,7 +59,6 @@ public class SplitterAnnotationPostProcessorTests {
TestSplitter splitter = new TestSplitter();
postProcessor.postProcessAfterInitialization(splitter, "testSplitter");
context.refresh();
messageBus.start();
inputChannel.send(new StringMessage("this.is.a.test"));
Message<?> message1 = outputChannel.receive(500);
assertNotNull(message1);
@@ -84,7 +73,7 @@ public class SplitterAnnotationPostProcessorTests {
assertNotNull(message4);
assertEquals("test", message4.getPayload());
assertNull(outputChannel.receive(0));
messageBus.stop();
context.stop();
}

View File

@@ -36,6 +36,7 @@ import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessageHeaders;
import org.springframework.integration.message.MessageDeliveryException;
import org.springframework.integration.util.TestUtils;
/**
* @author Iwein Fuld
@@ -59,6 +60,7 @@ public class SimpleMessagingGatewayTests {
this.simpleMessagingGateway = new SimpleMessagingGateway();
this.simpleMessagingGateway.setRequestChannel(requestChannel);
this.simpleMessagingGateway.setReplyChannel(replyChannel);
this.simpleMessagingGateway.setBeanFactory(TestUtils.createTestApplicationContext());
reset(allmocks);
}

View File

@@ -26,14 +26,13 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.bus.ApplicationContextMessageBus;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessagingException;
import org.springframework.integration.endpoint.PollingConsumer;
import org.springframework.integration.handler.MethodInvokingMessageHandler;
import org.springframework.integration.util.TestUtils;
import org.springframework.integration.util.TestUtils.TestApplicationContext;
/**
* @author Mark Fisher
@@ -75,27 +74,22 @@ public class MethodInvokingMessageHandlerTests {
@Test
public void subscription() throws Exception {
GenericApplicationContext context = new GenericApplicationContext();
TestApplicationContext context = TestUtils.createTestApplicationContext();
SynchronousQueue<String> queue = new SynchronousQueue<String>();
TestBean testBean = new TestBean(queue);
QueueChannel channel = new QueueChannel();
channel.setBeanName("channel");
context.getBeanFactory().registerSingleton("channel", channel);
context.registerChannel("channel", channel);
Message<String> message = new GenericMessage<String>("testing");
channel.send(message);
assertNull(queue.poll());
MethodInvokingMessageHandler handler = new MethodInvokingMessageHandler(testBean, "foo");
PollingConsumer endpoint = new PollingConsumer(channel, handler);
context.getBeanFactory().registerSingleton("testEndpoint", endpoint);
ApplicationContextMessageBus bus = new ApplicationContextMessageBus();
bus.setTaskScheduler(TestUtils.createTaskScheduler(10));
bus.setApplicationContext(context);
context.registerEndpoint("testEndpoint", endpoint);
context.refresh();
bus.start();
String result = queue.poll(1000, TimeUnit.MILLISECONDS);
assertNotNull(result);
assertEquals("testing", result);
bus.stop();
context.stop();
}

View File

@@ -19,6 +19,16 @@ package org.springframework.integration.util;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.scheduling.SimpleTaskScheduler;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -56,6 +66,12 @@ public abstract class TestUtils {
return (T) value;
}
public static TestApplicationContext createTestApplicationContext() {
TestApplicationContext context = new TestApplicationContext();
registerBean(IntegrationContextUtils.TASK_SCHEDULER_BEAN_NAME, createTaskScheduler(10), context);
return context;
}
public static TaskScheduler createTaskScheduler(int poolSize) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(poolSize);
@@ -64,4 +80,56 @@ public abstract class TestUtils {
return new SimpleTaskScheduler(executor);
}
private static void registerBean(String beanName, Object bean, BeanFactory beanFactory) {
Assert.notNull(beanName, "bean name must not be null");
ConfigurableListableBeanFactory configurableListableBeanFactory = null;
if (beanFactory instanceof ConfigurableListableBeanFactory) {
configurableListableBeanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
else if (beanFactory instanceof GenericApplicationContext) {
configurableListableBeanFactory = ((GenericApplicationContext) beanFactory).getBeanFactory();
}
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(beanFactory);
}
if (bean instanceof InitializingBean) {
try {
((InitializingBean) bean).afterPropertiesSet();
}
catch (Exception e) {
throw new FatalBeanException("failed to register bean with test context", e);
}
}
configurableListableBeanFactory.registerSingleton(beanName, bean);
}
public static class TestApplicationContext extends GenericApplicationContext {
private TestApplicationContext() {
super();
}
public void registerChannel(String channelName, MessageChannel channel) {
if (channel.getName() != null) {
if (channelName == null) {
Assert.notNull(channel.getName(), "channel name must not be null");
channelName = channel.getName();
}
else {
Assert.isTrue(channel.getName().equals(channelName),
"channel name has already been set with a conflicting value");
}
}
registerBean(channelName, channel, this);
}
public void registerEndpoint(String endpointName, AbstractEndpoint endpoint) {
registerBean(endpointName, endpoint, this);
}
}
}