Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version: 3.2.2 GA
Name and version of the database you are using: Db2 7.2 .5
J2EE Application Server : Webpshere 6.0.2.15
Hi,
We are using a customized
HibernateUtil class which is used by both transactional and non-transactional stateless session beans methods.
Here is our code of the HibernateUtil
-------------------------------------------------
package com.customer.ruby.utils.hibernate;
import java.sql.Timestamp;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.util.JTAHelper;
/**
* 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 RUBYBusinessException.
*
*/
public class HibernateUtil {
private static final Logger logger = Logger.getLogger(HibernateUtil.class);
private static Configuration configuration;
private static SessionFactory sessionFactory;
private static TimestampSynchronization iTsSyn = null;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTimeStamp = new ThreadLocal();
// Create the initial SessionFactory from the default configuration files or JNDI
static {
try {
configuration = new Configuration();
sessionFactory = configuration.configure("RUBYHibernate.cfg.xml")
.buildSessionFactory();
iTsSyn = new TimestampSynchronization(threadTimeStamp);
} catch (Throwable ex) {
// Log exceptions
logger.error("Building SessionFactory failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
*
*/
private HibernateUtil() {
super();
}
/**
* Returns the SessionFactory used for this static class.
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
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 HibernateException {
synchronized (sessionFactory) {
try {
sessionFactory = getConfiguration().buildSessionFactory();
} catch (Exception ex) {
throw new HibernateException(ex);
}
}
}
/**
* Rebuild the SessionFactory with the given Hibernate Configuration.
*
* @param cfg
*/
public static void rebuildSessionFactory(Configuration cfg)
throws HibernateException {
synchronized (sessionFactory) {
try {
sessionFactory = cfg.buildSessionFactory();
configuration = cfg;
} catch (Exception ex) {
throw new HibernateException(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 HibernateException {
Session sess = null;
SessionFactory sFactory = getSessionFactory();
try {
TransactionManager transactionManager = ((SessionFactoryImplementor)sFactory).getTransactionManager();
Transaction txn = null;
// Logs an error message if Transaction Manager is not found
if (transactionManager == null) {
logger.error( "No Transaction Manager found. Proceeding without transaction manager...");
}
else {
// Retrieves the Transaction associated with the current thread of execution
txn = transactionManager.getTransaction();
}
/*
* Checks if Transaction is NULL or NOT in progress, Returns
* the session in the threadSession Threadlocal instance
*/
if (txn == null || !JTAHelper.isInProgress(txn.getStatus())) {
sess = (Session)threadSession.get();
if(sess == null) {
/*
* Instatiates a new session if no existing session instance is found
* and sets it to the threadSession ThreadLocal instance in the current thread
*/
sess = sFactory.openSession();
threadSession.set(sess);
}
}
/*
* if Transaction is NOT NULL or in progress, returns the current session
*/
else {
sess = sFactory.getCurrentSession();
// Regsitering the TimestampSynchronization instance with the Transaction
txn.registerSynchronization(iTsSyn);
/*
* Populating the ThreadLocal threadTimestamp with the current Timestamp
*/
if(threadTimeStamp.get() == null) {
threadTimeStamp.set(new Timestamp(System.currentTimeMillis()));
}
}
return sess;
}
catch (HibernateException ex) {
throw new HibernateException(ex);
}
catch (Throwable t) {
throw new HibernateException( "Problem locating/validating JTA transaction", t );
}
}
/**
* @return
*/
public static Timestamp getThreadTimestamp() {
Timestamp ts = (Timestamp)threadTimeStamp.get();
return ts;
}
}
------------------------------------------------------------------------------------
For non-transactional situations we are using threadlocal to store the hibernate session. While it's simple to set it to the Threadlocal object when the session is not available, it's becoming a pain to remove it from the threadlocal instance when the bean call completes and the unsupported session bean method returns. On a subsequent call it's picking up stale value from the previous session and messing everything up. I did found some examples in the forum, esp the OpenSessionInviewFilter approach looked promising but we have strict separation of web layer and business layer where the hibernate POJOs resides. So servlet filter is ruled out. AOP looks complex and we are not using JBOSS anyway. We are using WebSphere 6.x. We do not have a have a JTA transaction either in hand to use the Synchronization interface since it's a unsupported session bean method
Any ideas, folks?