1 16 17 package org.springframework.transaction.interceptor; 18 19 import java.lang.reflect.Method ; 20 import java.lang.reflect.Proxy ; 21 import java.util.Map ; 22 23 import junit.framework.TestCase; 24 import org.aopalliance.intercept.MethodInterceptor; 25 import org.aopalliance.intercept.MethodInvocation; 26 import org.easymock.MockControl; 27 28 import org.springframework.aop.support.AopUtils; 29 import org.springframework.aop.support.StaticMethodMatcherPointcut; 30 import org.springframework.aop.target.HotSwappableTargetSource; 31 import org.springframework.beans.DerivedTestBean; 32 import org.springframework.beans.FatalBeanException; 33 import org.springframework.beans.ITestBean; 34 import org.springframework.beans.TestBean; 35 import org.springframework.beans.factory.xml.XmlBeanFactory; 36 import org.springframework.core.io.ClassPathResource; 37 import org.springframework.transaction.CountingTxManager; 38 import org.springframework.transaction.PlatformTransactionManager; 39 import org.springframework.transaction.TransactionDefinition; 40 import org.springframework.transaction.TransactionException; 41 import org.springframework.transaction.TransactionStatus; 42 import org.springframework.transaction.support.DefaultTransactionStatus; 43 44 50 public class BeanFactoryTransactionTests extends TestCase { 51 52 private XmlBeanFactory factory; 53 54 public void setUp() { 55 this.factory = new XmlBeanFactory(new ClassPathResource("transactionalBeanFactory.xml", getClass())); 56 } 57 58 public void testGetsAreNotTransactionalWithProxyFactory1() throws NoSuchMethodException { 59 ITestBean testBean = (ITestBean) factory.getBean("proxyFactory1"); 60 assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass())); 61 doTestGetsAreNotTransactional(testBean, ITestBean.class); 62 } 63 64 public void testGetsAreNotTransactionalWithProxyFactory2DynamicProxy() throws NoSuchMethodException { 65 this.factory.preInstantiateSingletons(); 66 ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2DynamicProxy"); 67 assertTrue("testBean is a dynamic proxy", Proxy.isProxyClass(testBean.getClass())); 68 doTestGetsAreNotTransactional(testBean, ITestBean.class); 69 } 70 71 public void testGetsAreNotTransactionalWithProxyFactory2Cglib() throws NoSuchMethodException { 72 ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Cglib"); 73 assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(testBean)); 74 doTestGetsAreNotTransactional(testBean, TestBean.class); 75 } 76 77 public void testProxyFactory2Lazy() throws NoSuchMethodException { 78 ITestBean testBean = (ITestBean) factory.getBean("proxyFactory2Lazy"); 79 assertFalse(factory.containsSingleton("target")); 80 assertEquals(666, testBean.getAge()); 81 assertTrue(factory.containsSingleton("target")); 82 } 83 84 public void testCglibTransactionProxyImplementsNoInterfaces() throws NoSuchMethodException { 85 ImplementsNoInterfaces ini = (ImplementsNoInterfaces) factory.getBean("cglibNoInterfaces"); 86 assertTrue("testBean is CGLIB advised", AopUtils.isCglibProxy(ini)); 87 String newName = "Gordon"; 88 89 final TransactionStatus ts = new DefaultTransactionStatus(null, true, false, false, false, null); 91 CountingTxManager ptm = new CountingTxManager(); 92 PlatformTransactionManagerFacade.delegate = ptm; 93 94 ini.setName(newName); 95 assertEquals(newName, ini.getName()); 96 assertEquals(2, ptm.commits); 97 } 98 99 public void testGetsAreNotTransactionalWithProxyFactory3() throws NoSuchMethodException { 100 ITestBean testBean = (ITestBean) factory.getBean("proxyFactory3"); 101 assertTrue("testBean is a full proxy", testBean instanceof DerivedTestBean); 102 InvocationCounterPointcut txnCounter = (InvocationCounterPointcut) factory.getBean("txnInvocationCounterPointcut"); 103 InvocationCounterInterceptor preCounter = (InvocationCounterInterceptor) factory.getBean("preInvocationCounterInterceptor"); 104 InvocationCounterInterceptor postCounter = (InvocationCounterInterceptor) factory.getBean("postInvocationCounterInterceptor"); 105 txnCounter.counter = 0; 106 preCounter.counter = 0; 107 postCounter.counter = 0; 108 doTestGetsAreNotTransactional(testBean, TestBean.class); 109 assertTrue(0 < txnCounter.counter && txnCounter.counter <= 4); 111 assertEquals(4, preCounter.counter); 112 assertEquals(4, postCounter.counter); 113 } 114 115 private void doTestGetsAreNotTransactional(final ITestBean testBean, final Class proxyClass) { 116 MockControl ptmControl = MockControl.createControl(PlatformTransactionManager.class); 118 PlatformTransactionManager ptm = (PlatformTransactionManager) ptmControl.getMock(); 119 ptmControl.replay(); 121 PlatformTransactionManagerFacade.delegate = ptm; 122 123 assertTrue("Age should not be " + testBean.getAge(), testBean.getAge() == 666); 124 ptmControl.verify(); 126 127 final TransactionStatus ts = new DefaultTransactionStatus(null, true, false, false, false, null); 129 ptm = new PlatformTransactionManager() { 130 private boolean invoked; 131 public TransactionStatus getTransaction(TransactionDefinition definition) 132 throws TransactionException { 133 if (invoked) { 134 throw new IllegalStateException ("getTransaction should not get invoked more than once"); 135 } 136 invoked = true; 137 if (!((definition.getName().indexOf(proxyClass.getName()) != -1) && 138 (definition.getName().indexOf("setAge") != -1))) { 139 throw new IllegalStateException ( 140 "transaction name should contain class and method name: " + definition.getName()); 141 } 142 return ts; 143 } 144 public void commit(TransactionStatus status) throws TransactionException { 145 assertTrue(status == ts); 146 } 147 public void rollback(TransactionStatus status) throws TransactionException { 148 throw new IllegalStateException ("rollback should not get invoked"); 149 } 150 }; 151 PlatformTransactionManagerFacade.delegate = ptm; 152 153 int age = 666; 155 testBean.setAge(age); 156 assertTrue(testBean.getAge() == age); 157 ptmControl.verify(); 158 } 159 160 public void testGetBeansOfTypeWithAbstract() { 161 Map beansOfType = factory.getBeansOfType(ITestBean.class, true, true); 162 } 164 165 168 public void testNoTransactionAttributeSource() { 169 try { 170 XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("noTransactionAttributeSource.xml", getClass())); 171 ITestBean testBean = (ITestBean) bf.getBean("noTransactionAttributeSource"); 172 fail("Should require TransactionAttributeSource to be set"); 173 } 174 catch (FatalBeanException ex) { 175 } 177 } 178 179 182 public void testDynamicTargetSource() throws NoSuchMethodException { 183 CountingTxManager txMan = new CountingTxManager(); 185 PlatformTransactionManagerFacade.delegate = txMan; 186 187 TestBean tb = (TestBean) factory.getBean("hotSwapped"); 188 assertEquals(666, tb.getAge()); 189 int newAge = 557; 190 tb.setAge(newAge); 191 assertEquals(newAge, tb.getAge()); 192 193 TestBean target2 = new TestBean(); 194 target2.setAge(65); 195 HotSwappableTargetSource ts = (HotSwappableTargetSource) factory.getBean("swapper"); 196 ts.swap(target2); 197 assertEquals(target2.getAge(), tb.getAge()); 198 tb.setAge(newAge); 199 assertEquals(newAge, target2.getAge()); 200 201 assertEquals(0, txMan.inflight); 202 assertEquals(2, txMan.commits); 203 assertEquals(0, txMan.rollbacks); 204 } 205 206 207 public static class InvocationCounterPointcut extends StaticMethodMatcherPointcut { 208 209 int counter = 0; 210 211 public boolean matches(Method method, Class clazz) { 212 counter++; 213 return true; 214 } 215 } 216 217 218 public static class InvocationCounterInterceptor implements MethodInterceptor { 219 220 int counter = 0; 221 222 public Object invoke(MethodInvocation methodInvocation) throws Throwable { 223 counter++; 224 return methodInvocation.proceed(); 225 } 226 } 227 228 } 229 | Popular Tags |