org.springframework.integration.handler.AbstractReplyProducingMessageHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.handler.AbstractReplyProducingMessageHandler.java

Source

/*
 * Copyright 2002-2019 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
 *
 *      https://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.handler;

import java.util.LinkedList;
import java.util.List;

import org.aopalliance.aop.Advice;

import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.integration.handler.advice.HandleMessageAdvice;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * Base class for MessageHandlers that are capable of producing replies.
 *
 * @author Mark Fisher
 * @author Iwein Fuld
 * @author Oleg Zhurakousky
 * @author Gary Russell
 * @author Artem Bilan
 * @author David Liu
 */
public abstract class AbstractReplyProducingMessageHandler extends AbstractMessageProducingHandler
        implements BeanClassLoaderAware {

    private final List<Advice> adviceChain = new LinkedList<>();

    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    private boolean requiresReply = false;

    private volatile RequestHandler advisedRequestHandler;

    /**
     * Flag whether a reply is required. If true an incoming message MUST result in a reply message being sent.
     * If false an incoming message MAY result in a reply message being sent. Default is false.
     * @param requiresReply true if a reply is required.
     */
    public void setRequiresReply(boolean requiresReply) {
        this.requiresReply = requiresReply;
    }

    protected boolean getRequiresReply() {
        return this.requiresReply;
    }

    /**
     * Configure a list of {@link Advice}s to proxy a {@link #handleRequestMessage(Message)} method.
     * @param adviceChain the list of {@link Advice}s to use.
     */
    public void setAdviceChain(List<Advice> adviceChain) {
        Assert.notEmpty(adviceChain, "adviceChain cannot be empty");
        synchronized (this.adviceChain) {
            this.adviceChain.clear();
            this.adviceChain.addAll(adviceChain);
            if (isInitialized()) {
                initAdvisedRequestHandlerIfAny();
            }
        }
    }

    protected boolean hasAdviceChain() {
        return this.adviceChain.size() > 0;
    }

    @Override
    public void setBeanClassLoader(ClassLoader beanClassLoader) {
        this.beanClassLoader = beanClassLoader;
    }

    protected ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }

    @Override
    protected final void onInit() {
        super.onInit();
        initAdvisedRequestHandlerIfAny();
        doInit();
    }

    private void initAdvisedRequestHandlerIfAny() {
        if (!this.adviceChain.isEmpty()) {
            ProxyFactory proxyFactory = new ProxyFactory(new AdvisedRequestHandler());
            boolean advised = false;
            for (Advice advice : this.adviceChain) {
                if (!(advice instanceof HandleMessageAdvice)) {
                    proxyFactory.addAdvice(advice);
                    advised = true;
                }
            }
            if (advised) {
                this.advisedRequestHandler = (RequestHandler) proxyFactory.getProxy(this.beanClassLoader);
            }
        }
    }

    protected void doInit() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final void handleMessageInternal(Message<?> message) {
        Object result;
        if (this.advisedRequestHandler == null) {
            result = handleRequestMessage(message);
        } else {
            result = doInvokeAdvisedRequestHandler(message);
        }
        if (result != null) {
            sendOutputs(result, message);
        } else if (this.requiresReply && !isAsync()) {
            throw new ReplyRequiredException(message, "No reply produced by handler '" + getComponentName()
                    + "', and its 'requiresReply' property is set to true.");
        } else if (!isAsync() && logger.isDebugEnabled()) {
            logger.debug("handler '" + this + "' produced no reply for request Message: " + message);
        }
    }

    @Nullable
    protected Object doInvokeAdvisedRequestHandler(Message<?> message) {
        return this.advisedRequestHandler.handleRequestMessage(message);
    }

    /**
     * Subclasses must implement this method to handle the request Message. The return
     * value may be a Message, a MessageBuilder, or any plain Object. The base class
     * will handle the final creation of a reply Message from any of those starting
     * points. If the return value is null, the Message flow will end here.
     * @param requestMessage The request message.
     * @return The result of handling the message, or {@code null}.
     */
    @Nullable
    protected abstract Object handleRequestMessage(Message<?> requestMessage);

    /**
     * An implementation of this interface is used to wrap the
     * {@link AbstractReplyProducingMessageHandler#handleRequestMessage(Message)}
     * method. Also allows access to the underlying
     * {@link AbstractReplyProducingMessageHandler} to obtain properties.
     *
     * @author Gary Russell
     * @since 2.2
     *
     * @see #getAdvisedHandler()
     *
     */
    public interface RequestHandler {

        @Nullable
        Object handleRequestMessage(Message<?> requestMessage);

        /**
         * Utility method, intended for use in message handler advice classes to get
         * information about the advised object. For example:
         * <p>
         * {@code ((AbstractReplyProducingMessageHandler.RequestHandler)
         * invocation.getThis()).getAdvisedHandler().getComponentName()}
         * @return the outer class instance.
         *
         * @since 4.3.2
         */
        AbstractReplyProducingMessageHandler getAdvisedHandler();

    }

    private class AdvisedRequestHandler implements RequestHandler {

        AdvisedRequestHandler() {
            super();
        }

        @Override
        @Nullable
        public Object handleRequestMessage(Message<?> requestMessage) {
            return AbstractReplyProducingMessageHandler.this.handleRequestMessage(requestMessage);
        }

        @Override
        public String toString() {
            return AbstractReplyProducingMessageHandler.this.toString();
        }

        @Override
        public AbstractReplyProducingMessageHandler getAdvisedHandler() {
            return AbstractReplyProducingMessageHandler.this;
        }

    }

}