KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > jtx > JtxTransaction


1 // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
2

3 package jodd.jtx;
4
5 import java.util.Map JavaDoc;
6 import java.util.HashMap JavaDoc;
7 import java.util.Iterator JavaDoc;
8
9 /**
10  * Represents <b>simple</b> single transaction. Created and controlled by some
11  * transactional manager, such as {@link JtxTransactionManager}.
12  * <p>
13  * This entity also may represents transaction absence, when client explicitly
14  * specifies with {@link JtxTransactionManager#requestTransaction(JtxTransactionMode)}
15  * that transactions should not be supported. This transaction also has to be committed,
16  * to close its resources.
17  * <p>
18  * Transaction logic is simple. First, it manages transaction states. Second, it
19  * holds attached {@link JtxResource} references and know how to create new ones.
20  * <p>
21  * Every transaction is associated to a thread from where it is created.
22  * Transaction may have more than one resource attached, but only <b>one</b> of
23  * specified type.
24  * <p>
25  * Committing and rolling back transaction actually performs commit/rollback on
26  * all attached resources. Therefore, it may happens that committing of one resource
27  * fails, what actually breaks the atomicity of the transaction. If transaction is
28  * attached just to one resource, atomicity is saved.
29  */

30 public class JtxTransaction {
31
32     // ---------------------------------------------------------------- statuses
33

34     /**
35      * Special status indicating the explicit absence of transaction,
36      * i.e. the autocommit mode.
37      */

38     public static final int STATUS_AUTOCOMMIT = -1;
39
40     /**
41      * Status code indicating an active transaction.
42      */

43     public static final int STATUS_ACTIVE = 0;
44
45     /**
46      * Status code indicating a transaction that has been committed.
47      * Probably heuristics still exists, or the transaction would no
48      * longer exist.
49      */

50     public static final int STATUS_COMMITTED = 3;
51
52     /**
53      * Status code indicating a transaction that has been rolled back.
54      */

55     public static final int STATUS_ROLLEDBACK = 4;
56
57     /**
58      * Status code indicating that no transaction exists yet.
59      */

60     public static final int STATUS_NO_TRANSACTION = 6;
61
62     /**
63      * Status code indicating a transaction that has begun,
64      * but not yet completed this phase.
65      */

66     public static final int STATUS_COMMITTING = 8;
67
68     /**
69      * Status code indicating a transaction that is in the process of
70      * rolling back.
71      */

72     public static final int STATUS_ROLLING_BACK = 9;
73
74
75     // ---------------------------------------------------------------- manager
76

77     protected JtxTransactionManager manager;
78     protected JtxTransactionMode mode;
79     protected Map JavaDoc resources;
80     protected int status;
81
82     /**
83      * Creates new transaction.
84      * If mode is equals to {@link JtxTransactionMode#PROPAGATION_NOT_SUPPORTED} or
85      * {@link JtxTransactionMode#PROPAGATION_NEVER}, transaction status
86      * becomes {@link #STATUS_AUTOCOMMIT}.
87      */

88     JtxTransaction(JtxTransactionManager manager, JtxTransactionMode mode) {
89         this.manager = manager;
90         this.mode = mode;
91         this.resources = new HashMap JavaDoc();
92         if ((mode.propagation == JtxTransactionMode.PROPAGATION_NOT_SUPPORTED) ||
93             (mode.propagation == JtxTransactionMode.PROPAGATION_NEVER)) {
94             this.status = STATUS_AUTOCOMMIT;
95         } else {
96             this.status = STATUS_NO_TRANSACTION;
97         }
98     }
99
100     // ---------------------------------------------------------------- status
101

102     /**
103      * Returns current transaction status.
104      */

105     public int getStatus() {
106         return status;
107     }
108
109     /**
110      * Returns <code>true</code> if transaction is active.
111      */

112     public boolean isActive() {
113         return status == STATUS_ACTIVE;
114     }
115
116     /**
117      * Returns <code>true</code> if transaction is explicatly forbidden, i.e.
118      * session is in autocommit mode.
119      */

120     public boolean isAutocommit() {
121         return status == STATUS_AUTOCOMMIT;
122     }
123
124     /**
125      * Returns <code>true</code> if transaction and all its resources are committed successfully.
126      */

127     public boolean isCommitted() {
128         return status == STATUS_COMMITTED;
129     }
130
131     /**
132      * Returns <code>true</code> if transaction and all its resources are rolledback successfully.
133      */

134     public boolean isRolledback() {
135         return status == STATUS_ROLLEDBACK;
136     }
137
138
139     // ---------------------------------------------------------------- core
140

141     /**
142      * Begins a new transaction.
143      */

144     public void begin() {
145         if (status == STATUS_AUTOCOMMIT) {
146             throw new JtxException("Transaction is not availiable in autocommit mode.");
147         }
148         if (status != STATUS_NO_TRANSACTION) {
149             throw new JtxException("Transaction already started.");
150         }
151         status = STATUS_ACTIVE;
152     }
153
154     /**
155      * Commit the current transaction. Transaction is commited
156      * on all attached resources. After, resources are detached
157      * from the transaction. When this method completes, transaction is no longer
158      * associated with current thread.
159      */

160     public void commit() {
161         commitOrRollback(true);
162     }
163
164     /**
165      * Roll back the current transaction.
166      * Transaction is rolled back on all attached resources.
167      * Resource are then detached from the tranasaction.
168      * When this method completes, transaction is no longer
169      * associated with current thread.
170      */

171     public void rollback() {
172         commitOrRollback(false);
173     }
174
175     protected void commitOrRollback(boolean commit) {
176         if (status != STATUS_AUTOCOMMIT) {
177             if (status != STATUS_ACTIVE) {
178                 throw new JtxException(commit ? "No active transaction to commit." : "No active transaction to roll back.");
179             }
180             status = commit ? STATUS_COMMITTING : STATUS_ROLLING_BACK;
181             Iterator JavaDoc it = resources.values().iterator();
182             while (it.hasNext()) {
183                 JtxResource resource = (JtxResource) it.next();
184                 if (resource.isTransactionActive() == true) {
185                     if (commit) {
186                         resource.commitTransaction();
187                     } else {
188                         resource.rollbackTransaction();
189                     }
190                 }
191             }
192         }
193         closeResources();
194         status = commit ? STATUS_COMMITTED : STATUS_ROLLEDBACK;
195         manager.removeTransaction(this);
196     }
197
198     protected void closeResources() {
199         Iterator JavaDoc it = resources.values().iterator();
200         while (it.hasNext()) {
201             JtxResource resource = (JtxResource) it.next();
202             resource.closeResource();
203         }
204         resources.clear();
205     }
206
207
208     // ---------------------------------------------------------------- resources
209

210     /**
211      * Attach a new transaction resource to current transaction
212      * and begins its transaction. There will be only one resource
213      * of its type per transaction.
214      */

215     protected void attachResource(String JavaDoc resourceType, JtxResource resource) {
216         if (resources.put(resourceType, resource) != null) {
217             throw new JtxException("Resource of the same type already attached to this transaction.");
218         }
219         if (manager.isSingleResourceTransaction() == true) {
220             if (resources.size() != 1) {
221                 throw new JtxException("Only one resource may be attached to transactions created by this transaction manager.");
222             }
223         }
224         if (status != STATUS_AUTOCOMMIT) {
225             resource.beginTransaction(mode);
226         }
227     }
228
229     /**
230      * Returns a resource attached to current transaction.
231      * If resource is not yet attached to a transaction, it will
232      * be created and attached.
233      *
234      * Note: transaction may be in {@link #STATUS_AUTOCOMMIT}.
235      * @see JtxTransactionManager#getResource(String)
236      */

237     public JtxResource getResource(String JavaDoc resourceType) {
238         JtxResource resource = (JtxResource) resources.get(resourceType);
239         if (resource == null) {
240             JtxResourceManager resourceManager = manager.lookupResourceManager(resourceType);
241             resource = resourceManager.createResource();
242             attachResource(resourceType, resource);
243         }
244         return resource;
245     }
246 }
247
Popular Tags