INT-941: Catch and unwrap in AbstractMessageProcessor
This commit is contained in:
@@ -47,6 +47,10 @@ public abstract class AbstractMessageProcessor implements MessageProcessor {
|
||||
try {
|
||||
return expression.getValue(this.evaluationContext, message);
|
||||
}
|
||||
catch (EvaluationException e) {
|
||||
Throwable cause = e.getCause();
|
||||
throw new MessageHandlingException(message, "Expression evaluation failed.", cause==null ? e : cause);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessageHandlingException(message, "Expression evaluation failed.", e);
|
||||
}
|
||||
|
||||
@@ -31,14 +31,12 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
@@ -156,7 +154,7 @@ public class MethodInvokingMessageProcessor extends AbstractMessageProcessor {
|
||||
}
|
||||
|
||||
public Object processMessage(Message<?> message) {
|
||||
EvaluationException evaluationException = null;
|
||||
Throwable evaluationException = null;
|
||||
List<HandlerMethod> candidates = this.findHandlerMethodsForMessage(message);
|
||||
for (HandlerMethod candidate : candidates) {
|
||||
try {
|
||||
@@ -169,17 +167,13 @@ public class MethodInvokingMessageProcessor extends AbstractMessageProcessor {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (EvaluationException e) {
|
||||
catch (MessageHandlingException e) {
|
||||
if (evaluationException == null) {
|
||||
// keep the first exception
|
||||
evaluationException = e;
|
||||
evaluationException = e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (evaluationException == null) {
|
||||
throw new MessageHandlingException(message, "Failed to find a suitable Message-handling " +
|
||||
"method on target of type [" + targetObject.getClass() + "].");
|
||||
}
|
||||
throw new MessageHandlingException(message, "Failed to process Message.", evaluationException);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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.handler;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hamcrest.Description;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.internal.matchers.TypeSafeMatcher;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.message.StringMessage;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluatingMessageProcessorTests {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ExpressionEvaluatingMessageProcessorTests.class);
|
||||
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testProcessMessage() {
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload");
|
||||
assertEquals("foo", processor.processMessage(new StringMessage("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageBadExpression() {
|
||||
expected.expect(new TypeSafeMatcher<Exception>(Exception.class) {
|
||||
private Throwable cause;
|
||||
@Override
|
||||
public boolean matchesSafely(Exception item) {
|
||||
logger.debug(item);
|
||||
cause = item.getCause();
|
||||
return cause instanceof EvaluationException;
|
||||
}
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("cause to be EvaluationException but was ").appendValue(cause);
|
||||
}
|
||||
});
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.fixMe()");
|
||||
assertEquals("foo", processor.processMessage(new StringMessage("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageExpressionThrowsRuntimeException() {
|
||||
expected.expect(new TypeSafeMatcher<Exception>(Exception.class) {
|
||||
private Throwable cause;
|
||||
@Override
|
||||
public boolean matchesSafely(Exception item) {
|
||||
logger.debug(item);
|
||||
cause = item.getCause();
|
||||
return cause instanceof UnsupportedOperationException;
|
||||
}
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("cause to be UnsupportedOperationException but was ").appendValue(cause);
|
||||
}
|
||||
});
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.error()");
|
||||
assertEquals("foo", processor.processMessage(new GenericMessage<ExpressionEvaluatingMessageProcessorTests>(this)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageExpressionThrowsCheckedException() {
|
||||
expected.expect(new TypeSafeMatcher<Exception>(Exception.class) {
|
||||
private Throwable cause;
|
||||
@Override
|
||||
public boolean matchesSafely(Exception item) {
|
||||
logger.debug(item);
|
||||
cause = item.getCause();
|
||||
return cause instanceof CheckedException;
|
||||
}
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("cause to be CheckedException but was ").appendValue(cause);
|
||||
}
|
||||
});
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.check()");
|
||||
assertEquals("foo", processor.processMessage(new GenericMessage<ExpressionEvaluatingMessageProcessorTests>(this)));
|
||||
}
|
||||
|
||||
public String error() {
|
||||
throw new UnsupportedOperationException("Expected test exception");
|
||||
}
|
||||
|
||||
public String check() throws Exception {
|
||||
throw new CheckedException("Expected test exception");
|
||||
}
|
||||
|
||||
private static final class CheckedException extends Exception {
|
||||
public CheckedException(String string) {
|
||||
super(string);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,8 +25,14 @@ import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.hamcrest.Description;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.junit.internal.matchers.TypeSafeMatcher;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.integration.annotation.Header;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.core.Message;
|
||||
@@ -39,9 +45,15 @@ import org.springframework.integration.message.StringMessage;
|
||||
* @author Mark Fisher
|
||||
* @author Marius Bogoevici
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class MethodInvokingMessageProcessorTests {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MethodInvokingMessageProcessorTests.class);
|
||||
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void testHandlerInheritanceMethodImplInSuper() {
|
||||
class A {
|
||||
@@ -246,6 +258,33 @@ public class MethodInvokingMessageProcessorTests {
|
||||
processor.processMessage(new StringMessage("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageBadExpression() throws Exception {
|
||||
expected.expect(new ExceptionCauseMatcher(ConversionFailedException.class));
|
||||
AnnotatedTestService service = new AnnotatedTestService();
|
||||
Method method = service.getClass().getMethod("integerMethod", Integer.class);
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
|
||||
assertEquals("foo", processor.processMessage(new StringMessage("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageRuntimeException() throws Exception {
|
||||
expected.expect(new ExceptionCauseMatcher(UnsupportedOperationException.class));
|
||||
TestErrorService service = new TestErrorService();
|
||||
Method method = service.getClass().getMethod("error", String.class);
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
|
||||
assertEquals("foo", processor.processMessage(new StringMessage("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageCheckedException() throws Exception {
|
||||
expected.expect(new ExceptionCauseMatcher(CheckedException.class));
|
||||
TestErrorService service = new TestErrorService();
|
||||
Method method = service.getClass().getMethod("checked", String.class);
|
||||
MethodInvokingMessageProcessor processor = new MethodInvokingMessageProcessor(service, method);
|
||||
assertEquals("foo", processor.processMessage(new StringMessage("foo")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageAndHeaderWithAnnotatedMethod() throws Exception {
|
||||
AnnotatedTestService service = new AnnotatedTestService();
|
||||
@@ -289,7 +328,40 @@ public class MethodInvokingMessageProcessorTests {
|
||||
assertEquals("true", bean.lastArg);
|
||||
}
|
||||
|
||||
|
||||
private static class ExceptionCauseMatcher extends TypeSafeMatcher<Exception> {
|
||||
private Throwable cause;
|
||||
private Class<? extends Exception> type;
|
||||
public ExceptionCauseMatcher(Class<? extends Exception> type) {
|
||||
this.type = type;
|
||||
}
|
||||
@Override
|
||||
public boolean matchesSafely(Exception item) {
|
||||
logger.debug(item);
|
||||
cause = item.getCause();
|
||||
assertNotNull("There is no cause for "+item, cause);
|
||||
return type.isAssignableFrom(cause.getClass());
|
||||
}
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("cause to be ").appendValue(type).appendText("but was ").appendValue(cause);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestErrorService {
|
||||
public String error(String input) {
|
||||
throw new UnsupportedOperationException("Expected test exception");
|
||||
}
|
||||
public String checked(String input) throws Exception {
|
||||
throw new CheckedException("Expected test exception");
|
||||
}
|
||||
}
|
||||
|
||||
public static final class CheckedException extends Exception {
|
||||
public CheckedException(String string) {
|
||||
super(string);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestBean {
|
||||
|
||||
Reference in New Issue
Block a user