/* * 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 org.springframework.expression.Expression; import org.springframework.integration.handler.AbstractMessageProducingHandler; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor; import org.springframework.integration.handler.MessageProcessor; import org.springframework.integration.handler.ReplyProducingMessageHandlerWrapper; import org.springframework.integration.handler.ServiceActivatingHandler; import org.springframework.messaging.MessageHandler; import org.springframework.util.StringUtils; /** * FactoryBean for creating {@link ServiceActivatingHandler} instances. * * @author Mark Fisher * @author Gary Russell * @author David Liu * @author Artem Bilan * * @since 2.0 */ public class ServiceActivatorFactoryBean extends AbstractStandardMessageHandlerFactoryBean { private volatile Long sendTimeout; private volatile Boolean requiresReply; public void setSendTimeout(Long sendTimeout) { this.sendTimeout = sendTimeout; } public void setRequiresReply(Boolean requiresReply) { this.requiresReply = requiresReply; } @Override protected MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) { MessageHandler handler = null; handler = createDirectHandlerIfPossible(targetObject, targetMethodName); if (handler == null) { handler = configureHandler( StringUtils.hasText(targetMethodName) ? new ServiceActivatingHandler(targetObject, targetMethodName) : new ServiceActivatingHandler(targetObject)); } return handler; } /** * If the target object is a {@link MessageHandler} and the method is 'handleMessage', return an * {@link AbstractMessageProducingHandler} that wraps it. * @param targetObject the object to check for Direct Handler requirements. * @param targetMethodName the method name to check for Direct Handler requirements. * @return the {@code targetObject} as a Direct {@link MessageHandler} or {@code null}. */ protected MessageHandler createDirectHandlerIfPossible(final Object targetObject, String targetMethodName) { MessageHandler handler = null; if (targetObject instanceof MessageHandler && this.methodIsHandleMessageOrEmpty(targetMethodName)) { if (targetObject instanceof AbstractMessageProducingHandler) { // should never happen but just return it if it's already an AMPH return (MessageHandler) targetObject; } /* * Return a reply-producing message handler so that we still get 'produced no reply' messages * and the super class will inject the advice chain to advise the handler method if needed. */ handler = new ReplyProducingMessageHandlerWrapper((MessageHandler) targetObject); } return handler; } @Override protected MessageHandler createExpressionEvaluatingHandler(Expression expression) { ExpressionEvaluatingMessageProcessor<Object> processor = new ExpressionEvaluatingMessageProcessor<Object>(expression); processor.setBeanFactory(this.getBeanFactory()); ServiceActivatingHandler handler = new ServiceActivatingHandler(processor); handler.setPrimaryExpression(expression); return this.configureHandler(handler); } @Override protected <T> MessageHandler createMessageProcessingHandler(MessageProcessor<T> processor) { return this.configureHandler(new ServiceActivatingHandler(processor)); } protected MessageHandler configureHandler(ServiceActivatingHandler handler) { postProcessReplyProducer(handler); return handler; } /** * Always returns true - any {@link AbstractMessageProducingHandler} can * be used directly. */ @Override protected boolean canBeUsedDirect(AbstractMessageProducingHandler handler) { return true; } @Override protected void postProcessReplyProducer(AbstractMessageProducingHandler handler) { if (this.sendTimeout != null) { handler.setSendTimeout(this.sendTimeout); } if (this.requiresReply != null) { if (handler instanceof AbstractReplyProducingMessageHandler) { ((AbstractReplyProducingMessageHandler) handler).setRequiresReply(this.requiresReply); } else { if (this.requiresReply && logger.isDebugEnabled()) { logger.debug("requires-reply can only be set to AbstractReplyProducingMessageHandler or its subclass, " + handler.getComponentName() + " doesn't support it."); } } } } }