/* * Copyright 2002-2017 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.config; import java.util.List; import org.aopalliance.aop.Advice; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.framework.Advised; 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.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.integration.context.IntegrationObjectSupport; import org.springframework.integration.context.Orderable; import org.springframework.integration.core.MessageProducer; import org.springframework.integration.handler.AbstractMessageProducingHandler; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.support.context.NamedComponent; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.core.DestinationResolver; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; /** * Factory bean to create and configure a {@link MessageHandler}. * * @author Dave Syer * @author Oleg Zhurakousky * @author Gary Russell * @author Artem Bilan * @author David Liu */ public abstract class AbstractSimpleMessageHandlerFactoryBean<H extends MessageHandler> implements FactoryBean<MessageHandler>, ApplicationContextAware, BeanFactoryAware, BeanNameAware, ApplicationEventPublisherAware { protected final Log logger = LogFactory.getLog(this.getClass()); private volatile H handler; private volatile MessageChannel outputChannel; private volatile Integer order; private BeanFactory beanFactory; private volatile boolean initialized; private final Object initializationMonitor = new Object(); private volatile List<Advice> adviceChain; private volatile String componentName; private ApplicationContext applicationContext; private String beanName; private ApplicationEventPublisher applicationEventPublisher; private DestinationResolver<MessageChannel> channelResolver; private Boolean async; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public void setBeanName(String beanName) { this.beanName = beanName; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * Set the handler's channel resolver. * @param channelResolver the channel resolver to set. */ public void setChannelResolver(DestinationResolver<MessageChannel> channelResolver) { this.channelResolver = channelResolver; } /** * Set the handler's output channel. * @param outputChannel the output channel to set. */ public void setOutputChannel(MessageChannel outputChannel) { this.outputChannel = outputChannel; } /** * Set the order in which the handler will be subscribed to its channel * (when subscribable). * @param order the order to set. */ public void setOrder(Integer order) { this.order = order; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } protected BeanFactory getBeanFactory() { return this.beanFactory; } /** * Set the advice chain to be configured within an * {@link AbstractReplyProducingMessageHandler} to advise just this local endpoint. * For other handlers, the advice chain is applied around the handler itself. * @param adviceChain the adviceChain to set. */ public void setAdviceChain(List<Advice> adviceChain) { this.adviceChain = adviceChain; } /** * Currently only exposed on the service activator * namespace. It's not clear that other endpoints would benefit from async support, * but any subclass of {@link AbstractReplyProducingMessageHandler} can potentially * return a {@code ListenableFuture<?>}. * @param async the async to set. * @since 4.3 */ public void setAsync(Boolean async) { this.async = async; } /** * Sets the name of the handler component. * * @param componentName The component name. */ public void setComponentName(String componentName) { this.componentName = componentName; } @Override public H getObject() throws Exception { if (this.handler == null) { this.handler = this.createHandlerInternal(); Assert.notNull(this.handler, "failed to create MessageHandler"); } return this.handler; } protected final H createHandlerInternal() { synchronized (this.initializationMonitor) { if (this.initialized) { // There was a problem when this method was called already return null; } this.handler = createHandler(); if (this.handler instanceof ApplicationContextAware && this.applicationContext != null) { ((ApplicationContextAware) this.handler).setApplicationContext(this.applicationContext); } if (this.handler instanceof BeanFactoryAware && getBeanFactory() != null) { ((BeanFactoryAware) this.handler).setBeanFactory(getBeanFactory()); } if (this.handler instanceof BeanNameAware && this.beanName != null) { ((BeanNameAware) this.handler).setBeanName(this.beanName); } if (this.handler instanceof ApplicationEventPublisherAware && this.applicationEventPublisher != null) { ((ApplicationEventPublisherAware) this.handler) .setApplicationEventPublisher(this.applicationEventPublisher); } if (this.handler instanceof MessageProducer && this.outputChannel != null) { ((MessageProducer) this.handler).setOutputChannel(this.outputChannel); } Object actualHandler = extractTarget(this.handler); if (actualHandler == null) { actualHandler = this.handler; } if (actualHandler instanceof IntegrationObjectSupport) { if (this.componentName != null) { ((IntegrationObjectSupport) actualHandler).setComponentName(this.componentName); } if (this.channelResolver != null) { ((IntegrationObjectSupport) actualHandler).setChannelResolver(this.channelResolver); } } if (!CollectionUtils.isEmpty(this.adviceChain)) { if (actualHandler instanceof AbstractReplyProducingMessageHandler) { ((AbstractReplyProducingMessageHandler) actualHandler).setAdviceChain(this.adviceChain); } else if (this.logger.isDebugEnabled()) { String name = this.componentName; if (name == null && actualHandler instanceof NamedComponent) { name = ((NamedComponent) actualHandler).getComponentName(); } this.logger.debug("adviceChain can only be set on an AbstractReplyProducingMessageHandler" + (name == null ? "" : (", " + name)) + "."); } } if (this.async != null) { if (actualHandler instanceof AbstractMessageProducingHandler) { ((AbstractMessageProducingHandler) actualHandler) .setAsync(this.async); } } if (this.handler instanceof Orderable && this.order != null) { ((Orderable) this.handler).setOrder(this.order); } this.initialized = true; } if (this.handler instanceof InitializingBean) { try { ((InitializingBean) this.handler).afterPropertiesSet(); } catch (Exception e) { throw new BeanInitializationException("failed to initialize MessageHandler", e); } } return this.handler; } protected abstract H createHandler(); @Override public Class<? extends MessageHandler> getObjectType() { if (this.handler != null) { return this.handler.getClass(); } return getPreCreationHandlerType(); } /** * Subclasses can override this to return a more specific type before handler creation. * After handler creation, the actual type is used. * @return the type. */ protected Class<? extends MessageHandler> getPreCreationHandlerType() { return MessageHandler.class; } @Override public boolean isSingleton() { return true; } private Object extractTarget(Object object) { if (!(object instanceof Advised)) { return object; } Advised advised = (Advised) object; if (advised.getTargetSource() == null) { return null; } try { return extractTarget(advised.getTargetSource().getTarget()); } catch (Exception e) { this.logger.error("Could not extract target", e); return null; } } }