The TaskScheduler for the MessageBus is now created in MessageBusParser if no explicit reference has been provided via the "task-executor" attribute of the <message-bus/> element. The configuration of an asynchronous ApplicationEventMulticaster has also been pushed to the parser rather than being contained within the MessageBus implementation.

This commit is contained in:
Mark Fisher
2008-10-09 13:45:07 +00:00
parent 977596272c
commit 49361dba5c
15 changed files with 161 additions and 146 deletions

View File

@@ -34,21 +34,17 @@ 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.ApplicationEventMulticaster;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.channel.ChannelRegistryAware;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.channel.MessagePublishingErrorHandler;
import org.springframework.integration.endpoint.MessageEndpoint;
import org.springframework.integration.endpoint.MessagingGateway;
import org.springframework.integration.scheduling.Schedulers;
import org.springframework.integration.scheduling.SimpleTaskScheduler;
import org.springframework.integration.scheduling.TaskScheduler;
import org.springframework.integration.scheduling.TaskSchedulerAware;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.util.Assert;
/**
@@ -60,8 +56,6 @@ import org.springframework.util.Assert;
*/
public class DefaultMessageBus implements MessageBus, ApplicationContextAware, ApplicationListener, DisposableBean {
private static final int DEFAULT_DISPATCHER_POOL_SIZE = 10;
private final Log logger = LogFactory.getLog(this.getClass());
private final Map<String, MessageChannel> channels = new ConcurrentHashMap<String, MessageChannel>();
@@ -76,8 +70,6 @@ public class DefaultMessageBus implements MessageBus, ApplicationContextAware, A
private volatile ApplicationContext applicationContext;
private volatile boolean configureAsyncEventMulticaster = false;
private volatile boolean autoStartup = true;
private volatile boolean initialized;
@@ -112,17 +104,6 @@ public class DefaultMessageBus implements MessageBus, ApplicationContextAware, A
this.autoStartup = autoStartup;
}
/**
* Set whether the bus should configure its asynchronous task executor
* to also be used by the ApplicationContext's 'applicationEventMulticaster'.
* This will only apply if the multicaster defined within the context
* is an instance of SimpleApplicationEventMulticaster (the default).
* This property is 'false' by default.
*/
public void setConfigureAsyncEventMulticaster(boolean configureAsyncEventMulticaster) {
this.configureAsyncEventMulticaster = configureAsyncEventMulticaster;
}
@SuppressWarnings("unchecked")
private void registerChannels(ApplicationContext context) {
Map<String, MessageChannel> channelBeans = (Map<String, MessageChannel>) context
@@ -155,9 +136,9 @@ public class DefaultMessageBus implements MessageBus, ApplicationContextAware, A
return;
}
Assert.notNull(this.applicationContext, "ApplicationContext must not be null");
//TODO: Assert.notNull(this.taskScheduler, "TaskScheduler must not be null");
if (this.taskScheduler == null) {
this.taskScheduler = Schedulers.createDefaultTaskExecutor(DEFAULT_DISPATCHER_POOL_SIZE,
new CustomizableThreadFactory("message-bus-"));
this.taskScheduler = new SimpleTaskScheduler(new SimpleAsyncTaskExecutor());
}
if (this.getErrorChannel() == null) {
this.registerChannel(new DefaultErrorChannel());
@@ -339,27 +320,12 @@ public class DefaultMessageBus implements MessageBus, ApplicationContextAware, A
ApplicationContext context = ((ContextRefreshedEvent) event).getApplicationContext();
this.registerChannels(context);
this.registerGateways(context);
if (this.configureAsyncEventMulticaster) {
this.initialize();
this.doConfigureAsyncEventMulticaster(context);
}
if (this.autoStartup) {
this.start();
}
}
}
private void doConfigureAsyncEventMulticaster(ApplicationContext context) {
String multicasterBeanName = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME;
if (context.containsBean(multicasterBeanName)) {
ApplicationEventMulticaster multicaster = (ApplicationEventMulticaster) context
.getBean(multicasterBeanName);
if (multicaster instanceof SimpleApplicationEventMulticaster) {
((SimpleApplicationEventMulticaster) multicaster).setTaskExecutor(this.taskScheduler);
}
}
}
public void addInterceptor(MessageBusInterceptor interceptor) {
this.interceptors.add(interceptor);
}

