MessageHandlingException consistency

* Use `IntegrationUtils.wrapInHandlingExceptionIfNecessary()` whenever
it is possible to avoid double wrapping into the `MessageHandlingException`
* Some code polishing for affected classes `@Nullable`, streams, diamonds etc.
This commit is contained in:
Artem Bilan
2019-02-21 17:39:20 -05:00
committed by Gary Russell
parent 9c84eceec2
commit 221393e02f
35 changed files with 354 additions and 301 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.integration.core;
import org.springframework.lang.Nullable;
import org.springframework.messaging.MessageChannel;
/**
@@ -49,6 +50,7 @@ public interface MessageProducer {
* @return the channel.
* @since 4.3
*/
@Nullable
MessageChannel getOutputChannel();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2018 the original author or authors.
* Copyright 2018-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.
@@ -20,9 +20,9 @@ import org.springframework.integration.StaticMessageHeaderAccessor;
import org.springframework.integration.acks.AckUtils;
import org.springframework.integration.acks.AcknowledgmentCallback;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.util.Assert;
/**
@@ -56,7 +56,9 @@ public class MessageSourcePollingTemplate implements PollingOperations {
}
catch (Exception e) {
AckUtils.autoNack(ackCallback);
throw new MessageHandlingException(message, e);
throw IntegrationUtils.wrapInHandlingExceptionIfNecessary(message,
() -> "error occurred during handling message in 'MessageSourcePollingTemplate' ["
+ this + "]", e);
}
return true;
}

View File

@@ -33,6 +33,7 @@ import org.springframework.integration.support.management.MessageHandlerMetrics;
import org.springframework.integration.support.management.MetricsContext;
import org.springframework.integration.support.management.Statistics;
import org.springframework.integration.support.management.TrackableComponent;
import org.springframework.integration.support.management.metrics.MeterFacade;
import org.springframework.integration.support.management.metrics.MetricsCaptor;
import org.springframework.integration.support.management.metrics.SampleFacade;
import org.springframework.integration.support.management.metrics.TimerFacade;
@@ -338,7 +339,7 @@ public abstract class AbstractMessageHandler extends IntegrationObjectSupport
@Override
public void destroy() throws Exception {
this.timers.forEach(t -> t.remove());
this.timers.forEach(MeterFacade::remove);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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.
@@ -17,6 +17,7 @@
package org.springframework.integration.handler;
import org.springframework.integration.util.AbstractExpressionEvaluator;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
/**
@@ -28,6 +29,7 @@ import org.springframework.messaging.Message;
*/
public abstract class AbstractMessageProcessor<T> extends AbstractExpressionEvaluator implements MessageProcessor<T> {
@Nullable
public abstract T processMessage(Message<?> message);
}

View File

