From e954e58e93d392c0f0354f81df9bc6e2c69bcb4f Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 17 Aug 2011 12:29:30 -0400 Subject: [PATCH 1/3] Gateway now rethrows unwrapped RuntimeExceptions --- .../gateway/GatewayProxyFactoryBean.java | 15 +++++++--- .../GatewayInvokingMessageHandlerTests.java | 29 +++++++++++++------ .../gateway/InnerGatewayWithChainTests.java | 3 +- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index e1a7f6d99d..03052f408c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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.gateway; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.lang.reflect.UndeclaredThrowableException; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -310,15 +311,21 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab private void rethrowExceptionInThrowsClauseIfPossible(Throwable originalException, Method method) throws Throwable { List> exceptionTypes = Arrays.asList(method.getExceptionTypes()); Throwable t = originalException; - while (t != null) { - if (exceptionTypes.contains(t.getClass())) { + while (t instanceof MessagingException || t instanceof UndeclaredThrowableException) { + t = t.getCause(); + } + if (t instanceof RuntimeException) { + throw t; + } + for (Class exceptionType : exceptionTypes) { + if (exceptionType.isAssignableFrom(t.getClass())) { throw t; } - t = t.getCause(); } throw originalException; } + private MethodInvocationGateway createGatewayForMethod(Method method) { Gateway gatewayAnnotation = method.getAnnotation(Gateway.class); MessageChannel requestChannel = this.defaultRequestChannel; diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInvokingMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInvokingMessageHandlerTests.java index e4f799533d..7355c60d18 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInvokingMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/GatewayInvokingMessageHandlerTests.java @@ -104,8 +104,8 @@ public class GatewayInvokingMessageHandlerTests { gatewayWithError.process("echoWithRuntimeExceptionChannel"); Assert.fail(); } - catch (MessageHandlingException e) { - Assert.assertEquals("echoWithRuntimeExceptionChannel", e.getFailedMessage().getPayload()); + catch (SampleRuntimeException e) { + Assert.assertEquals("echoWithRuntimeExceptionChannel", e.getMessage()); } try { @@ -133,7 +133,7 @@ public class GatewayInvokingMessageHandlerTests { Assert.fail(); } catch (Exception e) { - Assert.assertTrue(e instanceof MessageHandlingException); + Assert.assertEquals(SampleRuntimeException.class, e.getClass()); } } @@ -164,27 +164,38 @@ public class GatewayInvokingMessageHandlerTests { public static class SimpleService { + public String echo(String value) { return "echo:" + value; } - public RuntimeException echoWithRuntimeException(String value) { - throw new RuntimeException(value); + + public String echoWithRuntimeException(String value) { + throw new SampleRuntimeException(value); } - public MessageHandlingException echoWithMessagingException(String value) { + public String echoWithMessagingException(String value) { throw new MessageHandlingException(new GenericMessage(value)); } - public RuntimeException echoWithErrorAsync(String value) { - throw new RuntimeException(value); + + public String echoWithErrorAsync(String value) { + throw new SampleRuntimeException(value); } } @SuppressWarnings("serial") public static class SampleCheckedException extends Exception { - public SampleCheckedException(String message){ + public SampleCheckedException(String message) { super(message); } } + + @SuppressWarnings("serial") + public static class SampleRuntimeException extends RuntimeException { + public SampleRuntimeException(String message) { + super(message); + } + } + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/gateway/InnerGatewayWithChainTests.java b/spring-integration-core/src/test/java/org/springframework/integration/gateway/InnerGatewayWithChainTests.java index c46c978a1a..d8a5ac9dc1 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/gateway/InnerGatewayWithChainTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/gateway/InnerGatewayWithChainTests.java @@ -26,7 +26,6 @@ import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.Message; -import org.springframework.integration.MessageHandlingException; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.core.SubscribableChannel; import org.springframework.integration.endpoint.SourcePollingChannelAdapter; @@ -84,7 +83,7 @@ public class InnerGatewayWithChainTests { } // if no error channels explicitly defined exception is rethrown - @Test(expected=MessageHandlingException.class) + @Test(expected=ArithmeticException.class) public void testGatewaysNoErrorChannel(){ testGatewayWithNoErrorChannelAAA.echo(0); } From f81c9e1d7bd6505c32246c626b4eacb5656dba34 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Thu, 18 Aug 2011 13:45:44 -0400 Subject: [PATCH 2/3] walks the cause hierarchy again this will accommodate InvocationTargetException and more --- .../gateway/GatewayProxyFactoryBean.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 03052f408c..24f709fbf4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -20,9 +20,7 @@ import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.UndeclaredThrowableException; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.Executor; @@ -270,7 +268,7 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab return this.invokeGatewayMethod(invocation); } catch (Throwable e) { - this.rethrowExceptionInThrowsClauseIfPossible(e, invocation.getMethod()); + this.rethrowExceptionCauseIfPossible(e, invocation.getMethod()); return null; // preceding call should always throw something } } @@ -308,24 +306,24 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab return (response != null) ? this.convert(response, returnType) : null; } - private void rethrowExceptionInThrowsClauseIfPossible(Throwable originalException, Method method) throws Throwable { - List> exceptionTypes = Arrays.asList(method.getExceptionTypes()); + private void rethrowExceptionCauseIfPossible(Throwable originalException, Method method) throws Throwable { + Class[] exceptionTypes = method.getExceptionTypes(); Throwable t = originalException; - while (t instanceof MessagingException || t instanceof UndeclaredThrowableException) { - t = t.getCause(); - } - if (t instanceof RuntimeException) { - throw t; - } - for (Class exceptionType : exceptionTypes) { - if (exceptionType.isAssignableFrom(t.getClass())) { + while (t != null) { + for (Class exceptionType : exceptionTypes) { + if (exceptionType.isAssignableFrom(t.getClass())) { + throw t; + } + } + if ((t instanceof RuntimeException) && + !(t instanceof MessagingException) && !(t instanceof UndeclaredThrowableException)) { throw t; } + t = t.getCause(); } throw originalException; } - private MethodInvocationGateway createGatewayForMethod(Method method) { Gateway gatewayAnnotation = method.getAnnotation(Gateway.class); MessageChannel requestChannel = this.defaultRequestChannel; From bdc5dd9f855b6948fd3a48fa31b0924d6befd310 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 24 Aug 2011 21:03:18 -0400 Subject: [PATCH 3/3] added check for IllegalStateException on unexpected exception thrown from method invcation --- .../integration/gateway/GatewayProxyFactoryBean.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java index 24f709fbf4..de5b7eb6de 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/gateway/GatewayProxyFactoryBean.java @@ -315,8 +315,10 @@ public class GatewayProxyFactoryBean extends AbstractEndpoint implements Trackab throw t; } } - if ((t instanceof RuntimeException) && - !(t instanceof MessagingException) && !(t instanceof UndeclaredThrowableException)) { + if (t instanceof RuntimeException + && !(t instanceof MessagingException) + && !(t instanceof UndeclaredThrowableException) + && !(t instanceof IllegalStateException && ("Unexpected exception thrown").equals(t.getMessage()))) { throw t; } t = t.getCause();