devdaily home | apple | java | perl | unix | directory | blog

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * Copyright 2002-2007 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.aspectj;

import java.lang.reflect.Method;

import junit.framework.AssertionFailedError;

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.transaction.CallCountingTransactionManager;
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttribute;

/**
 * @author Rod Johnson
 */
public class TransactionAspectTests extends AbstractDependencyInjectionSpringContextTests {
	
	private TransactionAspectSupport transactionAspect;
	
	private CallCountingTransactionManager txManager;
	
	private TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface;
	
	private ClassWithProtectedAnnotatedMember beanWithAnnotatedProtectedMethod;

	private ClassWithPrivateAnnotatedMember beanWithAnnotatedPrivateMethod;
	
	private MethodAnnotationOnClassWithNoInterface methodAnnotationOnly = new MethodAnnotationOnClassWithNoInterface();


	public void setAnnotationOnlyOnClassWithNoInterface(
			TransactionalAnnotationOnlyOnClassWithNoInterface annotationOnlyOnClassWithNoInterface) {
		this.annotationOnlyOnClassWithNoInterface = annotationOnlyOnClassWithNoInterface;
	}
	
	public void setClassWithAnnotatedProtectedMethod(ClassWithProtectedAnnotatedMember aBean) {
		this.beanWithAnnotatedProtectedMethod = aBean;
	}

	public void setClassWithAnnotatedPrivateMethod(ClassWithPrivateAnnotatedMember aBean) {
		this.beanWithAnnotatedPrivateMethod = aBean;
	}

	public void setTransactionAspect(TransactionAspectSupport transactionAspect) {
		this.transactionAspect = transactionAspect;
		this.txManager = (CallCountingTransactionManager) transactionAspect.getTransactionManager();
	}

	public TransactionAspectSupport getTransactionAspect() {
		return this.transactionAspect;
	}

	@Override
	protected String getConfigPath() {
		return "txtests.xml";
	}


	public void testCommitOnAnnotatedClass() throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		annotationOnlyOnClassWithNoInterface.echo(null);
		assertEquals(1, txManager.commits);
	}

	public void testCommitOnAnnotatedProtectedMethod() throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		beanWithAnnotatedProtectedMethod.doInTransaction();
		assertEquals(1, txManager.commits);		
	}

	public void testCommitOnAnnotatedPrivateMethod() throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		beanWithAnnotatedPrivateMethod.doSomething();
		assertEquals(1, txManager.commits);		
	}

	public void testNoCommitOnNonAnnotatedNonPublicMethodInTransactionalType() throws Throwable {
		txManager.clear();
		assertEquals(0,txManager.begun);
		annotationOnlyOnClassWithNoInterface.nonTransactionalMethod();
		assertEquals(0,txManager.begun);
	}
	
	public void testCommitOnAnnotatedMethod() throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		methodAnnotationOnly.echo(null);
		assertEquals(1, txManager.commits);
	}
	
	
	public static class NotTransactional {
		public void noop() {
		}
	}
	
	public void testNotTransactional() throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		new NotTransactional().noop();
		assertEquals(0, txManager.begun);
	}
	
	
	public void testDefaultCommitOnAnnotatedClass() throws Throwable {
		testRollback(new TransactionOperationCallback() {
			public Object performTransactionalOperation() throws Throwable {
				return annotationOnlyOnClassWithNoInterface.echo(new Exception());
			}
		}, false);
	}
	
	public void testDefaultRollbackOnAnnotatedClass() throws Throwable {
		testRollback(new TransactionOperationCallback() {
			public Object performTransactionalOperation() throws Throwable {
				return annotationOnlyOnClassWithNoInterface.echo(new RuntimeException());
			}
		}, true);
	}
	
	
	public static class SubclassOfClassWithTransactionalAnnotation extends TransactionalAnnotationOnlyOnClassWithNoInterface {
	}
	
	public void testDefaultCommitOnSubclassOfAnnotatedClass() throws Throwable {
		testRollback(new TransactionOperationCallback() {
			public Object performTransactionalOperation() throws Throwable {
				return new SubclassOfClassWithTransactionalAnnotation().echo(new Exception());
			}
		}, false);
	}
	
	public static class SubclassOfClassWithTransactionalMethodAnnotation extends MethodAnnotationOnClassWithNoInterface {
	}
	
	public void testDefaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable {
		testRollback(new TransactionOperationCallback() {
			public Object performTransactionalOperation() throws Throwable {
				return new SubclassOfClassWithTransactionalMethodAnnotation().echo(new Exception());
			}
		}, false);
	}
	
	public static class ImplementsAnnotatedInterface implements ITransactional {
		public Object echo(Throwable t) throws Throwable {
			if (t != null) {
				throw t;
			}
			return t;
		}
	}
	
	public void testDefaultCommitOnImplementationOfAnnotatedInterface() throws Throwable {
//		testRollback(new TransactionOperationCallback() {
//			public Object performTransactionalOperation() throws Throwable {
//				return new ImplementsAnnotatedInterface().echo(new Exception());
//			}
//		}, false);
		
		final Exception ex = new Exception();
		testNotTransactional(new TransactionOperationCallback() {
			public Object performTransactionalOperation() throws Throwable {
				return new ImplementsAnnotatedInterface().echo(ex);
			}
		}, ex);
	}
	
	/**
	 * Note: resolution does not occur. Thus we can't make a class transactional if
	 * it implements a transactionally annotated interface. This behaviour could only
	 * be changed in AbstractFallbackTransactionAttributeSource in Spring proper.
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public void testDoesNotResolveTxAnnotationOnMethodFromClassImplementingAnnotatedInterface() throws SecurityException, NoSuchMethodException {
		AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
		Method m = ImplementsAnnotatedInterface.class.getMethod("echo", Throwable.class);
		TransactionAttribute ta = atas.getTransactionAttribute(m, ImplementsAnnotatedInterface.class);
		assertNull(ta);
	}
	
	
	public void testDefaultRollbackOnImplementationOfAnnotatedInterface() throws Throwable {
//		testRollback(new TransactionOperationCallback() {
//			public Object performTransactionalOperation() throws Throwable {
//				return new ImplementsAnnotatedInterface().echo(new RuntimeException());
//			}
//		}, true);
		
		final Exception rollbackProvokingException = new RuntimeException();
		testNotTransactional(new TransactionOperationCallback() {
			public Object performTransactionalOperation() throws Throwable {
				return new ImplementsAnnotatedInterface().echo(rollbackProvokingException);
			}
		}, rollbackProvokingException);
	}

	
	protected void testRollback(TransactionOperationCallback toc, boolean rollback) throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		try {
			toc.performTransactionalOperation();
			assertEquals(1, txManager.commits);
		}
		catch (Throwable caught) {
			if (caught instanceof AssertionFailedError) {
				return;
			}
		}
		
		if (rollback) {
			assertEquals(1, txManager.rollbacks);
		}
		assertEquals(1, txManager.begun);
	}
	
	protected void testNotTransactional(TransactionOperationCallback toc, Throwable expected) throws Throwable {
		txManager.clear();
		assertEquals(0, txManager.begun);
		try {
			toc.performTransactionalOperation();
		}
		catch (Throwable t) {
			if (expected == null) {
				fail("Expected " + expected);
			}
			assertSame(expected, t);
		}
		finally {
			assertEquals(0, txManager.begun);
		}
	}
	

	private interface TransactionOperationCallback {

		Object performTransactionalOperation() throws Throwable;
	}

}




Copyright 1998-2008 Alvin Alexander
All Rights Reserved.
 
devdaily.com is based in louisville, kentucky, and this web site is hosted by godaddy.com