I was seeing exactly the same problem in a non-managed environment using HiberateUtil.
It turned out that the session was indeed closed elsewhere in the code. But in my class, I have a DAO object that would start a new transaction. And the new transaction would start a new session. So it shouldn't have mattered that another session was closed earlier.
Well, I was wrong. The HibernateUtil we used, although slightly modified from the one from the Hibernate In Action book and from the one listed in the online doc, does not clear out the Transaction object in the ThreadLocal object when closing a session:
Code:
// Method is simplified for readibility
public static void closeSession() {
Session s = (Session) _Session.get();
if (s != null) {
s.close();
_Session.set(null);
}
}
Then when beginTransaction() is called, it checks to see if the Transaction in the ThreadLocal is null, and if it is, gets a new session and begins a new transaction:
Code:
// Method is simplified for readibility
public static void beginTransaction() {
Transaction tx = (Transaction) _Transaction.get();
if (tx == null) {
tx = getSession().beginTransaction();
_Transaction.set(tx);
}
}
Well, but tx is not null since closeSession() call earlier didn't set it to be null. So the application didn't get a new session nor begin a new transaction.
Then when I did a tx.commit(), I got exactly the same error as you did even though my current session is well and alive but the transaction itself was from the previous session.
I am not sure if it's the most elegant, but setting the Transaction object to be null in my closeConnection() method solved this problem:
Code:
public static void closeSession() {
Session s = (Session) _Session.get();
if (s != null) {
s.close();
_Session.set(null);
_Transaction.set(null);
}
}
Not sure if your exception was caused by the same nature but it is likely if you happen to use the HibernateUtil from the book or from the online doc, which does not nullify the Transaction object.
Hope this helps.