KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > easybeans > persistence > TxEntityManagerHandler


1 /**
2  * EasyBeans
3  * Copyright (C) 2006 Bull S.A.S.
4  * Contact: easybeans@objectweb.org
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  * USA
20  *
21  * --------------------------------------------------------------------------
22  * $Id: TxEntityManagerHandler.java 326 2006-04-14 08:20:59Z benoitf $
23  * --------------------------------------------------------------------------
24  */

25
26 package org.objectweb.easybeans.persistence;
27
28 import java.util.HashMap JavaDoc;
29 import java.util.Map JavaDoc;
30
31 import javax.persistence.EntityManager;
32 import javax.persistence.EntityManagerFactory;
33 import javax.transaction.RollbackException JavaDoc;
34 import javax.transaction.Status JavaDoc;
35 import javax.transaction.SystemException JavaDoc;
36 import javax.transaction.Transaction JavaDoc;
37
38 import org.objectweb.easybeans.transaction.JTransactionManager;
39
40 /**
41  * This class is used to handle different entity manager for Transaction Scoped
42  * Persistence Context. It associates one EntityManager to a given transaction
43  * @author Florent Benoit
44  */

45 public class TxEntityManagerHandler {
46
47     /**
48      * EntityManager factory that will create entity manager.
49      */

50     private EntityManagerFactory entityManagerFactory = null;
51
52     /**
53      * Map between transactions and the entity manager.
54      */

55     private Map JavaDoc<Transaction JavaDoc, EntityManager> entityManagers = null;
56
57     /**
58      * Previous entity manager (must be kept). Used when there is no TX.
59      */

60     private ThreadLocal JavaDoc<EntityManager> previousEntityManager = new ThreadLocal JavaDoc<EntityManager>();
61
62     /**
63      * Entity Manager used for a single method call when there is no TX. An
64      * interceptor will request to create a new entity manager and will close it
65      * at the end of the method.
66      */

67     private ThreadLocal JavaDoc<EntityManager> threadEntityManager = new ThreadLocal JavaDoc<EntityManager>();
68
69     /**
70      * Build a new handler of these entity managers.
71      * @param entityManagerFactory Factory used to create the entity manager (if
72      * no entity manager is already associated to the current
73      * transaction)
74      */

75     public TxEntityManagerHandler(final EntityManagerFactory entityManagerFactory) {
76         this.entityManagerFactory = entityManagerFactory;
77         this.entityManagers = new HashMap JavaDoc<Transaction JavaDoc, EntityManager>();
78     }
79
80     /**
81      * Gets the current entity manager (or create one) for the given transaction
82      * if there is one.
83      * @return an entitymanager
84      */

85     public synchronized EntityManager getCurrent() {
86         EntityManager current = null;
87
88         // Get current transaction (if any)
89
Transaction JavaDoc currentTx = null;
90         try {
91             currentTx = JTransactionManager.getTransactionManager().getTransaction();
92         } catch (SystemException JavaDoc e) {
93             throw new IllegalStateException JavaDoc("Cannot get current transaction", e);
94         }
95
96         // get status of the current tx (if any)
97
int statusTx = Status.STATUS_UNKNOWN;
98         if (currentTx != null) {
99             try {
100                 statusTx = currentTx.getStatus();
101             } catch (SystemException JavaDoc e) {
102                 throw new IllegalStateException JavaDoc("Cannot get the status on the current transaction", e);
103             }
104         }
105         /**
106          * If the entity manager is called when no JTA transaction is in
107          * progress, a persistence context is created and destroyed to service
108          * the method call only, and any entities loaded from the database will
109          * immediately become detached at the end of the method call.
110          */

111         if (currentTx == null || !(statusTx == Status.STATUS_ACTIVE)) {
112             return threadEntityManager.get();
113         }
114
115         current = entityManagers.get(currentTx);
116         /**
117          * If the entity manager is called and there is an existing persistence
118          * context bound to the current JTA transaction, the call takes place in
119          * that context.
120          */

121         if (current == null) {
122             /**
123              * If the entity manager is called and there is no persistence
124              * context associated with the current JTA transaction, a new
125              * persistence context will be created and bound to the JTA
126              * transaction, and the call will take place in that context.
127              */

128             current = buildNewTxEntityManager(currentTx);
129         }
130
131         return current;
132     }
133
134     /**
135      * Builds a new Entity manager for the given transaction.
136      * @param tx transaction on which associate the entity manager
137      * @return built entity manager.
138      */

139     private EntityManager buildNewTxEntityManager(final Transaction JavaDoc tx) {
140         EntityManager entityManager = entityManagerFactory.createEntityManager();
141
142         /**
143          * The persistence context is created and then associated with the
144          * current JTA transaction. The persistence context ends when the
145          * associated JTA transaction commits or rolls back,
146          */

147         try {
148             tx.registerSynchronization(new TxEntityManagerLifeCycle(entityManager, tx, this));
149         } catch (IllegalStateException JavaDoc e) {
150             throw new IllegalStateException JavaDoc("Cannot register Entity manager lifecycle", e);
151         } catch (RollbackException JavaDoc e) {
152             throw new IllegalStateException JavaDoc("Cannot register Entity manager lifecycle", e);
153         } catch (SystemException JavaDoc e) {
154             throw new IllegalStateException JavaDoc("Cannot register Entity manager lifecycle", e);
155         }
156
157         // add in the managed entitymanager
158
entityManagers.put(tx, entityManager);
159
160         return entityManager;
161     }
162
163     /**
164      * Builds a new Entity manager used when there is no transaction.
165      * @return built entity manager.
166      */

167     private EntityManager buildNoTxEntityManager() {
168         return entityManagerFactory.createEntityManager();
169     }
170
171     /**
172      * Release the entity manager associated to the given tx.
173      * @param tx tx to removed
174      */

175     public void release(final Transaction JavaDoc tx) {
176         entityManagers.remove(tx);
177     }
178
179     /**
180      * Sets the current entity manager (used when to transaction is active).
181      */

182     public void addCurrent() {
183         previousEntityManager.set(threadEntityManager.get());
184         threadEntityManager.set(buildNoTxEntityManager());
185     }
186
187     /**
188      * Sets back to the previous entity manager and close the current entity
189      * manager.
190      */

191     public void closeCurrentAndReturnToPrevious() {
192         EntityManager current = threadEntityManager.get();
193         // set to the previous one
194
threadEntityManager.set(previousEntityManager.get());
195
196         // close the current
197
if (current != null) {
198             current.close();
199         }
200
201     }
202 }
203
Popular Tags