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]