001: /*
002: * CoadunationHibernate: The hibernate configuration.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * HibernateUtil.java
020: */
021:
022: package com.rift.coad.hibernate.util;
023:
024: // java imports
025: import java.util.StringTokenizer;
026: import java.util.Map;
027: import java.util.HashMap;
028: import java.util.concurrent.ConcurrentHashMap;
029: import javax.naming.Context;
030: import javax.naming.InitialContext;
031: import javax.transaction.Transaction;
032: import javax.transaction.TransactionManager;
033: import javax.transaction.xa.XAException;
034: import javax.transaction.xa.XAResource;
035: import javax.transaction.xa.Xid;
036:
037: // logging import
038: import org.apache.log4j.Logger;
039:
040: // hibernate imports
041: import org.hibernate.*;
042: import org.hibernate.cfg.*;
043:
044: /**
045: * This class sets up a hibernate SessionFactory.
046: */
047: public class HibernateUtil implements XAResource {
048:
049: // class constants
050: public final static String RESOURCES_CONFIG = "hibernate_resource_config";
051: public final static String HIBERNATE_SQL = "hibernate_sql";
052: public final static String DB_SOURCE = "db_datasource";
053: public final static String HBM2DDL = "hibernate_hbm2ddl_auto";
054: public final static String TRANSACTION_TIMEOUT = "transaction_timeout";
055: public final static int DEFAULT_TRANSACTION_TIMEOUT = 180000;
056:
057: // class singleton
058: private static Map singletons = new HashMap();
059:
060: // the logger reference
061: protected static Logger log = Logger.getLogger(HibernateUtil.class
062: .getName());
063:
064: // class private member variables
065: private int timeout = 0;
066: private Context context = null;
067: private SessionFactory sessionFactory = null;
068: private Map sessions = new ConcurrentHashMap();
069: private ThreadLocal currentSession = new ThreadLocal();
070:
071: /**
072: * The constructor of the hibernate util object.
073: *
074: * @param configId The identifier of the configuration.
075: * @exception MessageServiceException
076: */
077: private HibernateUtil(Class configId) throws HibernateUtilException {
078: try {
079: // retrieve the initial context
080: context = new InitialContext();
081:
082: // Retrieve the configuration for the message service implementation
083: com.rift.coad.lib.configuration.Configuration coadConfig = com.rift.coad.lib.configuration.ConfigurationFactory
084: .getInstance().getConfig(configId);
085:
086: // retrieve the default transaction timeout
087: timeout = (int) coadConfig.getLong(TRANSACTION_TIMEOUT,
088: DEFAULT_TRANSACTION_TIMEOUT);
089:
090: // switch off jdbc 2 support
091: org.hibernate.cfg.Configuration config = null;
092: if (coadConfig.getBoolean("JDBC2_SUPPORT", true)) {
093: // init the configuration for the hibernate object.
094: config = new org.hibernate.cfg.Configuration()
095: .configure(
096: coadConfig.getString(RESOURCES_CONFIG))
097: .setProperty("hibernate.dialect",
098: coadConfig.getString("db_dialect"))
099: .setProperty("hibernate.connection.datasource",
100: coadConfig.getString(DB_SOURCE))
101: .setProperty(
102: "hibernate.current_session_context_class",
103: "jta")
104: .setProperty(
105: "hibernate.transaction.factory_class",
106: "org.hibernate.transaction.JTATransactionFactory")
107: .setProperty(
108: "hibernate.transaction.manager_lookup_class",
109: "org.hibernate.transaction.JOTMTransactionManagerLookup")
110: .setProperty("hibernate.connection.autocommit",
111: "false")
112: .setProperty("hibernate.cache.provider_class",
113: "org.hibernate.cache.NoCacheProvider")
114: .setProperty(
115: "hibernate.show_sql",
116: coadConfig.getString(HIBERNATE_SQL,
117: "false"))
118: .setProperty("hibernate.hbm2ddl.auto",
119: coadConfig.getString(HBM2DDL, "update"));
120: } else {
121: // init the configuration for the hibernate object.
122: // without JDBC 2 driver support
123: config = new org.hibernate.cfg.Configuration()
124: .configure(
125: coadConfig.getString(RESOURCES_CONFIG))
126: .setProperty("hibernate.dialect",
127: coadConfig.getString("db_dialect"))
128: .setProperty("hibernate.connection.datasource",
129: coadConfig.getString(DB_SOURCE))
130: .setProperty(
131: "hibernate.current_session_context_class",
132: "jta")
133: .setProperty(
134: "hibernate.transaction.factory_class",
135: "org.hibernate.transaction.JTATransactionFactory")
136: .setProperty(
137: "hibernate.transaction.manager_lookup_class",
138: "org.hibernate.transaction.JOTMTransactionManagerLookup")
139: .setProperty("hibernate.connection.autocommit",
140: "false")
141: .setProperty("hibernate.cache.provider_class",
142: "org.hibernate.cache.NoCacheProvider")
143: .setProperty("hibernate.jdbc.batch_size", "0")
144: .setProperty(
145: "hibernate.jdbc.use_scrollable_resultsets",
146: "false")
147: .setProperty(
148: "hibernate.show_sql",
149: coadConfig.getString(HIBERNATE_SQL,
150: "false"))
151: .setProperty("hibernate.hbm2ddl.auto",
152: coadConfig.getString(HBM2DDL, "update"));
153: }
154:
155: sessionFactory = config.buildSessionFactory();
156: } catch (Throwable ex) {
157: log.error("Initial SessionFactory " + "creation failed: "
158: + ex.getMessage(), ex);
159: throw new HibernateUtilException("Initial SessionFactory "
160: + "creation failed: " + ex.getMessage(), ex);
161: }
162: }
163:
164: /**
165: * Configures up hibernate programmatically using Coadunations configuration
166: * file.
167: *
168: * @return The reference to the hibernate util singleton.
169: * @param configId The id of the configuration.
170: * @excepiton MessageServiceException
171: */
172: public synchronized static HibernateUtil getInstance(Class configId)
173: throws HibernateUtilException {
174: HibernateUtil singleton = null;
175: if (!singletons.containsKey(configId)) {
176: singleton = new HibernateUtil(configId);
177: singletons.put(configId, singleton);
178: } else {
179: singleton = (HibernateUtil) singletons.get(configId);
180: }
181: return singleton;
182: }
183:
184: /**
185: * This method returns a reference to the session factory object.
186: *
187: * @return Returns the current session for this thread.
188: * @exception
189: */
190: public Session getSession() throws HibernateUtilException {
191: try {
192: Transaction transaction = getTransaction();
193: transaction.enlistResource(this );
194: return (Session) currentSession.get();
195: } catch (HibernateUtilException ex) {
196: throw ex;
197: } catch (Exception ex) {
198: log.error(
199: "Failed to retrieve the current session for this thread : "
200: + ex.getMessage(), ex);
201: throw new HibernateUtilException(
202: "Failed to retrieve the current session for this thread : "
203: + ex.getMessage(), ex);
204: }
205: }
206:
207: /**
208: * This method is responsible for handling the committing of a transaction
209: * identified by the xid.
210: *
211: * @param xid The id of the transaction to commit.
212: * @param onePhase If true a one phase commit should be used.
213: * @exception XAException
214: */
215: public void commit(Xid xid, boolean b) throws XAException {
216: if (this .sessions.containsKey(xid)) {
217: Session session = (Session) sessions.get(xid);
218: sessions.remove(xid);
219: try {
220: session.connection().setAutoCommit(true);
221: } catch (Exception ex) {
222: log
223: .error(
224: "Failed to reset the auto commit flag on the "
225: + "connection : "
226: + ex.getMessage(), ex);
227: }
228: }
229: }
230:
231: /**
232: * The resource manager has dissociated this object from the transaction.
233: *
234: * @param xid The id of the transaction that is getting ended.
235: * @param flags The flags associated with this operation.
236: * @exception XAException
237: */
238: public void end(Xid xid, int flags) throws XAException {
239: }
240:
241: /**
242: * The transaction has been completed and must be forgotten.
243: *
244: * @param xid The id of the transaction to forget.
245: * @exception XAException
246: */
247: public void forget(Xid xid) throws XAException {
248: if (this .sessions.containsKey(xid)) {
249: Session session = (Session) sessions.get(xid);
250: sessions.remove(xid);
251: try {
252: session.connection().setAutoCommit(true);
253: } catch (Exception ex) {
254: log
255: .error(
256: "Failed to reset the auto commit flag on the "
257: + "connection : "
258: + ex.getMessage(), ex);
259: }
260: }
261: }
262:
263: /**
264: * This method returns the transaction timeout for this object.
265: *
266: * @return The int containing the transaction timeout.
267: * @exception XAException
268: */
269: public int getTransactionTimeout() throws XAException {
270: return timeout;
271: }
272:
273: /**
274: * This method returns true if this object is the resource manager getting
275: * queried.
276: *
277: * @return TRUE if this is the resource manager, FALSE if not.
278: * @param xaResource The resource to perform the check against.
279: * @exception XAException
280: */
281: public boolean isSameRM(XAResource xAResource) throws XAException {
282: return this == xAResource;
283: }
284:
285: /**
286: * This is called before a transaction is committed.
287: *
288: * @return The results of the transaction.
289: * @param xid The id of the transaction to check against.
290: * @exception XAException
291: */
292: public int prepare(Xid xid) throws XAException {
293: return XAResource.XA_OK;
294: }
295:
296: /**
297: * This method returns the list of transaction branches for this resource
298: * manager.
299: *
300: * @return The list of resource branches.
301: * @param flags The flags
302: * @exception XAException
303: */
304: public Xid[] recover(int flags) throws XAException {
305: return null;
306: }
307:
308: /**
309: * This method is called to roll back the specified transaction.
310: *
311: * @param xid The id of the transaction to roll back.
312: * @exception XAException
313: */
314: public void rollback(Xid xid) throws XAException {
315: if (this .sessions.containsKey(xid)) {
316: Session session = (Session) sessions.get(xid);
317: sessions.remove(xid);
318: try {
319: session.connection().setAutoCommit(true);
320: } catch (Exception ex) {
321: log
322: .error(
323: "Failed to reset the auto commit flag on the "
324: + "connection : "
325: + ex.getMessage(), ex);
326: }
327:
328: }
329: }
330:
331: /**
332: * This method sets the transaction timeout for this resource manager.
333: *
334: * @return TRUE if the transaction timeout can be set successfully.
335: * @param transactionTimeout The new transaction timeout value.
336: * @exception XAException
337: */
338: public boolean setTransactionTimeout(int transactionTimeout)
339: throws XAException {
340: timeout = transactionTimeout;
341: return true;
342: }
343:
344: /**
345: * This method is called to start a transaction on a resource manager.
346: *
347: * @param xid The id of the new transaction.
348: * @param flags The flags associated with the transaction.
349: * @exception XAException
350: */
351: public void start(Xid xid, int i) throws XAException {
352: Session session = null;
353: if (this .sessions.containsKey(xid)) {
354: session = (Session) sessions.get(xid);
355: } else {
356: try {
357: session = sessionFactory.getCurrentSession();
358: session.connection().setAutoCommit(false);
359: sessions.put(xid, session);
360: } catch (Exception ex) {
361: log.error("Failed to start the transaction : "
362: + ex.getMessage(), ex);
363: throw new XAException(
364: "Failed to start the transaction : "
365: + ex.getMessage());
366: }
367: }
368: this .currentSession.set(session);
369: }
370:
371: /**
372: * This method returns the transaction for this thread.
373: *
374: * @return The transaction for this thread.
375: * @exception HibernateUtilException
376: */
377: private Transaction getTransaction() throws HibernateUtilException {
378: try {
379: TransactionManager transactionManager = (TransactionManager) context
380: .lookup("java:comp/TransactionManager");
381: return transactionManager.getTransaction();
382: } catch (Exception ex) {
383: log.error(
384: "Failed to retrieve the current transaction because : "
385: + ex.getMessage(), ex);
386: // Make sure you log the exception, as it might be swallowed
387: throw new HibernateUtilException(
388: "Failed to retrieve the current transaction because : "
389: + ex.getMessage(), ex);
390: }
391: }
392: }
|