Source Code Cross Referenced for ThreadLocalSessionContext.java in  » Database-ORM » hibernate » org » hibernate » context » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » hibernate » org.hibernate.context 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.hibernate.context;
002:
003:        import java.io.IOException;
004:        import java.io.ObjectInputStream;
005:        import java.io.ObjectOutputStream;
006:        import java.io.Serializable;
007:        import java.lang.reflect.InvocationHandler;
008:        import java.lang.reflect.InvocationTargetException;
009:        import java.lang.reflect.Method;
010:        import java.lang.reflect.Proxy;
011:        import java.util.HashMap;
012:        import java.util.Map;
013:        import javax.transaction.Synchronization;
014:
015:        import org.apache.commons.logging.Log;
016:        import org.apache.commons.logging.LogFactory;
017:        import org.hibernate.ConnectionReleaseMode;
018:        import org.hibernate.HibernateException;
019:        import org.hibernate.SessionFactory;
020:        import org.hibernate.classic.Session;
021:        import org.hibernate.engine.SessionFactoryImplementor;
022:
023:        /**
024:         * A {@link CurrentSessionContext} impl which scopes the notion of current
025:         * session by the current thread of execution.  Unlike the JTA counterpart,
026:         * threads do not give us a nice hook to perform any type of cleanup making
027:         * it questionable for this impl to actually generate Session instances.  In
028:         * the interest of usability, it was decided to have this default impl
029:         * actually generate a session upon first request and then clean it up
030:         * after the {@link org.hibernate.Transaction} associated with that session
031:         * is committed/rolled-back.  In order for ensuring that happens, the sessions
032:         * generated here are unusable until after {@link Session#beginTransaction()}
033:         * has been called. If <tt>close()</tt> is called on a session managed by
034:         * this class, it will be automatically unbound.
035:         * <p/>
036:         * Additionally, the static {@link #bind} and {@link #unbind} methods are
037:         * provided to allow application code to explicitly control opening and
038:         * closing of these sessions.  This, with some from of interception,
039:         * is the preferred approach.  It also allows easy framework integration
040:         * and one possible approach for implementing long-sessions.
041:         * <p/>
042:         * The {@link #buildOrObtainSession}, {@link #isAutoCloseEnabled},
043:         * {@link #isAutoFlushEnabled}, {@link #getConnectionReleaseMode}, and
044:         * {@link #buildCleanupSynch} methods are all provided to allow easy
045:         * subclassing (for long- running session scenarios, for example).
046:         *
047:         * @author <a href="mailto:steve@hibernate.org">Steve Ebersole </a>
048:         */
049:        public class ThreadLocalSessionContext implements  CurrentSessionContext {
050:
051:            private static final Log log = LogFactory
052:                    .getLog(ThreadLocalSessionContext.class);
053:            private static final Class[] SESS_PROXY_INTERFACES = new Class[] {
054:                    org.hibernate.classic.Session.class,
055:                    org.hibernate.engine.SessionImplementor.class,
056:                    org.hibernate.jdbc.JDBCContext.Context.class,
057:                    org.hibernate.event.EventSource.class };
058:
059:            /**
060:             * A ThreadLocal maintaining current sessions for the given execution thread.
061:             * The actual ThreadLocal variable is a java.util.Map to account for
062:             * the possibility for multiple SessionFactorys being used during execution
063:             * of the given thread.
064:             */
065:            private static final ThreadLocal context = new ThreadLocal();
066:
067:            protected final SessionFactoryImplementor factory;
068:
069:            public ThreadLocalSessionContext(SessionFactoryImplementor factory) {
070:                this .factory = factory;
071:            }
072:
073:            public final Session currentSession() throws HibernateException {
074:                Session current = existingSession(factory);
075:                if (current == null) {
076:                    current = buildOrObtainSession();
077:                    // register a cleanup synch
078:                    current.getTransaction().registerSynchronization(
079:                            buildCleanupSynch());
080:                    // wrap the session in the transaction-protection proxy
081:                    if (needsWrapping(current)) {
082:                        current = wrap(current);
083:                    }
084:                    // then bind it
085:                    doBind(current, factory);
086:                }
087:                return current;
088:            }
089:
090:            private boolean needsWrapping(Session session) {
091:                // try to make sure we don't wrap and already wrapped session
092:                return session != null
093:                        && !Proxy.isProxyClass(session.getClass())
094:                        || (Proxy.getInvocationHandler(session) != null && !(Proxy
095:                                .getInvocationHandler(session) instanceof  TransactionProtectionWrapper));
096:            }
097:
098:            protected SessionFactoryImplementor getFactory() {
099:                return factory;
100:            }
101:
102:            /**
103:             * Strictly provided for subclassing purposes; specifically to allow long-session
104:             * support.
105:             * <p/>
106:             * This implementation always just opens a new session.
107:             *
108:             * @return the built or (re)obtained session.
109:             */
110:            protected Session buildOrObtainSession() {
111:                return factory.openSession(null, isAutoFlushEnabled(),
112:                        isAutoCloseEnabled(), getConnectionReleaseMode());
113:            }
114:
115:            protected CleanupSynch buildCleanupSynch() {
116:                return new CleanupSynch(factory);
117:            }
118:
119:            /**
120:             * Mainly for subclass usage.  This impl always returns true.
121:             *
122:             * @return Whether or not the the session should be closed by transaction completion.
123:             */
124:            protected boolean isAutoCloseEnabled() {
125:                return true;
126:            }
127:
128:            /**
129:             * Mainly for subclass usage.  This impl always returns true.
130:             *
131:             * @return Whether or not the the session should be flushed prior transaction completion.
132:             */
133:            protected boolean isAutoFlushEnabled() {
134:                return true;
135:            }
136:
137:            /**
138:             * Mainly for subclass usage.  This impl always returns after_transaction.
139:             *
140:             * @return The connection release mode for any built sessions.
141:             */
142:            protected ConnectionReleaseMode getConnectionReleaseMode() {
143:                return factory.getSettings().getConnectionReleaseMode();
144:            }
145:
146:            protected Session wrap(Session session) {
147:                TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper(
148:                        session);
149:                Session wrapped = (Session) Proxy.newProxyInstance(
150:                        Session.class.getClassLoader(), SESS_PROXY_INTERFACES,
151:                        wrapper);
152:                // yick!  need this for proper serialization/deserialization handling...
153:                wrapper.setWrapped(wrapped);
154:                return wrapped;
155:            }
156:
157:            /**
158:             * Associates the given session with the current thread of execution.
159:             *
160:             * @param session The session to bind.
161:             */
162:            public static void bind(org.hibernate.Session session) {
163:                SessionFactory factory = session.getSessionFactory();
164:                cleanupAnyOrphanedSession(factory);
165:                doBind(session, factory);
166:            }
167:
168:            private static void cleanupAnyOrphanedSession(SessionFactory factory) {
169:                Session orphan = doUnbind(factory, false);
170:                if (orphan != null) {
171:                    log
172:                            .warn("Already session bound on call to bind(); make sure you clean up your sessions!");
173:                    try {
174:                        if (orphan.getTransaction() != null
175:                                && orphan.getTransaction().isActive()) {
176:                            try {
177:                                orphan.getTransaction().rollback();
178:                            } catch (Throwable t) {
179:                                log
180:                                        .debug(
181:                                                "Unable to rollback transaction for orphaned session",
182:                                                t);
183:                            }
184:                        }
185:                        orphan.close();
186:                    } catch (Throwable t) {
187:                        log.debug("Unable to close orphaned session", t);
188:                    }
189:                }
190:            }
191:
192:            /**
193:             * Unassociate a previously bound session from the current thread of execution.
194:             *
195:             * @return The session which was unbound.
196:             */
197:            public static Session unbind(SessionFactory factory) {
198:                return doUnbind(factory, true);
199:            }
200:
201:            private static Session existingSession(SessionFactory factory) {
202:                Map sessionMap = sessionMap();
203:                if (sessionMap == null) {
204:                    return null;
205:                } else {
206:                    return (Session) sessionMap.get(factory);
207:                }
208:            }
209:
210:            protected static Map sessionMap() {
211:                return (Map) context.get();
212:            }
213:
214:            private static void doBind(org.hibernate.Session session,
215:                    SessionFactory factory) {
216:                Map sessionMap = sessionMap();
217:                if (sessionMap == null) {
218:                    sessionMap = new HashMap();
219:                    context.set(sessionMap);
220:                }
221:                sessionMap.put(factory, session);
222:            }
223:
224:            private static Session doUnbind(SessionFactory factory,
225:                    boolean releaseMapIfEmpty) {
226:                Map sessionMap = sessionMap();
227:                Session session = null;
228:                if (sessionMap != null) {
229:                    session = (Session) sessionMap.remove(factory);
230:                    if (releaseMapIfEmpty && sessionMap.isEmpty()) {
231:                        context.set(null);
232:                    }
233:                }
234:                return session;
235:            }
236:
237:            /**
238:             * JTA transaction synch used for cleanup of the internal session map.
239:             */
240:            protected static class CleanupSynch implements  Synchronization,
241:                    Serializable {
242:                protected final SessionFactory factory;
243:
244:                public CleanupSynch(SessionFactory factory) {
245:                    this .factory = factory;
246:                }
247:
248:                public void beforeCompletion() {
249:                }
250:
251:                public void afterCompletion(int i) {
252:                    unbind(factory);
253:                }
254:            }
255:
256:            private class TransactionProtectionWrapper implements 
257:                    InvocationHandler, Serializable {
258:                private final Session realSession;
259:                private Session wrappedSession;
260:
261:                public TransactionProtectionWrapper(Session realSession) {
262:                    this .realSession = realSession;
263:                }
264:
265:                public Object invoke(Object proxy, Method method, Object[] args)
266:                        throws Throwable {
267:                    try {
268:                        // If close() is called, guarantee unbind()
269:                        if ("close".equals(method.getName())) {
270:                            unbind(realSession.getSessionFactory());
271:                        } else if ("toString".equals(method.getName())
272:                                || "equals".equals(method.getName())
273:                                || "hashCode".equals(method.getName())
274:                                || "getStatistics".equals(method.getName())
275:                                || "isOpen".equals(method.getName())) {
276:                            // allow these to go through the the real session no matter what
277:                        } else if (!realSession.isOpen()) {
278:                            // essentially, if the real session is closed allow any
279:                            // method call to pass through since the real session
280:                            // will complain by throwing an appropriate exception;
281:                            // NOTE that allowing close() above has the same basic effect,
282:                            //   but we capture that there simply to perform the unbind...
283:                        } else if (!realSession.getTransaction().isActive()) {
284:                            // limit the methods available if no transaction is active
285:                            if ("beginTransaction".equals(method.getName())
286:                                    || "getTransaction"
287:                                            .equals(method.getName())
288:                                    || "isTransactionInProgress".equals(method
289:                                            .getName())
290:                                    || "setFlushMode".equals(method.getName())
291:                                    || "getSessionFactory".equals(method
292:                                            .getName())) {
293:                                log.trace("allowing method ["
294:                                        + method.getName()
295:                                        + "] in non-transacted context");
296:                            } else if ("reconnect".equals(method.getName())
297:                                    || "disconnect".equals(method.getName())) {
298:                                // allow these (deprecated) methods to pass through
299:                            } else {
300:                                throw new HibernateException(
301:                                        method.getName()
302:                                                + " is not valid without active transaction");
303:                            }
304:                        }
305:                        log.trace("allowing proxied method ["
306:                                + method.getName()
307:                                + "] to proceed to real session");
308:                        return method.invoke(realSession, args);
309:                    } catch (InvocationTargetException e) {
310:                        if (e.getTargetException() instanceof  RuntimeException) {
311:                            throw (RuntimeException) e.getTargetException();
312:                        } else {
313:                            throw e;
314:                        }
315:                    }
316:                }
317:
318:                public void setWrapped(Session wrapped) {
319:                    this .wrappedSession = wrapped;
320:                }
321:
322:                // serialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
323:
324:                private void writeObject(ObjectOutputStream oos)
325:                        throws IOException {
326:                    // if a ThreadLocalSessionContext-bound session happens to get
327:                    // serialized, to be completely correct, we need to make sure
328:                    // that unbinding of that session occurs.
329:                    oos.defaultWriteObject();
330:                    if (existingSession(factory) == wrappedSession) {
331:                        unbind(factory);
332:                    }
333:                }
334:
335:                private void readObject(ObjectInputStream ois)
336:                        throws IOException, ClassNotFoundException {
337:                    // on the inverse, it makes sense that if a ThreadLocalSessionContext-
338:                    // bound session then gets deserialized to go ahead and re-bind it to
339:                    // the ThreadLocalSessionContext session map.
340:                    ois.defaultReadObject();
341:                    realSession.getTransaction().registerSynchronization(
342:                            buildCleanupSynch());
343:                    doBind(wrappedSession, factory);
344:                }
345:            }
346:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.