I've been searching a lot of Threads in Hibernate but nothing seems to solve my problem. I already try with explicit use of ThreadLocal on Session, contextual session with Thread and JTA. I have a app divided in 3 layers, web, bo and dao. Dao only contains method of save, load, update... using ProjectSessionFactory.getCurrentSession().
This is my ProjectSessionFactory class:
Code:
public class ProjectSessionFactory {
private static final SessionFactory factory;
private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();
static {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
AlertaLogger.error("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
} // static
/** Creates a new instance of ProjectSessionFactory */
public ProjectSessionFactory() {
} // ProjectSessionFactory
public static SessionFactory getSessionFactory() {
return factory;
} // getSessionFactory
public static Session getCurrentSession() throws HibernateException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = ProjectSessionFactory.getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new HibernateException(ex);
}
return s;
}
public static void currentTransactionBegin() throws HibernateException {
ProjectSessionFactory.getCurrentSession().beginTransaction();
}
public static void currentTransactionCommit() throws HibernateException{
System.out.println("[ProjectSessionFactory] Preparando commit");
ProjectSessionFactory.getCurrentSession().flush();
ProjectSessionFactory.getCurrentSession().getTransaction().commit();
}
public static void currentTransactionRollback() throws HibernateException{
if(ProjectSessionFactory.getCurrentSession().getTransaction() != null){
ProjectSessionFactory.getCurrentSession().getTransaction().rollback();
}
}
public static void currentTransactionSavePoint() throws HibernateException {
ProjectSessionFactory.getCurrentSession().flush();
ProjectSessionFactory.getCurrentSession().clear();
ProjectSessionFactory.getCurrentSession().getTransaction().commit();
ProjectSessionFactory.getCurrentSession().beginTransaction();
}
public static void currentSessionClose() throws HibernateException {
ProjectSessionFactory.getCurrentSession().close();
threadSession.set(null);
}
}
This is a action:
Code:
public class HibernateAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
ActionForward actionResponse = null;
try {
ProjectSessionFactory.currentTransactionBegin();
// invokes a BO method to do some work
ProjectSessionFactory.currentTransactionCommit();
} catch (Exception e) {
AlertaLogger.error(e.getMessage());
try {
ProjectSessionFactory.currentTransactionRollback();
} catch (Exception ex) {
AlertaLogger.error(ex.getMessage());
}
} finally {
ProjectSessionFactory.currentSessionClose();
}
return actionResponse;
}
}
I'm using Jboss, Struts and Hibernate. The app is working fine except for some points where I need to declare a new Thread to do some extra work on the db without involve the response time of the request. In the log everything executes ok, but anything the new Thread process stay on the db even when the commit executes normally. Why is this??? I need to use new Threads to do this work. I use a class for the new Threads:
Code:
public class HibernateThread extends Thread {
@Override
public void run(){
try {
ProjectSessionFactory.currentTransactionBegin();
execute();
ProjectSessionFactory.currentTransactionCommit();
} catch (Exception e) {
AlertaLogger.error(e.getMessage());
try {
ProjectSessionFactory.currentTransactionRollback();
} catch (Exception ex) {
AlertaLogger.error(ex.getMessage());
}
} finally {
ProjectSessionFactory.currentSessionClose();
}
}
public void executeWork(){
// do some work
}
}
As you can see, the execution of thread is the same of the action, but the data don't stay on the db after the commit.
Note: currentTransactionSavePoint() pretends to be a SavePoint invoked before a new Thread declaration so the data is avaliable for the Thread. But even when I don't use this method the problem persist.