View File

@@ -16,26 +16,38 @@
package org.springframework.integration.config;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
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.ManagedList;
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.DefaultMessageBus;
import org.springframework.integration.bus.MessageBus;
import org.springframework.integration.bus.MessageBusAwareBeanPostProcessor;
import org.springframework.integration.config.annotation.MessagingAnnotationPostProcessor;
import org.springframework.integration.config.annotation.PublisherAnnotationPostProcessor;
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;
/**
* Parser for the &lt;message-bus&gt; element of the integration namespace.
@@ -56,6 +68,10 @@ public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
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)
@@ -72,15 +88,49 @@ public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected boolean isEligibleAttribute(String attributeName) {
return !"task-scheduler".equals(attributeName) &&
return !TASK_SCHEDULER_ATTRIBUTE.equals(attributeName) &&
!ASYNC_EVENT_MULTICASTER_ATTRIBUTE.equals(attributeName) &&
!"enable-annotations".equals(attributeName) &&
super.isEligibleAttribute(attributeName);
}
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "task-scheduler");
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 (StringUtils.hasText(taskSchedulerRef)) {
builder.addPropertyReference("taskScheduler", taskSchedulerRef);
}
else {
taskExecutor = this.createTaskExecutor(100, "message-bus-");
builder.addPropertyValue("taskScheduler", new SimpleTaskScheduler(taskExecutor));
}
if ("true".equals(element.getAttribute(ASYNC_EVENT_MULTICASTER_ATTRIBUTE).toLowerCase())) {
if (taskExecutor == null) {
taskExecutor = this.createTaskExecutor(10, "event-multicaster-");
}
BeanDefinitionBuilder eventMulticasterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
SimpleApplicationEventMulticaster.class);
eventMulticasterBuilder.addPropertyValue("taskExecutor", taskExecutor);
eventMulticasterBuilder.addPropertyValue("collectionClass", CopyOnWriteArraySet.class);
BeanDefinitionHolder holder = new BeanDefinitionHolder(eventMulticasterBuilder.getBeanDefinition(),
AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
}
this.processChildElements(builder, element);
this.addPostProcessors(element, parserContext);
}
private TaskExecutor createTaskExecutor(int corePoolSize, String threadPrefix) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
if (StringUtils.hasText(threadPrefix)) {
executor.setThreadFactory(new CustomizableThreadFactory(threadPrefix));
}
executor.setRejectedExecutionHandler(new CallerRunsPolicy());
executor.afterPropertiesSet();
return executor;
}
@SuppressWarnings("unchecked")
@@ -100,12 +150,6 @@ public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
}
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
this.addPostProcessors(element, parserContext);
}
/**
* Adds extra post-processors to the context, to inject the objects configured by the MessageBus
*/

View File

@@ -20,7 +20,7 @@
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a message bus.
Defines the Message Bus for this Application Context.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>

View File

@@ -1,43 +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.scheduling;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* Helper class for creating predefined {@link TaskScheduler} classes.
*
* @author Marius Bogoevici
*/
public class Schedulers {
public static TaskScheduler createDefaultTaskExecutor(int poolSize, ThreadFactory threadFactory) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(poolSize);
executor.setThreadFactory(threadFactory);
executor.setRejectedExecutionHandler(new CallerRunsPolicy());
executor.afterPropertiesSet();
return new SimpleTaskScheduler(executor);
}
public static TaskScheduler createDefaultTaskScheduler(int poolSize) {
return createDefaultTaskExecutor(poolSize, null);
}
}

View File

@@ -19,7 +19,6 @@ package org.springframework.integration.scheduling;
import java.util.concurrent.ScheduledFuture;
import org.springframework.context.Lifecycle;
import org.springframework.scheduling.SchedulingTaskExecutor;
/**
* Base interface for scheduling messaging tasks.
@@ -27,7 +26,7 @@ import org.springframework.scheduling.SchedulingTaskExecutor;
* @author Mark Fisher
* @author Marius Bogoevici
*/
public interface TaskScheduler extends SchedulingTaskExecutor, Lifecycle {
public interface TaskScheduler extends Lifecycle {
ScheduledFuture<?> schedule(Runnable task, Trigger trigger);