org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean.java

Source

/*
 * 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;
        }
    }

}