To be honest, I *haven't* completely gotten around this problem.
I've *sort of* gotten around it by going to a long-session pattern so that
the Hibernate session virtually never flushes. If you want though I'll
attach my HibHelper class so you can get a feel for what I did. 

        Honestly though, it's not a magic bullet and I'm still struggling to
find one. Still, if it gets you partway there, you're welcome to use it,
modify it, whatever.

        To use it effectively you'll need a combination of the HibHelper
class (above) and the subclassed engine I provided earlier which stores and
retrieves the Hibernate session from the user session.

        --- Pat

> -----Original Message-----
> From: Chris Chiappone [mailto:[EMAIL PROTECTED]
> Sent: Tuesday, August 30, 2005 1:40 PM
> To: Tapestry users
> Subject: Re: Transaction handling. Where?
> 
> I was search back some threads and noticed your HibHelper class.  Is
> that basically the way you've gotten around this problem, HibHelper
> and the Servlet class you wrote?
> 
> On 8/30/05, Patrick Casey <[EMAIL PROTECTED]> wrote:
> >
> >        Not necessarily, but it depends on how you want your system to
> > manage transactions. One area where Hibernate and Tapestry don't "play
> nice"
> > is with data binding.
> >
> >        Let's say I have a "user" form that is bound to a persistent User
> > object.
> >
> >        Form gets rendered and goes out.
> >        User does some stuff and presses save.
> >        Form comes in, rewinds, and delta is pushed through into "user"
> > object.
> >        *** At this point the user object is flagged by Hibernate as
> dirty.
> > The next time the session flushes, it'll write through to the database,
> > whether or not you call saveOrUpdate()!
> >
> >        This is problematic if, for example, you want to cancel the
> update
> > because of failed validations :(.
> >
> >        One approach that can help is to evict everything from the
> session
> > on load so that it doesn't auto-flush. If you do this though, you will
> > likely have lazy initialization problems later on.
> >
> >        Another approach is to not directly bind your page to your
> > persistent object, but that adds a whole other level of work to the page
> > class.
> >
> >        All in all, I have not been happy with the interaction between
> > Hibernate and Tapestry. With a classic servlet engine it's not a biggy
> > because you can just not push invalid updates into the persistent
> object.
> > With Tapestry though, the (normally helpful) behavior of directly
> binding
> > user updates into the underlying persistent object doesn't allow the
> > programmer any control over when updates go through.
> >
> >        Basically it all comes down to Hibernate insisting that it knows
> > better than the programmer when things ought to be saved to the DB :(.
> >
> >        --- Pat
> >
> >
> > > -----Original Message-----
> > > From: Chris Chiappone [mailto:[EMAIL PROTECTED]
> > > Sent: Tuesday, August 30, 2005 1:07 PM
> > > To: Tapestry users
> > > Subject: Re: Transaction handling. Where?
> > >
> > > In my DOA i do the following...
> > >
> > >         public void makePersistentUser(Users user)
> > >                         throws InfrastructureException {
> > >
> > >                 try {
> > >                         HibernateUtil.beginTransaction();
> > >                         HibernateUtil.getSession().saveOrUpdate(user);
> > >                         HibernateUtil.commitTransaction();
> > >                         HibernateUtil.closeSession();
> > >                 } catch (HibernateException ex) {
> > >                         throw new InfrastructureException(ex);
> > >                 }
> > >         }
> > >
> > > Is this the wrong way to do it??
> > >
> > > On 8/30/05, Patrick Casey <[EMAIL PROTECTED]> wrote:
> > > >
> > > >        Have you tried subclassing BaseEngine and doing your
> transaction
> > > > management in cleanupAfterRequest() and setupForRequest() e.g.
> > > >
> > > > public class CorinnaEngine extends BaseEngine {
> > > >        private static final long serialVersionUID =
> > > 3257284742721648952L;
> > > >
> > > >        protected void cleanupAfterRequest(IRequestCycle cycle) {
> > > >                HibHelper.cleanupSession();
> > > >
> > > >                super.cleanupAfterRequest(cycle);
> > > >        }
> > > >
> > > >        protected void setupForRequest(RequestContext context) {
> > > >                HttpSession hs = MyServlet.getCurrentSession();
> > > >                HibHelper.attachSession(hs);
> > > >                HibHelper.getSession();
> > > >                super.setupForRequest(context);
> > > >        }
> > > >
> > > >
> > > >
> > > > }
> > > >
> > > > > -----Original Message-----
> > > > > From: Koka [mailto:[EMAIL PROTECTED]
> > > > > Sent: Tuesday, August 30, 2005 12:00 PM
> > > > > To: [email protected]
> > > > > Subject: Transaction handling. Where?
> > > > >
> > > > > Well, I have pages that allow to edit some database data, so I
> have
> > > easy
> > > > > solution to start transaction at
> > > > > public void pageBeginRender(PageEvent event)
> > > > > {
> > > > > if (event.getRequestCycle().isRewinding())
> > > > >
> > > > > // start transaction here
> > > > > }
> > > > >
> > > > > and at
> > > > > public void pageEndRender(PageEvent event)
> > > > > {
> > > > > if (event.getRequestCycle().isRewinding())
> > > > > {
> > > > > // Commit or rollback if errors found
> > > > >
> > > > > }
> > > > > }
> > > > >
> > > > > Hmm, it WORKS fine but, hmmm, page render and transactions...,
> agrrr
> > > sure
> > > > > there's some other place to handle things.So the question is what
> is
> > > the
> > > > > right place to start/end transaction in Tap4
> > > > > TYA
> > > >
> > > >
> > > >
> > > > --------------------------------------------------------------------
> -
> > > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > > For additional commands, e-mail: tapestry-user-
> [EMAIL PROTECTED]
> > > >
> > > >
> > >
> > >
> > > --
> > > ~chris
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
> 
> 
> --
> ~chris
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]

package data;

import java.lang.reflect.Proxy;

import javax.servlet.http.HttpSession;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import servlet.MyServlet;
import utils.Log;

import audit.AuditInterceptor;

public class HibHelper {
	private static final Configuration fConfiguration;
	private static final SessionFactory fSessionFactory;
	private static final ThreadLocal fThreadSession = new ThreadLocal();
	private static final ThreadLocal fThreadTransaction = new ThreadLocal();
	private static final String SESSION_KEY = "HIBERNATE_SESSION";
	// private static Session fDebug;

	static {
		fConfiguration = new Configuration().configure();
		fSessionFactory = fConfiguration.buildSessionFactory();
	}

	public static SessionFactory getSessionFactory() {
		return fSessionFactory;
	}

	/*
	 * private static Session getSessionFromServlet() { HttpSession hs =
	 * MyServlet.getCurrentSession();
	 * 
	 * Object o = hs.getAttribute(SESSION_KEY); if (o == null) return null;
	 * Session rc = (Session) o; return rc; }
	 */

	private static Session getSessionFromStorage() {
		return (Session) fThreadSession.get();
	}

	private static Session createNewSession() {
		AuditInterceptor intercept = new AuditInterceptor();
		Session s = fSessionFactory.openSession(intercept);
		intercept.setSession(s);
		s = (Session) (Proxy.newProxyInstance(Session.class.getClassLoader(),
				new Class[] { Session.class }, new CorinnaSession(s)));
		return s;
	}

	public static Session getSession() {
		// Session s = fDebug;
		Session s = (Session) getSessionFromStorage();
		try {
			if (s == null) {
				// s = fSessionFactory.openSession();
				s = createNewSession();
				fThreadSession.set(s);
			}
		} catch (HibernateException ex) {
			ex.printStackTrace();
		}
		return s;
	}

	public static void cleanupSession() {
		Session s = getSessionFromStorage();
		try {
			if (s != null) {
				commitTransaction();
				if (s.isConnected())
					s.disconnect();
			}
		} catch (Exception e) {
			Log.error(e);
		}
	}

	public static void closeSession() {
		try {
			Session s = getSessionFromStorage();
			MyServlet.getCurrentSession().setAttribute(SESSION_KEY, null);
			if (s != null && s.isOpen()) {
				s.close();
			}
		} catch (HibernateException ex) {
			ex.printStackTrace();
		}
	}

	public static void beginTransaction() {
		Transaction tx = (Transaction) fThreadTransaction.get();
		try {
			if (tx == null) {
				tx = getSession().beginTransaction();
				fThreadTransaction.set(tx);
			}
		} catch (HibernateException ex) {
			ex.printStackTrace();
		}
	}

	public static void commitTransaction() {
		Transaction tx = (Transaction) fThreadTransaction.get();
		try {
			if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
				tx.commit();
				fThreadTransaction.set(null);
			}
		} catch (HibernateException ex) {
			rollbackTransaction();
			ex.printStackTrace();
		}
	}

	public static void rollbackTransaction() {
		Transaction tx = (Transaction) fThreadTransaction.get();
		try {
			fThreadTransaction.set(null);
			if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
				tx.rollback();
			}
		} catch (HibernateException ex) {
			rollbackTransaction();
			ex.printStackTrace();
		} finally {
			closeSession();
		}
	}

	public static Configuration getConfiguration() {
		return fConfiguration;
	}

	public static void attachSession(HttpSession hs) {
		Session s = (Session) MyServlet.getCurrentSession().getAttribute(
				SESSION_KEY);
		if (s == null) {
			s = createNewSession();
			MyServlet.getCurrentSession().setAttribute(SESSION_KEY, s);
		}
		if (!s.isConnected())
			s.reconnect();
		fThreadSession.set(s);

	}

}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to