Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
[b]Hibernate version:[3.1]
Hi all iam new bie to Hibernate.
I have an application which runs as standalone and also web application.
For making a generic Persistance which works for standalone and web i have the following Persistance.java file.
Iam able to create sessions and persist data in standalone application.
Iam not able to do when i deploy as web application.
========= Persistance.java ======================
import java.io.*;
import java.util.*;
import javax.servlet.*;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.HibernateException;
import org.hibernate.StaleObjectStateException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.naming.InitialContext;
import javax.transaction.UserTransaction;
/**
* Filter which manages a ThreadLocal hibernate session. Obtain the session
* by calling Persistence.getSession(). Define the JNDI name of the
* hibernate session factory as an init param to the filter in your web.xml.
*
* Original author Jeff Schnitzer
*
* @version $Id: Persistence.java,v 1.4 2006/03/24 00:27:40 fazeel Exp $
*/
public class Persistence implements Filter
{
private static final long serialVersionUID=1L;
private static Log logger;
/**
* Filter init param which defines the JNDI name for the hibernate factory
*/
public static final String HIBERNATE_FACTORY_JNDI_PARAM = "hibernateFactory";
/**
* Default value if no init param is set.
*/
public static final String HIBERNATE_FACTORY_JNDI_DEFAULT = "java:/SessionFactory";
/**
* Holds the current hibernate session, if one has been created.
*/
protected static ThreadLocal hibernateHolder = new ThreadLocal();
protected static ThreadLocal txHolder = new ThreadLocal();
/**
*/
protected static SessionFactory factory;
/**
* Set to true is we're using Container Manager Persistence (CMP). This
* assumes that we're using JNDI and the Hibernate session factory is registered
* along with a JTA UserTransaction.
*/
private static boolean CMPMode = true;
/**
* JNDI resource name for Hibernate SessionFactory for CMP
*/
public static final String JNDI_HIBERNATE_FACTORY = "SessionFactory";
/**
* JNDI resource name for JTA transaction for CMP
*/
public static final String JNDI_JTA_TRANSACTION = "java:comp/UserTransaction";
/**
* Stored in the request to initiate a rollback
*/
public static final String ROLLBACK = "rollback";
public static final String STALEDATA = "staledata";
/**
* Determine if we're running in container managed persistence context.
* CMPMode cannot be changed externally
* @return True if Hibernate was initialized through the container
*/
public boolean isCMPMode() {
return CMPMode;
}
/**
*/
public void init(FilterConfig filterConfig) throws ServletException {
// Initialize session factory
try {
InitialContext ctx = new InitialContext();
factory = (SessionFactory) ctx.lookup(JNDI_HIBERNATE_FACTORY);
CMPMode = true;
} catch (Exception e) {
// do nothing
}
if (!CMPMode) {
logger.debugLog("Persistence: Init Session: Could not bind to Hibernate Factory through JNDI");
try {
factory = new Configuration().configure().buildSessionFactory();
logger.debugLog("Persistence: Init Session: Hibernate Factory built manually");
} catch (HibernateException ex) {
throw new ServletException(ex);
}
}
}
/**
* Method called by tomcat to apply the filter. Invoked before every servlet is called
* This method manages opening/closing the session and transaction for each servlet.
*/
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (CMPMode)
doFilterCMP(request, response, chain);
else
doFilterHibernate(request, response, chain);
}
/**
* Method called by tomcat to apply the filter. Invoked before every servlet is called
* This method manages opening/closing the session and transaction for each servlet.
*/
private void doFilterCMP(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
UserTransaction tx = null;
try {
tx = (UserTransaction) new InitialContext().lookup(JNDI_JTA_TRANSACTION);
logger.debugLog("=========== ["+Thread.currentThread().hashCode()+"]: dofilter: tx=" + tx);
tx.begin();
try {
// use the Hibernate Factory
//SessionFactory factory = (SessionFactory) new InitialContext().lookup(JNDI_HIBERNATE_FACTORY);
Session sess = factory.openSession();
logger.debugLog("=========== dofilter: sess=" + sess);
hibernateHolder.set(sess);
txHolder.set(tx);
logger.debugLog("=========== dofilter: tx and hib holders set");
chain.doFilter(request, response);
logger.debugLog("=========== dofilter: Returned from chain.dofilter");
String roll = (String) request.getAttribute(ROLLBACK);
if ("true".equals(roll)) {
logger.debugLog("ROLLBACK set to true in request attribute");
request.removeAttribute(ROLLBACK);
rollback();
}
logger.debugLog("Persistence: Commiting");
logger.debugLog("=========== dofilter: About to commit");
tx.commit();
logger.debugLog("=========== dofilter: Committed");
} catch (Exception e) {
logger.debugLog("Persistence: Caught exception during filter chain: " + e);
e.printStackTrace();
} finally {
//hsession.close();
}
} catch (Exception eo) {
eo.printStackTrace();
logger.debugLog("Persistence: Caught exception in tx try: " + eo);
try {
logger.debugLog("Persistence: Rolling back");
tx.rollback();
} catch (Exception rbe) {
logger.debugLog("Persistence: Caught exception while rolling back!!!! " + rbe);
}
}
}
/**
* Method called by tomcat to apply the filter. Invoked before every servlet is called
* This method manages opening/closing the session and transaction for each servlet.
*/
private void doFilterHibernate(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
boolean error = false;
logger.debugLog("Entering doFilter " + Thread.currentThread().hashCode());
if (hibernateHolder.get() != null)
throw new IllegalStateException(
"A session is already associated with this thread! "
+ "Someone must have called getSession() outside of the context "
+ "of a servlet request." + Thread.currentThread().hashCode());
try {
Session sess = factory.openSession();
hibernateHolder.set(sess);
txHolder.set(sess.beginTransaction());
chain.doFilter(request, response);
String roll = (String)request.getAttribute(ROLLBACK);
if ("true".equals(roll)) {
logger.debugLog("ROLLBACK set to true in request attribute");
request.removeAttribute(ROLLBACK);
rollback();
// set error flag to prevent commit
error = true;
}
} catch (Exception ex) {
// if an exception occurs rollback
logger.debugLog("Exception encountered setting error to true and rolling back the transaction");
ex.printStackTrace();
rollback();
// set error flag to prevent commit
error = true;
} finally {
logger.debugLog("closing tx" + Thread.currentThread().hashCode());
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess != null) {
hibernateHolder.set(null);
try {
if (tx != null && !error) {
logger.debugLog("commiting transaction");
tx.commit();
}
}
catch (HibernateException ex3) {
if (ex3 instanceof StaleObjectStateException) {
logger.debugLog("StaleObjectStateException - set STALEDATA attribute to true");
HttpServletRequest httpRequest = (HttpServletRequest)request;
HttpSession session = httpRequest.getSession();
session.setAttribute(STALEDATA, "true");
}
ex3.printStackTrace();
try {
if (!tx.wasCommitted()) {
rollback();
}
} catch (HibernateException ex4) {
ex4.printStackTrace();
throw new ServletException(ex4);
}
} finally {
try {
logger.debugLog("closing Session " + Thread.currentThread().hashCode());
sess.close();
} catch (HibernateException ex5) {
ex5.printStackTrace();
throw new ServletException(ex5);
}
}
}
logger.debugLog("Successfully closed");
}
}
/**
* @return an appropriate Session object. Not called by client code but by other
* persistence level classes hence throws a HibernateException.
*/
public static Session getSession() throws HibernateException {
Session sess = (Session)hibernateHolder.get();
if (sess == null) {
throw new HibernateException("Session has not been opened -- the session object is NULL");
} else {
//logger.debugLog("Getting session " + Thread.currentThread().hashCode());
}
return sess;
}
/**
* @return the hibernate session factory
*/
public static SessionFactory getSessionFactory() {
logger.debugLog("========== In Persistence.getSessionFactory: sf=" + factory);
return factory;
}
/**
* Commit the transaction. Exceptions thrown as PersistenceExceptions's. This means
* that any Exception handling by the caller needs to invoke the getCause() method
* to get the real exception.
*/
public static void commit() throws PersistenceException {
if (CMPMode)
commitCMP();
else
commitHibernate();
}
/**
* Commit the transaction thru CMP
*/
private static void commitCMP() throws PersistenceException {
try {
logger.debugLog("Persistence: commiting transaction");
UserTransaction tx = (UserTransaction) txHolder.get();
tx.commit();
} catch (Exception e) {
logger.debugLog("Persistence: Cannot commit transaction: rolling back");
rollback();
throw new UpdateException("Persistence: Unable to commit transaction", e);
}
}
/**
* Commit the transaction thru hibernate APIs.
*/
private static void commitHibernate() throws PersistenceException {
try {
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess != null && tx != null) {
try {
logger.debugLog("Persistence: commiting transaction");
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
try {
if (!tx.wasCommitted())
rollback();
} catch (HibernateException e2) {
e2.printStackTrace();
throw new UpdateException("Persistence: Unable to commit transaction", e2);
}
throw new UpdateException("Persistence: Unable to commit transaction", e);
}
}
} catch (Exception ex) {
throw new UpdateException("Persistence: Unable to commit transaction", ex);
}
}
/**
* This is a simple method to reduce the amount of code that needs
* to be written every time hibernate is used.
*/
public static void rollback() {
if (CMPMode)
rollbackCMP();
else
rollbackHibernate();
}
/**
* Rollback using CMP
*/
private static void rollbackCMP() {
UserTransaction tx = (UserTransaction) txHolder.get();
txHolder.set(null);
if (tx != null) {
try {
tx.rollback();
logger.debugLog("Rollback successful");
} catch (Exception ex) {
logger.debugLog("Persitence: Ate exception thrown during rollback: " + ex);
// Probably don't need to do anything - this is likely being
// called because of another exception, and we don't want to
// mask it with yet another exception.
}
}
}
/**
* Rollback using Hibernate APIs
*/
private static void rollbackHibernate() {
Transaction tx = (Transaction)txHolder.get();
txHolder.set(null);
if (tx != null) {
try {
tx.rollback();
logger.debugLog("Rollback successful");
} catch (HibernateException ex) {
logger.debugLog("Persitence: Ate exception thrown during rollback: " + ex);
// Probably don't need to do anything - this is likely being
// called because of another exception, and we don't want to
// mask it with yet another exception.
}
}
}
/**
Close the factory
*/
public void destroy() {
if (CMPMode) {
try {
factory.close();
} catch (HibernateException ex) {
throw new RuntimeException(ex);
}
}
}
/**
* This special init method should only be called from stand-alone
* applications that are running outside a web application context.
* The caller is responsible for initializing the DB/Hibernate backend
* and pass in a session factory to Persistence. This is then used by
* the collaborat.db.* and collaborato.dbservice.* to access the database.
* Note that the stand-alone application is required to manage its own
* session/connection logic, the only link to Persistence is to make
* sure that the sessionFactory is available to our persistence layer
* just as if we were running inside a servlet context.
* @param sf Initialized SessionFactory object that will be used by
* the DAO objects
*/
public static void applicationModeInit(SessionFactory sf, Log log)
throws Exception {
// Initialize hibernate
try {
logger = log;
logger.debugLog("Init Session " + Thread.currentThread().hashCode());
factory = sf;
} catch (Exception ex) {
throw new ServletException(ex);
}
}
/**
Invoke this to open a hibernate session.
**/
public static void openSession() throws PersistenceException {
Session sess = (Session)hibernateHolder.get();
if (sess == null) {
logger.debugLog("Opening Session " + Thread.currentThread().hashCode());
try {
sess = factory.openSession();
hibernateHolder.set(sess);
} catch (HibernateException e) {
throw new PersistenceException("Unable to open session", e);
}
} else {
// session already exists
throw new PersistenceException("Session already exists");
}
}
/**
Invoke this method to begin a transaction.
**/
public static void beginTransaction() throws PersistenceException {
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess == null) {
throw new PersistenceException("Need to call openSession() prior to calling beginTransaction");
} else if (tx == null) {
// creates a new transaction for the current session
try {
if (sess.isConnected()) {
logger.debugLog("beginTransaction: session is connected: disconnect");
sess.disconnect();
logger.debugLog("beginTransaction: disconnect successful");
} else {
logger.debugLog("beginTransaction: no connectione exists");
}
logger.debugLog("beginTransaction: calling reconnect");
sess.reconnect();
logger.debugLog("beginTransaction: reconnect successful");
txHolder.set(sess.beginTransaction());
} catch (HibernateException e) {
throw new PersistenceException("Unable to begin transaction", e);
}
} else {
throw new PersistenceException("Attempting to begin a transaction without ending the previous transaction");
}
return;
}
/**
Invoke this method to end a transaction.
**/
public static void endTransaction() throws PersistenceException {
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
try {
if (sess == null) {
// throw exception
throw new PersistenceException("Attempting to end a transaction when the session is null");
} else if (tx == null) {
throw new PersistenceException("Attempting to end a transaction when there transaction is null");
// throw exception
} else {
commit();
txHolder.set(null);
}
} finally {
try {
if (sess.isConnected()) {
logger.debugLog("endTransaction: connection exists - disconecting");
sess.disconnect();
} else {
logger.debugLog("endTransaction: no connectione exists");
}
logger.debugLog("endTransaction: calling reconnect");
sess.reconnect();
logger.debugLog("endTransaction: reconnect successful");
} catch (Exception e){
throw new PersistenceException("Unable to re-establish a jdbc connection: " + e);
}
}
}
public static void closeSession() throws PersistenceException {
Session sess = (Session)hibernateHolder.get();
Transaction tx = (Transaction)txHolder.get();
if (sess == null) {
throw new PersistenceException("Attempting to close a session that is already null");
}
if (tx != null) {
throw new PersistenceException("Attempting to close a session prior to calling endTransaction()");
}
try {
sess.close();
hibernateHolder.set(null);
} catch (HibernateException e) {
throw new PersistenceException("Unable to close session", e);
}
}
}
================== web.xml =========================
<web-app>
<servlet>
<servlet-name>ABCServlet</servlet-name>
<servlet-class>com.abc.ABCMgr</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ABCServlet</servlet-name>
<url-pattern>/ABCMgr</url-pattern>
</servlet-mapping>
<resource-ref>
<res-ref-name>SessionFactory</res-ref-name>
<res-type>net.sf.hibernate.SessionFactory</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<filter>
<filter-name>Persistence</filter-name>
<filter-class>com.abc.persistutils.Persistence</filter-class>
</filter>
<filter-mapping>
<filter-name>Persistence</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
================== UserDAO =========================
package com.abc.persistence;
import java.util.List;
import javax.naming.InitialContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.LockMode;
import org.hibernate.SessionFactory;
import static org.hibernate.criterion.Example.create;
import com.abc.persistutils.Persistence;
/**
* Home object for domain model class User.
* @see com.abc.persistence.User
* @author Hibernate Tools
*/
public class UserDAO {
private static final Log log = LogFactory.getLog(UserDAO.class);
public void persist(User transientInstance) {
log.debug("persisting User instance");
try {
Persistence.getSession().persist(transientInstance);
log.debug("persist successful");
}
catch (RuntimeException re) {
log.error("persist failed", re);
throw re;
}
}
public void attachDirty(User instance) {
log.debug("attaching dirty User instance");
try {
Persistence.getSession().saveOrUpdate(instance);
log.debug("attach successful");
}
catch (RuntimeException re) {
log.error("attach failed", re);
throw re;
}
}
public void attachClean(User instance) {
log.debug("attaching clean User instance");
try {
Persistence.getSession().lock(instance, LockMode.NONE);
log.debug("attach successful");
}
catch (RuntimeException re) {
log.error("attach failed", re);
throw re;
}
}
public void delete(User persistentInstance) {
log.debug("deleting User instance");
try {
Persistence.getSession().delete(persistentInstance);
log.debug("delete successful");
}
catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}
public User merge(User detachedInstance) {
log.debug("merging User instance");
try {
User result = (User) Persistence.getSession()
.merge(detachedInstance);
log.debug("merge successful");
return result;
}
catch (RuntimeException re) {
log.error("merge failed", re);
throw re;
}
}
public User findById( long id) {
log.debug("getting User instance with id: " + id);
try {
User instance = (User) Persistence.getSession()
.get("com.abc.persistence.User", id);
if (instance==null) {
log.debug("get successful, no instance found");
}
else {
log.debug("get successful, instance found");
}
return instance;
}
catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}
}
}
In webapplication I set CMPMode to true for my web application.
For creating sessions iam using servlet filter model, where i create sessions on doFilter().
my servlet has the following code
UserDAO uH = new UserDAO();
User u = new User(login, name, passwd, role, privilege,
null, null, null);
uH.persist(u);
Iam getting an excetion at Persistance.getSession();
when i debug i found that hibernateHolder.get() always returns null.
Iam suprised why Session is null. Can any one help me where iam going wrong.
Thanks in Advance.
Jonny