001: /*
002: * JBoss, Home of Professional Open Source
003: * Copyright 2005, JBoss Inc., and individual contributors as indicated
004: * by the @authors tag. See the copyright.txt in the distribution for a
005: * full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jbpm.db;
023:
024: import java.sql.Connection;
025: import java.util.LinkedList;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.hibernate.HibernateException;
030: import org.hibernate.Session;
031: import org.hibernate.Transaction;
032: import org.jbpm.JbpmException;
033:
034: /**
035: * represents the connection to the jbpm database.
036: *
037: * You can obtain a DbSession with
038: * <pre>
039: * DbSession dbSession = dbSessionFactory.openDbSession();
040: * </pre>
041: * or
042: * <pre>
043: * Connection jdbcConnection = ...;
044: * DbSession dbSession = dbSessionFactory.openDbSession(jdbcConnection);
045: * </pre>
046: * The actual database operations are defined in the module sessions :
047: * <ul>
048: * <li>{@link org.jbpm.db.GraphSession}</li>
049: * <li>{@link org.jbpm.db.TaskMgmtSession}</li>
050: * <li>{@link org.jbpm.db.LoggingSession}</li>
051: * <li>{@link org.jbpm.db.FileSession}</li>
052: * </ul>
053: * The easiest way to obtain the operations is like this :
054: * <ul>
055: * <li><pre>jbpmSession.getGraphSession().someGraphDbMethod(...)</pre></li>
056: * <li><pre>jbpmSession.getTaskMgmtSession().someTaskDbMethod(...)</pre></li>
057: * <li><pre>jbpmSession.getLoggingSession().someLoggingDbMethod(...)</pre></li>
058: * <li><pre>jbpmSession.getContextSession().someFileDbMethod(...)</pre></li>
059: * <li><pre>jbpmSession.getFileSession().someFileDbMethod(...)</pre></li>
060: * </ul>
061: *
062: * @deprecated use {@link org.jbpm.tc.ContextBuilder} and {@link org.jbpm.tc.db.JbpmSessionContext} instead.
063: */
064: public class JbpmSession {
065:
066: static ThreadLocal currentJbpmSessionStack = new ThreadLocal();
067:
068: JbpmSessionFactory jbpmSessionFactory = null;
069: Session session = null;
070: Transaction transaction = null;
071:
072: GraphSession graphSession = null;
073: ContextSession contextSession = null;
074: TaskMgmtSession taskMgmtSession = null;
075: LoggingSession loggingSession = null;
076: JobSession jobSession = null;
077:
078: public JbpmSession(JbpmSessionFactory jbpmSessionFactory,
079: Session session) {
080: this .jbpmSessionFactory = jbpmSessionFactory;
081: this .session = session;
082: this .graphSession = new GraphSession(this );
083: this .contextSession = new ContextSession(this );
084: this .taskMgmtSession = new TaskMgmtSession(this );
085: this .loggingSession = new LoggingSession(this );
086:
087: pushCurrentSession();
088: }
089:
090: public JbpmSession(Session session) {
091: this .session = session;
092: this .graphSession = new GraphSession(this );
093: this .contextSession = new ContextSession(this );
094: this .taskMgmtSession = new TaskMgmtSession(this );
095: this .loggingSession = new LoggingSession(this );
096: }
097:
098: public JbpmSessionFactory getJbpmSessionFactory() {
099: return jbpmSessionFactory;
100: }
101:
102: public Connection getConnection() {
103: try {
104: return session.connection();
105: } catch (Exception e) {
106: log.error(e);
107: handleException();
108: throw new JbpmException(
109: "couldn't get the jdbc connection from hibernate",
110: e);
111: }
112: }
113:
114: public Session getSession() {
115: return session;
116: }
117:
118: public Transaction getTransaction() {
119: return transaction;
120: }
121:
122: public void beginTransaction() {
123: try {
124: transaction = session.beginTransaction();
125: } catch (Exception e) {
126: log.error(e);
127: handleException();
128: throw new JbpmException("couldn't begin a transaction", e);
129: }
130: }
131:
132: public void commitTransaction() {
133: if (transaction == null) {
134: throw new JbpmException(
135: "can't commit : no transaction started");
136: }
137: try {
138: session.flush();
139: transaction.commit();
140: } catch (Exception e) {
141: log.error(e);
142: handleException();
143: throw new JbpmException("couldn't commit transaction", e);
144: } finally {
145: transaction = null;
146: }
147: }
148:
149: public void rollbackTransaction() {
150: if (transaction == null) {
151: throw new JbpmException(
152: "can't rollback : no transaction started");
153: }
154: try {
155: transaction.rollback();
156: } catch (Exception e) {
157: log.error(e);
158: handleException();
159: throw new JbpmException("couldn't rollback transaction", e);
160: } finally {
161: transaction = null;
162: }
163: }
164:
165: public void commitTransactionAndClose() {
166: commitTransaction();
167: close();
168: }
169:
170: public void rollbackTransactionAndClose() {
171: rollbackTransaction();
172: close();
173: }
174:
175: public GraphSession getGraphSession() {
176: return graphSession;
177: }
178:
179: public ContextSession getContextSession() {
180: return contextSession;
181: }
182:
183: public TaskMgmtSession getTaskMgmtSession() {
184: return taskMgmtSession;
185: }
186:
187: public LoggingSession getLoggingSession() {
188: return loggingSession;
189: }
190:
191: public JobSession getJobSession() {
192: return jobSession;
193: }
194:
195: public void close() {
196: try {
197: if ((session != null) && (session.isOpen())) {
198: session.close();
199: }
200: } catch (Exception e) {
201: log.error(e);
202: throw new JbpmException(
203: "couldn't close the hibernate connection", e);
204: } finally {
205: popCurrentSession();
206: session = null;
207: }
208: }
209:
210: /**
211: * handles an exception that is thrown by hibernate.
212: */
213: void handleException() {
214: // if hibernate throws an exception,
215: if (transaction != null) {
216: try {
217: // the transaction should be rolled back
218: transaction.rollback();
219: } catch (HibernateException e) {
220: log.error("couldn't rollback hibernate transaction", e);
221: }
222: // and the hibernate session should be closed.
223: close();
224: }
225: }
226:
227: public void pushCurrentSession() {
228: LinkedList stack = (LinkedList) currentJbpmSessionStack.get();
229: if (stack == null) {
230: stack = new LinkedList();
231: currentJbpmSessionStack.set(stack);
232: }
233: stack.addFirst(this );
234: }
235:
236: /**
237: * @deprecated use {@link org.jbpm.tc.db.JbpmSessionContext} instead.
238: */
239: public static JbpmSession getCurrentJbpmSession() {
240: JbpmSession jbpmSession = null;
241: LinkedList stack = (LinkedList) currentJbpmSessionStack.get();
242: if ((stack != null) && (!stack.isEmpty())) {
243: jbpmSession = (JbpmSession) stack.getFirst();
244: }
245: return jbpmSession;
246: }
247:
248: public void popCurrentSession() {
249: LinkedList stack = (LinkedList) currentJbpmSessionStack.get();
250: if ((stack == null) || (stack.isEmpty())
251: || (stack.getFirst() != this )) {
252: log
253: .warn("can't pop current session: are you calling JbpmSession.close() multiple times ?");
254: } else {
255: stack.removeFirst();
256: }
257: }
258:
259: private static final Log log = LogFactory.getLog(JbpmSession.class);
260: }
|