From d371886988a12331128ff645537e542f00dd7467 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 30 Oct 2013 22:38:49 -0700 Subject: [PATCH] Allow null method for getTransactionAttribute Update MatchAlwaysTransactionAttributeSource.getTransactionAttribute to allow a null method argument. Passing a null method is not recommended and is not indicated as valid in the Javadoc, however, this was allowed in previous versions of Spring. Issue: SPR-11048 --- .../main/java/org/springframework/util/ClassUtils.java | 8 ++++++-- .../MatchAlwaysTransactionAttributeSource.java | 2 +- .../interceptor/TransactionAttributeSourceTests.java | 10 ++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 9ae3c1d4b4..c7d586413a 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -778,8 +778,12 @@ public abstract class ClassUtils { * @return {@code true} if the method can be considered as user-declared; [@code false} otherwise */ public static boolean isUserLevelMethod(Method method) { - return (method.isBridge() || - (!method.isSynthetic() && !method.getDeclaringClass().getName().equals("groovy.lang.GroovyObject"))); + Assert.notNull(method, "Method must not be null"); + return (method.isBridge() || (!method.isSynthetic() && !isGroovyObjectMethod(method))); + } + + private static boolean isGroovyObjectMethod(Method method) { + return method.getDeclaringClass().getName().equals("groovy.lang.GroovyObject"); } /** diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java index 90c62d3f9f..b1bb7bb604 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java @@ -53,7 +53,7 @@ public class MatchAlwaysTransactionAttributeSource implements TransactionAttribu @Override public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) { - return (ClassUtils.isUserLevelMethod(method) ? this.transactionAttribute : null); + return (method == null || ClassUtils.isUserLevelMethod(method) ? this.transactionAttribute : null); } diff --git a/spring-tx/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java b/spring-tx/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java index b5a7b2c741..7871f11a90 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/interceptor/TransactionAttributeSourceTests.java @@ -54,6 +54,16 @@ public final class TransactionAttributeSourceTests { assertTrue(TransactionDefinition.PROPAGATION_SUPPORTS == ta.getPropagationBehavior()); } + @Test + public void testMatchAlwaysTransactionAttributeSourceWithNulls() throws Exception { + MatchAlwaysTransactionAttributeSource tas = new MatchAlwaysTransactionAttributeSource(); + TransactionDefinition definition = tas.getTransactionAttribute(null, null); + assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, definition.getPropagationBehavior()); + assertEquals(TransactionDefinition.ISOLATION_DEFAULT, definition.getIsolationLevel()); + assertEquals(TransactionDefinition.TIMEOUT_DEFAULT, definition.getTimeout()); + assertFalse(definition.isReadOnly()); + } + @SuppressWarnings("unchecked") @Ignore // no longer works now that setMethodMap has been parameterized @Test