KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > toplink > SessionFactoryUtils


1 /*
2  * Copyright 2002-2006 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
17 package org.springframework.orm.toplink;
18
19 import oracle.toplink.exceptions.ConcurrencyException;
20 import oracle.toplink.exceptions.ConversionException;
21 import oracle.toplink.exceptions.DatabaseException;
22 import oracle.toplink.exceptions.OptimisticLockException;
23 import oracle.toplink.exceptions.QueryException;
24 import oracle.toplink.exceptions.TopLinkException;
25 import oracle.toplink.sessions.Session;
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28
29 import org.springframework.dao.ConcurrencyFailureException;
30 import org.springframework.dao.DataAccessException;
31 import org.springframework.dao.DataAccessResourceFailureException;
32 import org.springframework.dao.TypeMismatchDataAccessException;
33 import org.springframework.transaction.support.TransactionSynchronizationAdapter;
34 import org.springframework.transaction.support.TransactionSynchronizationManager;
35 import org.springframework.util.Assert;
36
37 /**
38  * Helper class featuring methods for TopLink Session handling,
39  * allowing for reuse of TopLink Session instances within transactions.
40  * Also provides support for exception translation.
41  *
42  * <p>Mainly intended for internal use within the framework.
43  *
44  * @author Juergen Hoeller
45  * @author <a HREF="mailto:james.x.clark@oracle.com">James Clark</a>
46  * @since 1.2
47  */