@@ -68,8 +68,10 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
private boolean async;
@Nullable
private String outputChannelName;
@Nullable
private MessageChannel outputChannel;
private String[] notPropagatedHeaders;
@@ -205,6 +207,7 @@ public abstract class AbstractMessageProducingHandler extends AbstractMessageHan
}
@Override
@Nullable
public MessageChannel getOutputChannel() {
if (this.outputChannelName != null) {
this.outputChannel = getChannelResolver().resolveDestination(this.outputChannelName);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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.
@@ -24,6 +24,7 @@ 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;
@@ -137,6 +138,7 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
}
}
@Nullable
protected Object doInvokeAdvisedRequestHandler(Message<?> message) {
return this.advisedRequestHandler.handleRequestMessage(message);
}
@@ -149,6 +151,7 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
* @param requestMessage The request message.
* @return The result of handling the message, or {@code null}.
*/
@Nullable
protected abstract Object handleRequestMessage(Message<?> requestMessage);
@@ -166,6 +169,7 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
*/
public interface RequestHandler {
@Nullable
Object handleRequestMessage(Message<?> requestMessage);
/**
@@ -189,6 +193,7 @@ public abstract class AbstractReplyProducingMessageHandler extends AbstractMessa
}
@Override
@Nullable
public Object handleRequestMessage(Message<?> requestMessage) {
return AbstractReplyProducingMessageHandler.this.handleRequestMessage(requestMessage);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -16,10 +16,13 @@
package org.springframework.integration.handler;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
/**
* @author Gary Russell
* @author Artem Bilan
*
* @since 3.0
*
*/
@@ -42,6 +45,7 @@ public abstract class AbstractReplyProducingPostProcessingMessageHandler
}
@Override
@Nullable
protected final Object handleRequestMessage(Message<?> requestMessage) {
Object result = this.doHandleRequestMessage(requestMessage);
if (this.postProcessWithinAdvice || !this.hasAdviceChain()) {
@@ -51,6 +55,7 @@ public abstract class AbstractReplyProducingPostProcessingMessageHandler
}
@Override
@Nullable
protected final Object doInvokeAdvisedRequestHandler(Message<?> message) {
Object result = super.doInvokeAdvisedRequestHandler(message);
if (!this.postProcessWithinAdvice) {
@@ -59,6 +64,7 @@ public abstract class AbstractReplyProducingPostProcessingMessageHandler
return result;
}
@Nullable
protected abstract Object doHandleRequestMessage(Message<?> requestMessage);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2017 the original author or authors.
* Copyright 2016-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.
@@ -19,8 +19,8 @@ package org.springframework.integration.handler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
/**
* An "artificial" {@link MessageProcessor} for lazy-load of target bean by its name.
@@ -29,6 +29,7 @@ import org.springframework.util.Assert;
* @param <T> the expected {@link #processMessage} result type.
*
* @author Artem Bilan
*
* @since 5.0
*/
public class BeanNameMessageProcessor<T> implements MessageProcessor<T>, BeanFactoryAware {
@@ -48,11 +49,11 @@ public class BeanNameMessageProcessor<T> implements MessageProcessor<T>, BeanFac
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
Assert.notNull(beanFactory, "'beanFactory' must not be null");
this.beanFactory = beanFactory;
}
@Override
@Nullable
public T processMessage(Message<?> message) {
if (this.delegate == null) {
Object target = this.beanFactory.getBean(this.beanName);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016 the original author or authors.
* Copyright 2016-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.
@@ -16,6 +16,7 @@
package org.springframework.integration.handler;
import org.springframework.lang.Nullable;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
@@ -32,6 +33,7 @@ public interface DiscardingMessageHandler extends MessageHandler {
* Return the discard channel.
* @return the channel.
*/
@Nullable
MessageChannel getDiscardChannel();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -31,7 +31,9 @@ import org.springframework.expression.MethodExecutor;
import org.springframework.expression.MethodFilter;
import org.springframework.expression.MethodResolver;
import org.springframework.expression.spel.support.ReflectiveMethodResolver;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.util.CollectionUtils;
/**
* A MessageProcessor implementation that expects an Expression or expressionString
@@ -40,6 +42,8 @@ import org.springframework.messaging.Message;
* @author Dave Syer
* @author Mark Fisher
* @author Gary Russell
* @author Artem Bilan
*
* @since 2.0
*/
public class ExpressionCommandMessageProcessor extends AbstractMessageProcessor<Object> {
@@ -47,26 +51,31 @@ public class ExpressionCommandMessageProcessor extends AbstractMessageProcessor<
public ExpressionCommandMessageProcessor() {
}
public ExpressionCommandMessageProcessor(MethodFilter methodFilter) {
public ExpressionCommandMessageProcessor(@Nullable MethodFilter methodFilter) {
this(methodFilter, null);
}
public ExpressionCommandMessageProcessor(MethodFilter methodFilter, BeanFactory beanFactory) {
public ExpressionCommandMessageProcessor(@Nullable MethodFilter methodFilter, @Nullable BeanFactory beanFactory) {
if (beanFactory != null) {
this.setBeanFactory(beanFactory);
setBeanFactory(beanFactory);
}
if (methodFilter != null) {
MethodResolver methodResolver = new ExpressionCommandMethodResolver(methodFilter);
this.getEvaluationContext(false).setMethodResolvers(Collections.singletonList(methodResolver));
getEvaluationContext(false).setMethodResolvers(Collections.singletonList(methodResolver));
}
}
@Override
public final void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
}
/**
* Evaluates the Message payload expression as a command.
* @throws IllegalArgumentException if the payload is not an Exception or String
*/
@Override
@Nullable
public Object processMessage(Message<?> message) {
Object expression = message.getPayload();
if (expression instanceof Expression) {
@@ -91,18 +100,17 @@ public class ExpressionCommandMessageProcessor extends AbstractMessageProcessor<
@Override
public MethodExecutor resolve(EvaluationContext context,
Object targetObject, String name, List<TypeDescriptor> argumentTypes) throws AccessException {
this.validateMethod(targetObject, name, (argumentTypes != null ? argumentTypes.size() : 0));
Object targetObject, String name, List<TypeDescriptor> argumentTypes)
throws AccessException {
validateMethod(targetObject, name, !CollectionUtils.isEmpty(argumentTypes) ? argumentTypes.size() : 0);
return super.resolve(context, targetObject, name, argumentTypes);
}
private void validateMethod(Object targetObject, String name, int argumentCount) {
if (this.methodFilter == null) {
return;
}
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
Method[] methods = type.getMethods();
List<Method> candidates = new ArrayList<Method>();
List<Method> candidates = new ArrayList<>();
for (Method method : methods) {
if (method.getName().equals(name) && method.getParameterTypes().length == argumentCount) {
candidates.add(method);
@@ -111,10 +119,12 @@ public class ExpressionCommandMessageProcessor extends AbstractMessageProcessor<
List<Method> supportedMethods = this.methodFilter.filter(candidates);
if (supportedMethods.size() == 0) {
String methodDescription = (candidates.size() > 0) ? candidates.get(0).toString() : name;
throw new EvaluationException("The method '" + methodDescription + "' is not supported by this command processor. " +
throw new EvaluationException("The method '" + methodDescription +
"' is not supported by this command processor. " +
"If using the Control Bus, consider adding @ManagedOperation or @ManagedAttribute.");
}
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -18,6 +18,7 @@ package org.springframework.integration.handler;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
@@ -28,6 +29,7 @@ import org.springframework.util.Assert;
* @author Mark Fisher
* @author Artem Bilan
* @author Gary Russell
*
* @since 2.0
*/
public class ExpressionEvaluatingMessageProcessor<T> extends AbstractMessageProcessor<T> {
@@ -51,7 +53,7 @@ public class ExpressionEvaluatingMessageProcessor<T> extends AbstractMessageProc
* @param expression The expression.
* @param expectedType The expected type.
*/
public ExpressionEvaluatingMessageProcessor(Expression expression, Class<T> expectedType) {
public ExpressionEvaluatingMessageProcessor(Expression expression, @Nullable Class<T> expectedType) {
Assert.notNull(expression, "The expression must not be null");
try {
this.expression = expression;
@@ -84,7 +86,7 @@ public class ExpressionEvaluatingMessageProcessor<T> extends AbstractMessageProc
* @param expectedType the expected result type.
* @since 5.0
*/
public ExpressionEvaluatingMessageProcessor(String expression, Class<T> expectedType) {
public ExpressionEvaluatingMessageProcessor(String expression, @Nullable Class<T> expectedType) {
try {
this.expression = EXPRESSION_PARSER.parseExpression(expression);
this.expectedType = expectedType;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2016-2018 the original author or authors.
* Copyright 2016-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.
@@ -29,6 +29,7 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.converter.MessageConverter;
@@ -47,7 +48,7 @@ import org.springframework.util.ReflectionUtils;
*/
public class LambdaMessageProcessor implements MessageProcessor<Object>, BeanFactoryAware {
private static final Log logger = LogFactory.getLog(LambdaMessageProcessor.class); // NOSONAR lower case static
private static final Log LOGGER = LogFactory.getLog(LambdaMessageProcessor.class);
private final Object target;
@@ -103,15 +104,17 @@ public class LambdaMessageProcessor implements MessageProcessor<Object>, BeanFac
}
catch (InvocationTargetException e) {
if (e.getTargetException() instanceof ClassCastException) {
logger.error("Could not invoke the method due to a class cast exception, if using a lambda in the DSL, "
+ "consider using an overloaded EIP method that takes a Class<?> argument to explicitly "
+ "specify the type. An example of when this often occurs is if the lambda is configured to "
+ "receive a Message<?> argument.", e.getCause());
LOGGER.error("Could not invoke the method due to a class cast exception, " +
"if using a lambda in the DSL, consider using an overloaded EIP method " +
"that takes a Class<?> argument to explicitly specify the type. " +
"An example of when this often occurs is if the lambda is configured to " +
"receive a Message<?> argument.", e.getCause());
}
throw new MessageHandlingException(message, e.getCause());
}
catch (Exception e) {
throw new MessageHandlingException(message, e);
throw IntegrationUtils.wrapInHandlingExceptionIfNecessary(message,
() -> "error occurred during processing message in 'LambdaMessageProcessor' [" + this + "]", e);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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.
@@ -19,6 +19,7 @@ package org.springframework.integration.handler;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.function.Function;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -27,6 +28,8 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.integration.dispatcher.AggregateMessageDeliveryException;
import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -41,6 +44,7 @@ import org.springframework.util.StringUtils;
* @author Gary Russell
* @author Artem Bilan
* @author Andriy Kryvtsun
*
* @since 1.0.1
*/
public class LoggingHandler extends AbstractMessageHandler {
@@ -51,17 +55,17 @@ public class LoggingHandler extends AbstractMessageHandler {
}
private volatile Level level;
private Level level;
private volatile boolean expressionSet;
private Expression expression = new FunctionExpression<Message<?>>(Message::getPayload);
private volatile Expression expression = EXPRESSION_PARSER.parseExpression("payload");
private boolean expressionSet;
private volatile EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext();
private EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext();
private volatile boolean shouldLogFullMessageSet;
private boolean shouldLogFullMessageSet;
private volatile Log messageLogger = this.logger;
private Log messageLogger = this.logger;
/**
* Create a LoggingHandler with the given log level (case-insensitive).
@@ -153,9 +157,10 @@ public class LoggingHandler extends AbstractMessageHandler {
public void setShouldLogFullMessage(boolean shouldLogFullMessage) {
Assert.isTrue(!(this.expressionSet), "Cannot set both 'expression' AND 'shouldLogFullMessage' properties");
this.shouldLogFullMessageSet = true;
this.expression = shouldLogFullMessage
? EXPRESSION_PARSER.parseExpression("#root")
: EXPRESSION_PARSER.parseExpression("payload");
this.expression =
shouldLogFullMessage
? new FunctionExpression<Message<?>>(Function.identity())
: new FunctionExpression<Message<?>>(Message::getPayload);
}
@Override
@@ -170,7 +175,7 @@ public class LoggingHandler extends AbstractMessageHandler {
}
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
protected void handleMessageInternal(Message<?> message) {
switch (this.level) {
case FATAL:
if (this.messageLogger.isFatalEnabled()) {
@@ -207,6 +212,7 @@ public class LoggingHandler extends AbstractMessageHandler {
}
}
@Nullable
private Object createLogMessage(Message<?> message) {
Object logMessage = this.expression.getValue(this.evaluationContext, message);
return logMessage instanceof Throwable

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* 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.
@@ -16,6 +16,7 @@
package org.springframework.integration.handler;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
/**
@@ -37,6 +38,8 @@ import org.springframework.messaging.Message;
* message-handling components. As such, it is subject to change.
*
* @author Mark Fisher
* @author Artem Bilan
*
* @since 2.0
*/
@FunctionalInterface
@@ -48,6 +51,7 @@ public interface MessageProcessor<T> {
* @param message The message to process.
* @return The result.
*/
@Nullable
T processMessage(Message<?> message);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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.
@@ -34,18 +34,18 @@ import org.springframework.util.Assert;
*/
public class MethodInvokingMessageHandler extends AbstractMessageHandler implements Lifecycle {
private volatile MethodInvokingMessageProcessor<Object> processor;
private final MethodInvokingMessageProcessor<Object> processor;
private volatile String componentType;
private String componentType;
public MethodInvokingMessageHandler(Object object, Method method) {
Assert.isTrue(method.getReturnType().equals(void.class),
"MethodInvokingMessageHandler requires a void-returning method");
this.processor = new MethodInvokingMessageProcessor<Object>(object, method);
this.processor = new MethodInvokingMessageProcessor<>(object, method);
}
public MethodInvokingMessageHandler(Object object, String methodName) {
this.processor = new MethodInvokingMessageProcessor<Object>(object, methodName);
this.processor = new MethodInvokingMessageProcessor<>(object, methodName);
}
@Override
@@ -79,7 +79,7 @@ public class MethodInvokingMessageHandler extends AbstractMessageHandler impleme
}
@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
protected void handleMessageInternal(Message<?> message) {
Object result = this.processor.processMessage(message);
if (result != null) {
throw new MessagingException(message, "the MethodInvokingMessageHandler method must "

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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.
@@ -23,9 +23,9 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.Lifecycle;
import org.springframework.core.convert.ConversionService;
import org.springframework.integration.handler.support.MessagingMethodInvokerHelper;
import org.springframework.lang.NonNull;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
/**
* A MessageProcessor implementation that invokes a method on a target Object.
@@ -69,7 +69,7 @@ public class MethodInvokingMessageProcessor<T> extends AbstractMessageProcessor<
}
@Override
public void setBeanFactory(@NonNull BeanFactory beanFactory) {
public void setBeanFactory(@Nullable BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
this.delegate.setBeanFactory(beanFactory);
}
@@ -101,12 +101,15 @@ public class MethodInvokingMessageProcessor<T> extends AbstractMessageProcessor<
}
@Override
@Nullable
public T processMessage(Message<?> message) {
try {
return this.delegate.process(message);
}
catch (Exception e) {
throw new MessageHandlingException(message, e);
throw IntegrationUtils.wrapInHandlingExceptionIfNecessary(message,
() -> "error occurred during processing message in 'MethodInvokingMessageProcessor' [" + this + "]",
e);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* 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.
@@ -22,6 +22,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.Lifecycle;
import org.springframework.core.convert.ConversionService;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
/**
@@ -35,15 +36,15 @@ public class ServiceActivatingHandler extends AbstractReplyProducingMessageHandl
public ServiceActivatingHandler(final Object object) {
this(new MethodInvokingMessageProcessor<Object>(object, ServiceActivator.class));
this(new MethodInvokingMessageProcessor<>(object, ServiceActivator.class));
}
public ServiceActivatingHandler(Object object, Method method) {
this(new MethodInvokingMessageProcessor<Object>(object, method));
this(new MethodInvokingMessageProcessor<>(object, method));
}
public ServiceActivatingHandler(Object object, String methodName) {
this(new MethodInvokingMessageProcessor<Object>(object, methodName));
this(new MethodInvokingMessageProcessor<>(object, methodName));
}
public <T> ServiceActivatingHandler(MessageProcessor<T> processor) {
@@ -89,6 +90,7 @@ public class ServiceActivatingHandler extends AbstractReplyProducingMessageHandl
}
@Override
@Nullable
protected Object handleRequestMessage(Message<?> message) {
return this.processor.processMessage(message);
}
@@ -96,7 +98,7 @@ public class ServiceActivatingHandler extends AbstractReplyProducingMessageHandl
@Override
public String toString() {
return "ServiceActivator for [" + this.processor + "]"
+ (this.getComponentName() == null ? "" : " (" + this.getComponentName() + ")");
+ (getComponentName() == null ? "" : " (" + getComponentName() + ")");
}
}

View File

@@ -84,7 +84,7 @@ import org.springframework.integration.util.ClassUtils;
import org.springframework.integration.util.FixedMethodFilter;
import org.springframework.integration.util.MessagingAnnotationUtils;
import org.springframework.integration.util.UniqueMethodFilter;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessageHeaders;
@@ -285,7 +285,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
}
@Override
public void setBeanFactory(@NonNull BeanFactory beanFactory) {
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
((DefaultMessageHandlerMethodFactory) this.messageHandlerMethodFactory).setBeanFactory(beanFactory);
@@ -308,11 +308,13 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
}
}
@Nullable
public T process(Message<?> message) throws Exception {
ParametersWrapper parameters = new ParametersWrapper(message);
return processInternal(parameters);
}
@Nullable
public T process(Collection<Message<?>> messages, Map<String, Object> headers) throws Exception {
ParametersWrapper parameters = new ParametersWrapper(messages, headers);
return processInternal(parameters);
@@ -468,6 +470,7 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
}
@SuppressWarnings("unchecked")
@Nullable
private T processInternal(ParametersWrapper parameters) throws Exception {
if (!this.initialized) {
initialize();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-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.
@@ -37,6 +37,8 @@ import org.springframework.util.Assert;
*
* @author Gary Russell
* @author Marius Bogoevici
* @author Artem Bilan
*
* @since 4.0
*
*/
@@ -113,7 +115,6 @@ public final class IntegrationUtils {
/**
* Utility method for null-safe conversion from String to byte[]
*
* @param value the String to be converted
* @param encoding the encoding
* @return the byte[] corresponding to the given String and encoding, null if provided String argument was null
@@ -130,7 +131,6 @@ public final class IntegrationUtils {
/**
* Utility method for null-safe conversion from byte[] to String
*
* @param bytes the byte[] to be converted
* @param encoding the encoding
* @return the String corresponding to the given byte[] and encoding, null if provided byte[] argument was null
@@ -151,19 +151,19 @@ public final class IntegrationUtils {
* in a new {@link MessageDeliveryException} with the message.
* @param message the message.
* @param text a Supplier for the new exception's message text.
* @param e the exception.
* @param ex the exception.
* @return the wrapper, if necessary, or the original exception.
* @since 5.0.4
*/
public static RuntimeException wrapInDeliveryExceptionIfNecessary(Message<?> message, Supplier<String> text,
Exception e) {
Throwable ex) {
RuntimeException runtimeException = (e instanceof RuntimeException)
? (RuntimeException) e
: new MessageDeliveryException(message, text.get(), e);
if (!(e instanceof MessagingException) ||
((MessagingException) e).getFailedMessage() == null) {
runtimeException = new MessageDeliveryException(message, text.get(), e);
RuntimeException runtimeException = (ex instanceof RuntimeException)
? (RuntimeException) ex
: new MessageDeliveryException(message, text.get(), ex);
if (!(ex instanceof MessagingException) ||
((MessagingException) ex).getFailedMessage() == null) {
runtimeException = new MessageDeliveryException(message, text.get(), ex);
}
return runtimeException;
}
@@ -174,19 +174,19 @@ public final class IntegrationUtils {
* in a new {@link MessageHandlingException} with the message.
* @param message the message.
* @param text a Supplier for the new exception's message text.
* @param e the exception.
* @param ex the exception.
* @return the wrapper, if necessary, or the original exception.
* @since 5.0.4
*/
public static RuntimeException wrapInHandlingExceptionIfNecessary(Message<?> message, Supplier<String> text,
Exception e) {
Throwable ex) {
RuntimeException runtimeException = (e instanceof RuntimeException)
? (RuntimeException) e
: new MessageHandlingException(message, text.get(), e);
if (!(e instanceof MessagingException) ||
((MessagingException) e).getFailedMessage() == null) {
runtimeException = new MessageHandlingException(message, text.get(), e);
RuntimeException runtimeException = (ex instanceof RuntimeException)
? (RuntimeException) ex
: new MessageHandlingException(message, text.get(), ex);
if (!(ex instanceof MessagingException) ||
((MessagingException) ex).getFailedMessage() == null) {
runtimeException = new MessageHandlingException(message, text.get(), ex);
}
return runtimeException;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* 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.
@@ -35,7 +35,6 @@ import org.springframework.integration.support.MessageBuilderFactory;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandlingException;
/**
* @author Mark Fisher
@@ -64,13 +63,11 @@ public abstract class AbstractExpressionEvaluator implements BeanFactoryAware, I
* Specify a BeanFactory in order to enable resolution via <code>@beanName</code> in the expression.
*/
@Override
public void setBeanFactory(final @Nullable BeanFactory beanFactory) {
if (beanFactory != null) {
this.beanFactory = beanFactory;
this.typeConverter.setBeanFactory(beanFactory);
if (this.evaluationContext != null && this.evaluationContext.getBeanResolver() == null) {
this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.typeConverter.setBeanFactory(beanFactory);
if (this.evaluationContext != null && this.evaluationContext.getBeanResolver() == null) {
this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
}
@@ -89,7 +86,7 @@ public abstract class AbstractExpressionEvaluator implements BeanFactoryAware, I
}
@Override
public final void afterPropertiesSet() throws Exception {
public final void afterPropertiesSet() {
getEvaluationContext();
if (this.beanFactory != null) {
this.messageBuilderFactory = IntegrationUtils.getMessageBuilderFactory(this.beanFactory);
@@ -99,7 +96,7 @@ public abstract class AbstractExpressionEvaluator implements BeanFactoryAware, I
}
protected StandardEvaluationContext getEvaluationContext() {
return this.getEvaluationContext(true);
return getEvaluationContext(true);
}
/**
@@ -126,50 +123,52 @@ public abstract class AbstractExpressionEvaluator implements BeanFactoryAware, I
return this.evaluationContext;
}
protected <T> T evaluateExpression(Expression expression, Message<?> message, Class<T> expectedType) {
@Nullable
protected <T> T evaluateExpression(Expression expression, Message<?> message, @Nullable Class<T> expectedType) {
try {
return evaluateExpression(expression, (Object) message, expectedType);
}
catch (EvaluationException e) {
Throwable cause = e.getCause();
if (this.logger.isDebugEnabled()) {
this.logger.debug("SpEL Expression evaluation failed with EvaluationException.", e);
catch (Exception ex) {
this.logger.debug("SpEL Expression evaluation failed with Exception.", ex);
Throwable cause = null;
if (ex instanceof EvaluationException) {
cause = ex.getCause();
}
throw new MessageHandlingException(message, "Expression evaluation failed: "
+ expression.getExpressionString(), cause == null ? e : cause);
}
catch (Exception e) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("SpEL Expression evaluation failed with Exception." + e);
}
throw new MessageHandlingException(message, "Expression evaluation failed: "
+ expression.getExpressionString(), e);
throw IntegrationUtils.wrapInHandlingExceptionIfNecessary(message,
() -> "Expression evaluation failed: " + expression.getExpressionString(),
cause == null ? ex : cause);
}
}
@Nullable
protected Object evaluateExpression(String expression, Object input) {
return this.evaluateExpression(expression, input, null);
return evaluateExpression(expression, input, null);
}
protected <T> T evaluateExpression(String expression, Object input, Class<T> expectedType) {
@Nullable
protected <T> T evaluateExpression(String expression, Object input, @Nullable Class<T> expectedType) {
return EXPRESSION_PARSER.parseExpression(expression)
.getValue(this.getEvaluationContext(), input, expectedType);
.getValue(getEvaluationContext(), input, expectedType);
}
@Nullable
protected Object evaluateExpression(Expression expression, Object input) {
return this.evaluateExpression(expression, input, null);
return evaluateExpression(expression, input, null);
}
protected <T> T evaluateExpression(Expression expression, Class<T> expectedType) {
return expression.getValue(this.getEvaluationContext(), expectedType);
@Nullable
protected <T> T evaluateExpression(Expression expression, @Nullable Class<T> expectedType) {
return expression.getValue(getEvaluationContext(), expectedType);
}
@Nullable
protected Object evaluateExpression(Expression expression) {
return expression.getValue(this.getEvaluationContext());
return expression.getValue(getEvaluationContext());
}
protected <T> T evaluateExpression(Expression expression, Object input, Class<T> expectedType) {
return expression.getValue(this.getEvaluationContext(), input, expectedType);
@Nullable
protected <T> T evaluateExpression(Expression expression, Object input, @Nullable Class<T> expectedType) {
return expression.getValue(getEvaluationContext(), input, expectedType);
}
protected void onInit() {

View File

@@ -17,22 +17,21 @@
package org.springframework.integration.config.xml;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.handler.LoggingHandler;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Mark Fisher
@@ -41,14 +40,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
*
* @since 2.1
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringRunner.class)
public class LoggingChannelAdapterParserTests {
@Autowired @Qualifier("logger.adapter")
@Autowired
@Qualifier("logger.adapter")
private EventDrivenConsumer loggerConsumer;
@Autowired @Qualifier("loggerWithExpression.adapter")
@Autowired
@Qualifier("loggerWithExpression.adapter")
private EventDrivenConsumer loggerWithExpression;
@@ -58,33 +58,30 @@ public class LoggingChannelAdapterParserTests {
assertThat(TestUtils.getPropertyValue(loggingHandler, "messageLogger.logger.name"))
.isEqualTo("org.springframework.integration.test.logger");
assertThat(TestUtils.getPropertyValue(loggingHandler, "order")).isEqualTo(1);
assertThat(TestUtils.getPropertyValue(loggingHandler, "level").toString()).isEqualTo("WARN");
assertThat(TestUtils.getPropertyValue(loggingHandler, "expression.expression")).isEqualTo("#root");
assertThat(TestUtils.getPropertyValue(loggingHandler, "level")).isEqualTo(LoggingHandler.Level.WARN);
assertThat(TestUtils.getPropertyValue(loggingHandler, "expression")).isInstanceOf(FunctionExpression.class);
}
@Test
public void verifyExpressionAndOtherDefaultConfig() {
LoggingHandler loggingHandler = TestUtils.getPropertyValue(loggerWithExpression, "handler", LoggingHandler.class);
LoggingHandler loggingHandler =
TestUtils.getPropertyValue(loggerWithExpression, "handler", LoggingHandler.class);
assertThat(TestUtils.getPropertyValue(loggingHandler, "messageLogger.logger.name"))
.isEqualTo("org.springframework.integration.handler.LoggingHandler");
assertThat(TestUtils.getPropertyValue(loggingHandler, "order")).isEqualTo(Ordered.LOWEST_PRECEDENCE);
assertThat(TestUtils.getPropertyValue(loggingHandler, "level").toString()).isEqualTo("INFO");
assertThat(TestUtils.getPropertyValue(loggingHandler, "level")).isEqualTo(LoggingHandler.Level.INFO);
assertThat(TestUtils.getPropertyValue(loggingHandler, "expression.expression")).isEqualTo("payload.foo");
assertThat(TestUtils.getPropertyValue(loggingHandler, "evaluationContext.beanResolver")).isNotNull();
}
@Test
public void failConfigLogFullMessageAndExpression() {
try {
new ClassPathXmlApplicationContext("LoggingChannelAdapterParserTests-fail-context.xml", this.getClass())
.close();
fail("BeanDefinitionParsingException expected");
}
catch (BeansException e) {
assertThat(e instanceof BeanDefinitionParsingException).isTrue();
assertThat(e.getMessage()
.contains("The 'expression' and 'log-full-message' attributes are mutually exclusive.")).isTrue();
}
assertThatExceptionOfType(BeanDefinitionParsingException.class)
.isThrownBy(() ->
new ClassPathXmlApplicationContext(
"LoggingChannelAdapterParserTests-fail-context.xml",
getClass()))
.withMessageContaining("The 'expression' and 'log-full-message' attributes are mutually exclusive.");
}
}

View File

@@ -17,7 +17,7 @@
package org.springframework.integration.handler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.fail;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.ArgumentMatchers.anyString;
@@ -76,6 +76,7 @@ import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.converter.MessageConversionException;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
@@ -394,13 +395,14 @@ public class MethodInvokingMessageProcessorTests {
assertThat(result).isEqualTo(456);
}
@Test(expected = MessageHandlingException.class)
@Test
public void conversionFailureWithAnnotatedMethod() throws Exception {
AnnotatedTestService service = new AnnotatedTestService();
Method method = service.getClass().getMethod("integerMethod", Integer.class);
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
processor.setBeanFactory(mock(BeanFactory.class));
processor.processMessage(new GenericMessage<>("foo"));
assertThatExceptionOfType(MessageConversionException.class)
.isThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")));
}
@Test
@@ -420,8 +422,9 @@ public class MethodInvokingMessageProcessorTests {
Method method = service.getClass().getMethod("integerMethod", Integer.class);
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
processor.setBeanFactory(mock(BeanFactory.class));
assertThatThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.isInstanceOf(MessageHandlingException.class);
assertThatExceptionOfType(MessageConversionException.class)
.isThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.withMessageContaining("Failed to convert message payload 'foo' to 'java.lang.Integer'");
}
@Test
@@ -430,8 +433,9 @@ public class MethodInvokingMessageProcessorTests {
Method method = service.getClass().getMethod("error", String.class);
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
processor.setBeanFactory(mock(BeanFactory.class));
assertThatThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.hasCauseInstanceOf(UnsupportedOperationException.class);
assertThatExceptionOfType(MessageHandlingException.class)
.isThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.withCauseInstanceOf(UnsupportedOperationException.class);
}
@Test
@@ -440,8 +444,9 @@ public class MethodInvokingMessageProcessorTests {
Method method = service.getClass().getMethod("checked", String.class);
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
processor.setBeanFactory(mock(BeanFactory.class));
assertThatThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.hasCauseInstanceOf(CheckedException.class);
assertThatExceptionOfType(MessageHandlingException.class)
.isThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.withCauseInstanceOf(CheckedException.class);
}
@Test
@@ -451,8 +456,9 @@ public class MethodInvokingMessageProcessorTests {
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
processor.setUseSpelInvoker(true);
processor.setBeanFactory(mock(BeanFactory.class));
assertThatThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.hasCauseInstanceOf(SpelEvaluationException.class);
assertThatExceptionOfType(MessageHandlingException.class)
.isThrownBy(() -> processor.processMessage(new GenericMessage<>("foo")))
.withCauseInstanceOf(SpelEvaluationException.class);
}
@Test

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.handler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.fail;
import java.util.concurrent.atomic.AtomicReference;
@@ -43,8 +44,7 @@ import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.ErrorMessage;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.SettableListenableFuture;
@@ -57,8 +57,7 @@ import org.springframework.util.concurrent.SettableListenableFuture;
*
* @since 2.0.1
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@RunWith(SpringRunner.class)
public class ServiceActivatorDefaultFrameworkMethodTests {
@Autowired
@@ -109,19 +108,14 @@ public class ServiceActivatorDefaultFrameworkMethodTests {
assertThat(reply.getHeaders().get("history").toString())
.isEqualTo("gatewayTestInputChannel,gatewayTestService,gateway,requestChannel,replyChannel");
message = MessageBuilder.withPayload("foo").setReplyChannel(replyChannel).build();
try {
this.gatewayTestInputChannel.send(message);
fail("Exception expected");
}
catch (Exception e) {
assertThat(e).isInstanceOf(MessageHandlingException.class);
assertThat(e.getCause()).isInstanceOf(MessageTransformationException.class);
assertThat(e.getCause().getCause()).isInstanceOf(MessageHandlingException.class);
assertThat(e.getCause().getCause().getCause()).isInstanceOf(IllegalStateException.class);
assertThat(e.getMessage()).contains("Expression evaluation failed");
assertThat(e.getMessage()).contains("Wrong payload");
}
Message<?> message2 = MessageBuilder.withPayload("foo").setReplyChannel(replyChannel).build();
assertThatExceptionOfType(MessageTransformationException.class)
.isThrownBy(() -> this.gatewayTestInputChannel.send(message2))
.withCauseInstanceOf(MessageHandlingException.class)
.withRootCauseInstanceOf(IllegalStateException.class)
.withMessageContaining("Expression evaluation failed")
.withMessageContaining("Wrong payload");
}
@Test