org.springframework.integration.filter.MessageFilter.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.integration.filter.MessageFilter.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.filter;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.Lifecycle;
import org.springframework.core.convert.ConversionService;
import org.springframework.integration.MessageRejectedException;
import org.springframework.integration.core.MessageSelector;
import org.springframework.integration.handler.AbstractReplyProducingPostProcessingMessageHandler;
import org.springframework.integration.handler.DiscardingMessageHandler;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.util.Assert;

/**
 * Message Handler that delegates to a {@link MessageSelector}. If and only if
 * the selector {@link MessageSelector#accept(Message) accepts} the Message, it
 * will be passed to this filter's output channel. Otherwise the message will
 * either be silently dropped (the default) or will trigger the throwing of a
 * {@link MessageRejectedException} depending on the value of its
 * {@link #throwExceptionOnRejection} property. If a discard channel is
 * provided, the rejected Messages will be sent to that channel.
 *
 * @author Mark Fisher
 * @author Oleg Zhurakousky
 * @author Gary Russell
 * @author Artem Bilan
 * @author David Liu
 */
public class MessageFilter extends AbstractReplyProducingPostProcessingMessageHandler
        implements DiscardingMessageHandler, Lifecycle {

    private final MessageSelector selector;

    private boolean throwExceptionOnRejection;

    private MessageChannel discardChannel;

    private String discardChannelName;

    /**
     * Create a MessageFilter that will delegate to the given {@link MessageSelector}.
     * @param selector The message selector.
     */
    public MessageFilter(MessageSelector selector) {
        Assert.notNull(selector, "selector must not be null");
        this.selector = selector;
    }

    /**
     * Specify whether this filter should throw a
     * {@link MessageRejectedException} when its selector does not accept a
     * Message. The default value is <code>false</code> meaning that rejected
     * Messages will be quietly dropped or sent to the discard channel if
     * available. Typically this value would not be <code>true</code> when
     * a discard channel is provided, but if so, it will still apply
     * (in such a case, the Message will be sent to the discard channel,
     * and <em>then</em> the exception will be thrown).
     * @param throwExceptionOnRejection true if an exception should be thrown.
     * @see #setDiscardChannel(MessageChannel)
     */
    public void setThrowExceptionOnRejection(boolean throwExceptionOnRejection) {
        this.throwExceptionOnRejection = throwExceptionOnRejection;
    }

    /**
     * Specify a channel where rejected Messages should be sent. If the discard
     * channel is null (the default), rejected Messages will be dropped. However,
     * the 'throwExceptionOnRejection' flag determines whether rejected Messages
     * trigger an exception. That value is evaluated regardless of the presence
     * of a discard channel.
     * @param discardChannel The discard channel.
     * @see #setThrowExceptionOnRejection(boolean)
     */
    public void setDiscardChannel(MessageChannel discardChannel) {
        this.discardChannel = discardChannel;
    }

    public void setDiscardChannelName(String discardChannelName) {
        Assert.hasText(discardChannelName, "'discardChannelName' must not be empty");
        this.discardChannelName = discardChannelName;
    }

    /**
     * Set to 'true' if you wish the discard processing to occur within any
     * request handler advice applied to this filter. Also applies to
     * throwing an exception on rejection. Default: true.
     * @param discardWithinAdvice true to discard within the advice.
     */
    public void setDiscardWithinAdvice(boolean discardWithinAdvice) {
        this.setPostProcessWithinAdvice(discardWithinAdvice);
    }

    @Override
    public MessageChannel getDiscardChannel() {
        String channelName = this.discardChannelName;
        if (channelName != null) {
            this.discardChannel = getChannelResolver().resolveDestination(channelName);
            this.discardChannelName = null;
        }
        return this.discardChannel;
    }

    @Override
    public String getComponentType() {
        return "filter";
    }

    @Override
    protected void doInit() {
        Assert.state(!(this.discardChannelName != null && this.discardChannel != null),
                "'discardChannelName' and 'discardChannel' are mutually exclusive.");
        if (this.selector instanceof AbstractMessageProcessingSelector) {
            ConversionService conversionService = getConversionService();
            if (conversionService != null) {
                ((AbstractMessageProcessingSelector) this.selector).setConversionService(conversionService);
            }
        }
        BeanFactory beanFactory = getBeanFactory();
        if (this.selector instanceof BeanFactoryAware && beanFactory != null) {
            ((BeanFactoryAware) this.selector).setBeanFactory(beanFactory);
        }
    }

    @Override
    public void start() {
        if (this.selector instanceof Lifecycle) {
            ((Lifecycle) this.selector).start();
        }
    }

    @Override
    public void stop() {
        if (this.selector instanceof Lifecycle) {
            ((Lifecycle) this.selector).stop();
        }
    }

    @Override
    public boolean isRunning() {
        return !(this.selector instanceof Lifecycle) || ((Lifecycle) this.selector).isRunning();
    }

    @Override
    protected Object doHandleRequestMessage(Message<?> message) {
        if (this.selector.accept(message)) {
            return message;
        } else {
            return null;
        }
    }

    @Override
    public Object postProcess(Message<?> message, Object result) {
        if (result == null) {
            MessageChannel channel = getDiscardChannel();
            if (channel != null) {
                this.messagingTemplate.send(channel, message);
            }
            if (this.throwExceptionOnRejection) {
                throw new MessageRejectedException(message, "message has been rejected in filter: " + this);
            }
        }
        return result;
    }

    @Override
    protected boolean shouldCopyRequestHeaders() {
        return false;
    }

}