/** * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations under * the License. * * The Original Code is OpenELIS code. * * Copyright (C) The Minnesota Department of Health. All Rights Reserved. */ package us.mn.state.health.lims.hibernate; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import us.mn.state.health.lims.common.exception.LIMSRuntimeException; import us.mn.state.health.lims.common.log.LogEvent; import us.mn.state.health.lims.hibernate.resources.interceptor.LIMSTrimDataInterceptor; /** * Basic Hibernate helper class, handles SessionFactory, Session and Transaction. * <p> * Uses a static initializer for the initial SessionFactory creation * and holds Session and Transactions in thread local variables. All * exceptions are wrapped in an unchecked InfrastructureException. * * @author christian@hibernate.org */ public class HibernateUtil { public static final String HIBERNATE_CFG_FILE_PROPERTY = "openELIS.hibernate.cfg"; private static Configuration configuration; private static SessionFactory sessionFactory; private static final ThreadLocal threadSession = new ThreadLocal(); private static final ThreadLocal threadTransaction = new ThreadLocal(); private static final ThreadLocal threadInterceptor = new ThreadLocal(); private static String CONFIG_FILE_LOCATION = "/us/mn/state/health/lims/hibernate/hibernate.cfg.xml"; private static String configFile = CONFIG_FILE_LOCATION; static { String testCfg = System.getProperty(HIBERNATE_CFG_FILE_PROPERTY); if (null != testCfg) { configFile = testCfg; } } static { try { configuration = new Configuration(); //bugzilla 1939 (trim changed data before update/insert) configuration.setInterceptor(new LIMSTrimDataInterceptor()); sessionFactory = configuration.configure(configFile).buildSessionFactory(); // We could also let Hibernate bind it to JNDI: // configuration.configure().buildSessionFactory() } catch (Throwable ex) { // We have to catch Throwable, otherwise we will miss // NoClassDefFoundError and other subclasses of Error //ex.printStackTrace(); //log.error("Building SessionFactory failed.", ex); //bugzilla 2154 LogEvent.logError("HibernateUtil","static constructor","Building SessionFactory failed. " + ex.toString()); throw new ExceptionInInitializerError(ex); } } /** * Returns the SessionFactory used for this static class. * * @return SessionFactory */ public static SessionFactory getSessionFactory() { /* Instead of a static variable, use JNDI: SessionFactory sessions = null; try { Context ctx = new InitialContext(); String jndiName = "java:hibernate/HibernateFactory"; sessions = (SessionFactory)ctx.lookup(jndiName); } catch (NamingException ex) { throw new InfrastructureException(ex); } return sessions; */ if( sessionFactory == null){ rebuildSessionFactory(); } return sessionFactory; } /** * Returns the original Hibernate configuration. * * @return Configuration */ public static Configuration getConfiguration() { return configuration; } /** * Rebuild the SessionFactory with the static Configuration. * */ public static void rebuildSessionFactory() throws LIMSRuntimeException { synchronized (sessionFactory) { try { sessionFactory = getConfiguration().buildSessionFactory(); } catch (Exception ex) { //bugzilla 2154 LogEvent.logError("HibernateUtil","rebuildSessionFactory()",ex.toString()); throw new LIMSRuntimeException("Error in rebuildSessionFactory()", ex); } } } /** * Rebuild the SessionFactory with the given Hibernate Configuration. * * @param cfg */ public static void rebuildSessionFactory(Configuration cfg) throws LIMSRuntimeException { synchronized (sessionFactory) { try { sessionFactory = cfg.buildSessionFactory(); configuration = cfg; } catch (Exception ex) { //bugzilla 2154 LogEvent.logError("HibernateUtil","rebuildSessionFactory()",ex.toString()); throw new LIMSRuntimeException("Error in rebuildSessionFactory()", ex); } } } /** * Retrieves the current Session local to the thread. * <p/> * If no Session is open, opens a new Session for the running thread. * * @return Session */ public static Session getSession() throws LIMSRuntimeException { Session s = (Session) threadSession.get(); try { if (s == null) { //bugzilla 2154 LogEvent.logDebug("HibernateUtil","getSession()","Opening new Session for this thread."); if (getInterceptor() != null) { LogEvent.logDebug("HibernateUtil","getSession()","Using interceptor: " + getInterceptor().getClass()); s = getSessionFactory().openSession(getInterceptor()); } else { s = getSessionFactory().openSession(); } threadSession.set(s); } } catch (HibernateException ex) { //bugzilla 2154 LogEvent.logError("HibernateUtil","getSession()",ex.toString()); throw new LIMSRuntimeException("Error in getSession()", ex); } return s; } /** * Closes the Session local to the thread. */ public static void closeSession() throws LIMSRuntimeException { try { Session s = (Session) threadSession.get(); threadSession.set(null); if (s != null && s.isOpen()) { //bugzilla 2154 LogEvent.logDebug("HibernateUtil","closeSession()","Closing Session of this thread."); s.close(); } } catch (HibernateException ex) { //bugzilla 2154 LogEvent.logError("HibernateUtil","closeSession()",ex.toString()); throw new LIMSRuntimeException("Error in closeSession()", ex); } } /** * Start a new database transaction. */ /* public static void beginTransaction() throws LIMSRuntimeException { Transaction tx = (Transaction) threadTransaction.get(); try { if (tx == null) { log.debug("Starting new database transaction in this thread."); tx = getSession().beginTransaction(); threadTransaction.set(tx); } } catch (HibernateException ex) { throw new LIMSRuntimeException("Error in beginTransaction()", ex); } } */ /** * Commit the database transaction. */ /* public static void commitTransaction() throws LIMSRuntimeException { Transaction tx = (Transaction) threadTransaction.get(); try { if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) { log.debug("Committing database transaction of this thread."); tx.commit(); } threadTransaction.set(null); } catch (HibernateException ex) { rollbackTransaction(); throw new LIMSRuntimeException("Error in commitTransaction()", ex); } } */ /** * Commit the database transaction. */ /* public static void rollbackTransaction() throws LIMSRuntimeException { Transaction tx = (Transaction) threadTransaction.get(); try { threadTransaction.set(null); if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) { log.debug( "Tyring to rollback database transaction of this thread."); tx.rollback(); } } catch (HibernateException ex) { throw new LIMSRuntimeException("Error in rollbackTransaction()", ex); } finally { closeSession(); } } */ /** * Reconnects a Hibernate Session to the current Thread. * * @param session The Hibernate Session to be reconnected. */ //public static void reconnect(Session session) throws LIMSRuntimeException { //try { //session.reconnect(); //threadSession.set(session); //} catch (HibernateException ex) { //throw new LIMSRuntimeException("Error in reconnect()", ex); //} //} /** * Disconnect and return Session from current Thread. * * @return Session the disconnected Session */ /* public static Session disconnectSession() throws LIMSRuntimeException { Session session = getSession(); try { threadSession.set(null); if (session.isConnected() && session.isOpen()) { session.disconnect(); } } catch (HibernateException ex) { throw new LIMSRuntimeException("Error in disconnectSession()", ex); } return session; } */ /** * Register a Hibernate interceptor with the current thread. * <p> * Every Session opened is opened with this interceptor after * registration. Has no effect if the current Session of the * thread is already open, effective on next close()/getSession(). */ public static void registerInterceptor(Interceptor interceptor) { threadInterceptor.set(interceptor); } private static Interceptor getInterceptor() { Interceptor interceptor = (Interceptor) threadInterceptor.get(); return interceptor; } }