(no commit message)
[utils] / test / enterprise / src / main / java / org / wamblee / test / transactions / SimpleTransactionManager.java
1 /*
2  * Copyright 2005-2010 the original author or authors.
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.test.transactions;
17
18 import java.util.ArrayList;
19 import java.util.List;
20
21 import javax.transaction.UserTransaction;
22
23 import org.wamblee.general.ThreadSpecificProxyFactory;
24 import org.wamblee.general.ThreadSpecificProxyFactory.CreationCallback;
25 import org.wamblee.test.persistence.JpaBuilder;
26
27 /**
28  * 
29  * <p>
30  * Simple transaction manager provides a simple mechanism to manage transactions
31  * in test code through the {@link UserTransaction} object. To construct the
32  * transaction manager use:
33  * </p>
34  * 
35  * <pre>
36  * SimpleTransactionManager manager = new SimpleTransactionManager(
37  *     new DefaultUserTransactionFactory());
38  * </pre>
39  * 
40  * <p>
41  * Next, add resources to manage using {@link #addResource(TransactionResource)}:
42  * 
43  * <pre>
44  * manager.addResource(jpaTester.getJpaBuilder());
45  * </pre>
46  * <p>
47  * As you can see from the above, {@link JpaBuilder} is a resource that can be
48  * used so this mechanism can be used with JPA testing.
49  * </p>
50  * 
51  * <p>
52  * The next step is to manage transactions using the standard
53  * <code>UserTransaction</code> APIs:
54  * </p>
55  * 
56  * <pre>
57  *      UserTransaction transaction = manager.getTransaction();
58  *      transaction.begin();
59  *     
60  *      ... do work...
61  *  
62  *      transaction.commit();
63  * </pre>
64  * 
65  * @author Erik Brakkee
66  * 
67  */
68 public class SimpleTransactionManager {
69
70     private UserTransactionFactory factory;
71     private List<TransactionResource> resources;
72     private UserTransactionCallback transactionFInishedCallback;
73     private ThreadSpecificProxyFactory<UserTransaction> transaction;
74
75     /**
76      * Constructs the transaction manager.
77      * 
78      * @param aFactory
79      *            Factory to create transactions with.
80      */
81     public SimpleTransactionManager(UserTransactionFactory aFactory) {
82         factory = aFactory;
83
84         resources = new ArrayList<TransactionResource>();
85
86         transactionFInishedCallback = new UserTransactionCallback() {
87             @Override
88             public void transactionFinished() {
89                 transaction.set(factory.create(this, resources)); 
90             }
91         };
92         transaction = new ThreadSpecificProxyFactory<UserTransaction>(
93             UserTransaction.class, new CreationCallback<UserTransaction>() {
94                 @Override
95                 public UserTransaction create() {
96                     return factory.create(transactionFInishedCallback,
97                         resources);
98                 }
99             });
100     }
101
102     /**
103      * Adds a resource to manage. Adding resources is no longer allowed after
104      * the first transaction has started.
105      * 
106      * @param aResource
107      *            Resource.
108      */
109     public void addResource(TransactionResource aResource) {
110         resources.add(aResource);
111     }
112
113     /**
114      * Gets the user transaction. This is a contextual reference, meaning that
115      * it will delegate to the appropriate thread-specific user transaction. It
116      * is also safe to store in a JNDI tree and for caching by applications.
117      * 
118      * @return User transaction.
119      */
120     public UserTransaction getTransaction() {
121         return transaction.getProxy();
122     }
123     
124     /**
125      * Gets the thread-specific transaction object.
126      * 
127      * @return Transaction object.
128      */
129     UserTransaction getThreadSpecificTransaction() {
130         getTransaction(); // create tx if needed
131         return transaction.get();
132     }
133 }