GH-3474: LambdaMPP: rethrow runtime ex as is
Fixes https://github.com/spring-projects/spring-integration/issues/3474 The `AbstractTransformer` implementation just wraps a thrown exception into a `MessageTransformationException`. It is expected with any method transformer impl (POJO, Lambda direct etc.) the exception is thrown as is without extra wrapping into an `IllegalStateException` for consistency * Fix `LambdaMessageProcessor` to rethrow `RuntimeException` as is and only wrap into an `IllegalStateException` for all other exceptions * Fix tests for missed extra stack trace
This commit is contained in:
committed by
Gary Russell
parent
707b653d97
commit
31863f06e3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2019 the original author or authors.
|
||||
* Copyright 2016-2021 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.
|
||||
@@ -97,15 +97,19 @@ public class LambdaMessageProcessor implements MessageProcessor<Object>, BeanFac
|
||||
return this.method.invoke(this.target, args);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (e.getTargetException() instanceof ClassCastException) {
|
||||
LOGGER.error("Could not invoke the method '" + this.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());
|
||||
"receive a Message<?> argument.", cause);
|
||||
}
|
||||
if (cause instanceof RuntimeException) { // NOSONAR
|
||||
throw (RuntimeException) cause;
|
||||
}
|
||||
throw new IllegalStateException(// NOSONAR lost stack trace
|
||||
"Could not invoke the method '" + this.method + "'", e.getCause());
|
||||
"Could not invoke the method '" + this.method + "'", cause);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2019 the original author or authors.
|
||||
* Copyright 2016-2021 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,13 +18,11 @@ package org.springframework.integration.dsl;
|
||||
|
||||
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.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -38,7 +36,7 @@ import org.springframework.integration.handler.LambdaMessageProcessor;
|
||||
import org.springframework.integration.transformer.GenericTransformer;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
|
||||
|
||||
/**
|
||||
@@ -47,7 +45,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringJUnitConfig
|
||||
public class LambdaMessageProcessorTests {
|
||||
|
||||
@Autowired
|
||||
@@ -56,13 +54,8 @@ public class LambdaMessageProcessorTests {
|
||||
@Test
|
||||
@SuppressWarnings("divzero")
|
||||
public void testException() {
|
||||
try {
|
||||
handle((m, h) -> 1 / 0);
|
||||
fail("Expected exception");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e.getCause()).isInstanceOf(ArithmeticException.class);
|
||||
}
|
||||
assertThatExceptionOfType(ArithmeticException.class)
|
||||
.isThrownBy(() -> handle((m, h) -> 1 / 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -88,9 +81,8 @@ public class LambdaMessageProcessorTests {
|
||||
(GenericTransformer<Message<?>, Message<?>>) this::messageTransformer, null);
|
||||
lmp.setBeanFactory(this.beanFactory);
|
||||
GenericMessage<String> testMessage = new GenericMessage<>("foo");
|
||||
assertThatExceptionOfType(IllegalStateException.class)
|
||||
.isThrownBy(() -> lmp.processMessage(testMessage))
|
||||
.withCauseInstanceOf(ClassCastException.class);
|
||||
assertThatExceptionOfType(ClassCastException.class)
|
||||
.isThrownBy(() -> lmp.processMessage(testMessage));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-2021 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,7 +18,8 @@ package org.springframework.integration.dsl.manualflow;
|
||||
|
||||
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 static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
@@ -220,14 +221,9 @@ public class ManualFlowTests {
|
||||
|
||||
assertThat(messagingTemplate.convertSendAndReceive("bar", String.class)).isEqualTo("Hello, BAR");
|
||||
|
||||
try {
|
||||
messagingTemplate.receive();
|
||||
fail("UnsupportedOperationException expected");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(UnsupportedOperationException.class);
|
||||
assertThat(e.getMessage()).contains("The 'receive()/receiveAndConvert()' isn't supported");
|
||||
}
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(messagingTemplate::receive)
|
||||
.withMessageContaining("The 'receive()/receiveAndConvert()' isn't supported");
|
||||
|
||||
assertThat(this.beanFactory.getBeanNamesForType(MessageTransformingHandler.class)[0]).startsWith(flowId + ".");
|
||||
|
||||
@@ -251,15 +247,9 @@ public class ManualFlowTests {
|
||||
|
||||
@Test
|
||||
public void testWrongLifecycle() {
|
||||
try {
|
||||
this.integrationFlowContext.remove("foo");
|
||||
fail("IllegalStateException expected");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(IllegalStateException.class);
|
||||
assertThat(e.getMessage())
|
||||
.contains("An IntegrationFlow with the id [" + "foo" + "] doesn't exist in the registry.");
|
||||
}
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> this.integrationFlowContext.remove("foo"))
|
||||
.withMessageContaining("An IntegrationFlow with the id [" + "foo" + "] doesn't exist in the registry.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -305,14 +295,10 @@ public class ManualFlowTests {
|
||||
|
||||
@Test
|
||||
public void testWrongIntegrationFlowScope() {
|
||||
try {
|
||||
new AnnotationConfigApplicationContext(InvalidIntegrationFlowScopeConfiguration.class).close();
|
||||
fail("BeanCreationNotAllowedException expected");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(BeanCreationNotAllowedException.class);
|
||||
assertThat(e.getMessage()).contains("IntegrationFlows can not be scoped beans.");
|
||||
}
|
||||
assertThatExceptionOfType(BeanCreationNotAllowedException.class)
|
||||
.isThrownBy(() ->
|
||||
new AnnotationConfigApplicationContext(InvalidIntegrationFlowScopeConfiguration.class))
|
||||
.withMessageContaining("IntegrationFlows can not be scoped beans.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -382,13 +368,9 @@ public class ManualFlowTests {
|
||||
|
||||
this.roleController.stopLifecyclesInRole(testRole);
|
||||
|
||||
try {
|
||||
messagingTemplate.send(new GenericMessage<>("test2"));
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(MessageDeliveryException.class);
|
||||
assertThat(e.getMessage()).contains("Dispatcher has no subscribers for channel");
|
||||
}
|
||||
assertThatExceptionOfType(MessageDeliveryException.class)
|
||||
.isThrownBy(() -> messagingTemplate.send(new GenericMessage<>("test2")))
|
||||
.withMessageContaining("Dispatcher has no subscribers for channel");
|
||||
|
||||
this.roleController.startLifecyclesInRole(testRole);
|
||||
|
||||
@@ -453,16 +435,13 @@ public class ManualFlowTests {
|
||||
.id(testId)
|
||||
.register();
|
||||
|
||||
try {
|
||||
this.integrationFlowContext
|
||||
.registration(testFlow)
|
||||
.id(testId)
|
||||
.register();
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertThat(e).isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(e.getMessage()).contains("with flowId '" + testId + "' is already registered.");
|
||||
}
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() ->
|
||||
this.integrationFlowContext
|
||||
.registration(testFlow)
|
||||
.id(testId)
|
||||
.register())
|
||||
.withMessageContaining("with flowId '" + testId + "' is already registered.");
|
||||
|
||||
flowRegistration.destroy();
|
||||
}
|
||||
@@ -527,8 +506,7 @@ public class ManualFlowTests {
|
||||
.register();
|
||||
assertThatExceptionOfType(MessageTransformationException.class)
|
||||
.isThrownBy(() -> flowRegistration.getInputChannel().send(new GenericMessage<>(new Date())))
|
||||
.withCauseExactlyInstanceOf(IllegalStateException.class)
|
||||
.withRootCauseInstanceOf(ClassCastException.class)
|
||||
.withCauseExactlyInstanceOf(ClassCastException.class)
|
||||
.withMessageContaining("from source: '" + source + "'")
|
||||
.withStackTraceContaining("java.util.Date cannot be cast to");
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016-2020 the original author or authors.
|
||||
* Copyright 2016-2021 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.
|
||||
@@ -913,7 +913,7 @@ public class RouterTests {
|
||||
|
||||
@ServiceActivator(inputChannel = "scatterGatherErrorChannel")
|
||||
public Message<?> processAsyncScatterError(MessagingException payload) {
|
||||
return MessageBuilder.withPayload(payload.getCause().getCause())
|
||||
return MessageBuilder.withPayload(payload.getCause())
|
||||
.copyHeaders(payload.getFailedMessage().getHeaders())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017-2020 the original author or authors.
|
||||
* Copyright 2017-2021 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.
|
||||
@@ -89,7 +89,7 @@ public class ExpressionEvaluatingRequestHandlerAdviceTests {
|
||||
advice.setOnSuccessExpressionString("payload + ' was successful'");
|
||||
advice.setFailureChannelName("failure.input");
|
||||
advice.setOnFailureExpressionString(
|
||||
"payload + ' was bad, with reason: ' + #exception.cause.message");
|
||||
"payload + ' was bad, with reason: ' + #exception.message");
|
||||
advice.setTrapException(true);
|
||||
return advice;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user