48 public abstract class SessionFactoryUtils {
49
50     private static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
51
52
53     /**
54      * Get a TopLink Session for the given SessionFactory. Is aware of and will
55      * return any existing corresponding Session bound to the current thread, for
56      * example when using TopLinkTransactionManager. Will create a new Session
57      * otherwise, if "allowCreate" is <code>true</code>.
58      * <p>This is the <code>getSession</code> method used by typical data access code,
59      * in combination with <code>releaseSession</code> called when done with
60      * the Session. Note that TopLinkTemplate allows to write data access code
61      * without caring about such resource handling.
62      * @param sessionFactory TopLink SessionFactory to create the session with
63      * @param allowCreate if a non-transactional Session should be created when no
64      * transactional Session can be found for the current thread
65      * @return the TopLink Session
66      * @throws DataAccessResourceFailureException if the Session couldn't be created
67      * @throws IllegalStateException if no thread-bound Session found and
68      * "allowCreate" is <code>false</code>
69      * @see #releaseSession
70      * @see TopLinkTemplate
71      */

72     public static Session getSession(SessionFactory sessionFactory, boolean allowCreate)
73             throws DataAccessResourceFailureException, IllegalStateException JavaDoc {
74
75         try {
76             return doGetSession(sessionFactory, allowCreate);
77         }
78         catch (TopLinkException ex) {
79             throw new DataAccessResourceFailureException("Could not open TopLink Session", ex);
80         }
81     }
82
83     /**
84      * Get a TopLink Session for the given SessionFactory. Is aware of and will
85      * return any existing corresponding Session bound to the current thread, for
86      * example when using TopLinkTransactionManager. Will create a new Session
87      * otherwise, if "allowCreate" is <code>true</code>.
88      * <p>Same as <code>getSession</code>, but throwing the original TopLinkException.
89      * @param sessionFactory TopLink SessionFactory to create the session with
90      * @param allowCreate if a non-transactional Session should be created when no
91      * transactional Session can be found for the current thread
92      * @return the TopLink Session
93      * @throws TopLinkException if the Session couldn't be created
94      * @throws IllegalStateException if no thread-bound Session found and
95      * "allowCreate" is <code>false</code>
96      * @see #releaseSession
97      * @see TopLinkTemplate
98      */

99     public static Session doGetSession(SessionFactory sessionFactory, boolean allowCreate)
100             throws TopLinkException, IllegalStateException JavaDoc {
101
102         Assert.notNull(sessionFactory, "No SessionFactory specified");
103
104         SessionHolder sessionHolder =
105                 (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
106         if (sessionHolder != null) {
107             return sessionHolder.getSession();
108         }
109
110         if (!allowCreate && !TransactionSynchronizationManager.isSynchronizationActive()) {
111             throw new IllegalStateException JavaDoc("No TopLink Session bound to thread, " +
112                     "and configuration does not allow creation of non-transactional one here");
113         }
114
115         logger.debug("Creating TopLink Session");
116         Session session = sessionFactory.createSession();
117
118         if (TransactionSynchronizationManager.isSynchronizationActive()) {
119             logger.debug("Registering new Spring transaction synchronization for new TopLink Session");
120             // Use same Session for further TopLink actions within the transaction.
121
// Thread object will get removed by synchronization at transaction completion.
122
sessionHolder = new SessionHolder(session);
123             sessionHolder.setSynchronizedWithTransaction(true);
124             TransactionSynchronizationManager.registerSynchronization(
125                     new SessionSynchronization(sessionHolder, sessionFactory));
126             TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
127         }
128
129         return session;
130     }
131
132     /**
133      * Return whether the given TopLink Session is transactional, that is,
134      * bound to the current thread by Spring's transaction facilities.
135      * @param session the TopLink Session to check
136      * @param sessionFactory TopLink SessionFactory that the Session was created with
137      * (can be <code>null</code>)
138      * @return whether the Session is transactional
139      */

140     public static boolean isSessionTransactional(Session session, SessionFactory sessionFactory) {
141         if (sessionFactory == null) {
142             return false;
143         }
144         SessionHolder sessionHolder =
145                 (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
146         return (sessionHolder != null && session == sessionHolder.getSession());
147     }
148
149     /**
150      * Convert the given TopLinkException to an appropriate exception from the
151      * <code>org.springframework.dao</code> hierarchy.
152      * @param ex TopLinkException that occured
153      * @return the corresponding DataAccessException instance
154      */

155     public static DataAccessException convertTopLinkAccessException(TopLinkException ex) {
156         if (ex instanceof DatabaseException) {
157             // SQLException during TopLink access: only passed in here from custom code,
158
// as TopLinkTemplate will use SQLExceptionTranslator-based handling.
159
return new TopLinkJdbcException((DatabaseException) ex);
160         }
161         if (ex instanceof OptimisticLockException) {
162             return new TopLinkOptimisticLockingFailureException((OptimisticLockException) ex);
163         }
164         if (ex instanceof QueryException) {
165             return new TopLinkQueryException((QueryException) ex);
166         }
167         if (ex instanceof ConcurrencyException) {
168             return new ConcurrencyFailureException(ex.getMessage(), ex);
169         }
170         if (ex instanceof ConversionException) {
171             return new TypeMismatchDataAccessException(ex.getMessage(), ex);
172         }
173         // fallback
174
return new TopLinkSystemException(ex);
175     }
176
177     /**
178      * Close the given Session, created via the given factory,
179      * if it is not managed externally (i.e. not bound to the thread).
180      * @param session the TopLink Session to close
181      * @param sessionFactory TopLink SessionFactory that the Session was created with
182      * (can be <code>null</code>)
183      */

184     public static void releaseSession(Session session, SessionFactory sessionFactory) {
185         if (session == null) {
186             return;
187         }
188         // Only release non-transactional Sessions.
189
if (!isSessionTransactional(session, sessionFactory)) {
190             doRelease(session);
191         }
192     }
193
194     /**
195      * Perform the actual releasing of the TopLink Session.
196      * @param session the TopLink Session to release
197      */

198     private static void doRelease(Session session) {
199         if (session != null) {
200             logger.debug("Closing TopLink Session");
201             try {
202                 session.release();
203             }
204             catch (TopLinkException ex) {
205                 logger.debug("Could not close TopLink Session", ex);
206             }
207             catch (Throwable JavaDoc ex) {
208                 logger.debug("Unexpected exception on closing TopLink Session", ex);
209             }
210         }
211     }
212
213
214     /**
215      * Callback for resource cleanup at the end of a Spring-managed JTA transaction,
216      * i.e. when participating in a JtaTransactionManager transaction.
217      * @see org.springframework.transaction.jta.JtaTransactionManager
218      */

219     private static class SessionSynchronization extends TransactionSynchronizationAdapter {
220
221         private final SessionHolder sessionHolder;
222
223         private final SessionFactory sessionFactory;
224
225         private boolean holderActive = true;
226
227         private SessionSynchronization(SessionHolder sessionHolder, SessionFactory sessionFactory) {
228             this.sessionHolder = sessionHolder;
229             this.sessionFactory = sessionFactory;
230         }
231
232         public void suspend() {
233             if (this.holderActive) {
234                 TransactionSynchronizationManager.unbindResource(this.sessionFactory);
235             }
236         }
237
238         public void resume() {
239             if (this.holderActive) {
240                 TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
241             }
242         }
243
244         public void beforeCompletion() {
245             TransactionSynchronizationManager.unbindResource(this.sessionFactory);
246             this.holderActive = false;
247         }
248
249         public void afterCompletion(int status) {
250             releaseSession(this.sessionHolder.getSession(), this.sessionFactory);
251         }
252     }
253
254 }
255
Popular Tags