diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/StackTraceUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/util/StackTraceUtils.java new file mode 100644 index 0000000000..f76c2ee1cf --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/StackTraceUtils.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013 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.util; + +/** + * Utility methods for analyzing stack traces. + * + * @author Gary Russell + * @since 3.0 + * + */ +public class StackTraceUtils { + + private StackTraceUtils() {} + + /** + * Traverses the stack trace element array looking for instances that contain the first or second + * Strings in the className property. + * @param firstClass The first class to look for. + * @param secondClass The second class to look for. + * @param stackTrace The stack trace. + * @return true if the first class appears first, false if the second appears first + * @throws IllegalArgumentException if neither class is found. + */ + public static boolean isFrameContainingXBeforeFrameContainingY(String firstClass, String secondClass, StackTraceElement[] stackTrace) { + for (StackTraceElement element : stackTrace) { + if (element.getClassName().contains(firstClass)) { + return true; + } + else if (element.getClassName().contains(secondClass)) { + return false; + } + } + throw new IllegalArgumentException("Neither " + firstClass + " nor " + secondClass + " class found"); + } +} diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/ServiceActivatorDefaultFrameworkMethodTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/ServiceActivatorDefaultFrameworkMethodTests.java index f788c76c3c..7205448876 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/ServiceActivatorDefaultFrameworkMethodTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/ServiceActivatorDefaultFrameworkMethodTests.java @@ -17,8 +17,10 @@ package org.springframework.integration.handler; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.hamcrest.Matchers; @@ -35,6 +37,7 @@ import org.springframework.integration.core.MessageHandler; import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.util.StackTraceUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -95,7 +98,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { assertEquals("TEST", reply.getPayload()); assertEquals("replyingHandlerTestInputChannel,replyingHandlerTestService", reply.getHeaders().get("history").toString()); StackTraceElement[] st = (StackTraceElement[]) reply.getHeaders().get("callStack"); - assertEquals("doDispatch", st[3].getMethodName()); // close to the metal + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); // close to the metal } @Test @@ -108,7 +111,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { assertEquals("optimizedRefReplyingHandlerTestInputChannel,optimizedRefReplyingHandlerTestService", reply.getHeaders().get("history").toString()); StackTraceElement[] st = (StackTraceElement[]) reply.getHeaders().get("callStack"); - assertEquals("doDispatch", st[3].getMethodName()); + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); // close to the metal } @Test @@ -120,7 +123,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { assertEquals("TEST", reply.getPayload()); assertEquals("replyingHandlerWithStandardMethodTestInputChannel,replyingHandlerWithStandardMethodTestService", reply.getHeaders().get("history").toString()); StackTraceElement[] st = (StackTraceElement[]) reply.getHeaders().get("callStack"); - assertEquals("doDispatch", st[3].getMethodName()); // close to the metal + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); // close to the metal } @Test @@ -183,6 +186,10 @@ public class ServiceActivatorDefaultFrameworkMethodTests { } public String foo(String in) { + Exception e = new RuntimeException(); + StackTraceElement[] st = e.getStackTrace(); + // use this to test that StackTraceUtils works as expected and returns false + assertFalse(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); return "bar"; } @@ -195,7 +202,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { public void handleMessage(Message requestMessage) { Exception e = new RuntimeException(); StackTraceElement[] st = e.getStackTrace(); - assertEquals("doDispatch", st[4].getMethodName()); + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); // close to the metal } } diff --git a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/ServiceActivatorDefaultFrameworkMethodTests.java b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/ServiceActivatorDefaultFrameworkMethodTests.java index 0f8db9084a..2ddc4ca31c 100644 --- a/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/ServiceActivatorDefaultFrameworkMethodTests.java +++ b/spring-integration-jmx/src/test/java/org/springframework/integration/jmx/ServiceActivatorDefaultFrameworkMethodTests.java @@ -17,8 +17,10 @@ package org.springframework.integration.jmx; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.hamcrest.Matchers; @@ -37,6 +39,7 @@ import org.springframework.integration.handler.AbstractReplyProducingMessageHand import org.springframework.integration.handler.MessageProcessor; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.util.StackTraceUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -97,7 +100,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { assertEquals("TEST", reply.getPayload()); assertEquals("replyingHandlerTestInputChannel,replyingHandlerTestService", reply.getHeaders().get("history").toString()); StackTraceElement[] st = (StackTraceElement[]) reply.getHeaders().get("callStack"); - assertEquals("doDispatch", st[15].getMethodName()); // close to the metal + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); } @Test @@ -110,7 +113,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { assertEquals("optimizedRefReplyingHandlerTestInputChannel,optimizedRefReplyingHandlerTestService", reply.getHeaders().get("history").toString()); StackTraceElement[] st = (StackTraceElement[]) reply.getHeaders().get("callStack"); - assertEquals("doDispatch", st[15].getMethodName()); + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); } @Test @@ -122,7 +125,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { assertEquals("TEST", reply.getPayload()); assertEquals("replyingHandlerWithStandardMethodTestInputChannel,replyingHandlerWithStandardMethodTestService", reply.getHeaders().get("history").toString()); StackTraceElement[] st = (StackTraceElement[]) reply.getHeaders().get("callStack"); - assertEquals("doDispatch", st[15].getMethodName()); // close to the metal + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); } @Test @@ -191,6 +194,10 @@ public class ServiceActivatorDefaultFrameworkMethodTests { } public String foo(String in) { + Exception e = new RuntimeException(); + StackTraceElement[] st = e.getStackTrace(); + // use this to test that StackTraceUtils works as expected and returns false + assertFalse(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); return "bar"; } @@ -203,7 +210,7 @@ public class ServiceActivatorDefaultFrameworkMethodTests { public void handleMessage(Message requestMessage) { Exception e = new RuntimeException(); StackTraceElement[] st = e.getStackTrace(); - assertEquals("doDispatch", st[16].getMethodName()); + assertTrue(StackTraceUtils.isFrameContainingXBeforeFrameContainingY("Dispatcher", "MethodInvokerHelper", st)); } }