diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorDoubleProxyingTests-context.xml b/org.springframework.integration-tests/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorDoubleProxyingTests-context.xml new file mode 100755 index 00000000000..06254762fbd --- /dev/null +++ b/org.springframework.integration-tests/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorDoubleProxyingTests-context.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.dialect.HSQLDialect + create + false + + + + + + + + + + + + + + + + diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorDoubleProxyingTests.java b/org.springframework.integration-tests/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorDoubleProxyingTests.java new file mode 100644 index 00000000000..0a4892ca557 --- /dev/null +++ b/org.springframework.integration-tests/src/test/java/org/springframework/transaction/interceptor/TransactionInterceptorDoubleProxyingTests.java @@ -0,0 +1,82 @@ +/* + * 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.transaction.interceptor; + + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.IllegalTransactionStateException; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + + +/** + * Tests cornering SPR-7009. + * + * @author Chris Beams + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class TransactionInterceptorDoubleProxyingTests { + + @Autowired + TestRepository repository; + + @Test + public void test1() { + // method 1 is required, so no problem + assertThat(repository.method1(), equalTo("result1")); + } + + @Test(expected = IllegalTransactionStateException.class) + public void test2() { + // method 2 is mandatory, so expect exception + assertThat(repository.method2(), equalTo("result2")); + } + +} + + +interface TestRepository { + + public String method1(); + + public String method2(); + +} + +@Repository("testRepository") +class TestRepositoryImpl implements TestRepository { + + @Transactional + public String method1() { + return "result1"; + } + + @Transactional(propagation = Propagation.MANDATORY) + public String method2() { + return "result2"; + } + +} diff --git a/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionInterceptor.java b/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionInterceptor.java index a7ef513bd63..e7665f980d7 100644 --- a/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionInterceptor.java +++ b/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionInterceptor.java @@ -25,6 +25,7 @@ import java.util.Properties; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; +import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; @@ -49,6 +50,7 @@ import org.springframework.transaction.support.TransactionCallback; * @see org.springframework.aop.framework.ProxyFactoryBean * @see org.springframework.aop.framework.ProxyFactory */ +@SuppressWarnings("serial") public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { /** @@ -90,7 +92,7 @@ public class TransactionInterceptor extends TransactionAspectSupport implements // Work out the target class: may be null. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. - Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null); + Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr =