So far my answer is lazy="false" but I'm sure that mite bite me in the a$$ when going to production and having a lot of users. Pat, I think I'm gonna try out your long-session thread pattern and see if that fixes some of my issues. If not that then to tap 4 and hiveutils...
On 8/30/05, Patrick Casey <[EMAIL PROTECTED]> wrote: > > I don't think that gets you around the lazy initialization problem > though, does it? If the session closes when the servlet returns, then it's > no longer available in subsequent interactions to load lazy collections. > > Likewise, globally rolling back the transaction isn't necessarily > the right approach either (yet another gripe I have about how hibernate and > the web fight one another). > > This is a slightly contrived example, but for purposes of > explanation it should work: > > Lets say I need to log every user interaction to the DB (not that > weird actually, I've had to do this on some security conscious apps). > > So whenever A user presses "save" on a web form I have to: > > Log an "interaction begun" datum with the IP address, session ID, > etc. > Do the transaction. > Log an "interaction complete" datum with the UP address, session ID, > etc. > > If I roll back globally, I lose not only the user's personal update > (which I want to roll back), but also the interaction records, which I > *don't* want to roll back. > > It's gotten so aggravating I'm seriously considering using two > parallel session. One for "system" data that I have control of and one for > "user" updates that I might have to roll back. That way I can always flush > my system session and selectively flush the user session. Of course that > means twice the number of DB connections, dogs and cats living together, > etc, etc, etc. > > It's frustrating, as you can doubtless discern from my aggravated > tone :(. > > --- Pat > > > -----Original Message----- > > From: Paul Cantrell [mailto:[EMAIL PROTECTED] > > Sent: Tuesday, August 30, 2005 3:23 PM > > To: Tapestry users > > Subject: Re: Transaction handling. Where? > > > > If you open & close your ThreadLocal session from a *servlet filter* > > instead of trying to finagle it into the tapestry lifecycle, > > everything is peachy -- at least in my limited experience. > > > > For rollbacks, implement a preventCommit() method your code can call > > on error. In the filter, you either commit or roll back depending on > > whether preventCommit() was called. > > > > Cheers, > > > > Paul > > > > On Aug 30, 2005, at 4:22 PM, Patrick Casey wrote: > > > > > > > > Yah, I'm familiar with a large variety of ways to initialize > > > collections. The problem with pre-initializing everything though is > > > that > > > most of the time, you *don't* need the whole object graph. So if I > > > have to > > > fill out every object graph every time I load a root object on the off > > > chance that somewhere, someday, someone might reference a child > > > object, I > > > end up wasting a lot of memory and database labour. > > > > > > As for long sessions being a bad idea; they *definitely* have > > > their > > > risks, especially if you aren't careful about evicting things when > > > they > > > aren't needed anymore. For web applications though, they really > > > seem like > > > the only practical approach in my experience. The threadlocal > > > pattern can't > > > solve the initialization problem, and the session-per-transaction > > > pattern > > > has performance problems *and* the lazy initialization problem. > > > > > > I really think the whole "we refuse to automatically reconnect to > > > lazy-load a connection and instead insist on throwing and > > > exception" is > > > database-purist-arrogance on the part of the Hibernate team. Most > > > of their > > > library is great, but this behavior is just *not* web friendly, and > > > their > > > smug assurance that it's "not a big deal to workaround" turns out > > > not to be > > > true in practice. > > > > > > --- Pat > > > > > > > > >> -----Original Message----- > > >> From: Tomáš Drenčák [mailto:[EMAIL PROTECTED] > > >> Sent: Tuesday, August 30, 2005 2:16 PM > > >> To: Tapestry users > > >> Subject: Re: Transaction handling. Where? > > >> > > >> You can initialize collections with Hibernate.initialize(collection), > > >> or in query with left join fetch and than use detached objects in > > >> further requests. And btw I've read that long open sessions aren't > > >> good idea at all... > > >> > > >> 2005/8/30, Patrick Casey <[EMAIL PROTECTED]>: > > >> > > >>> > > >>> As I understand it though, with this approach the session > > >>> has a > > >>> lifespan that doesn't span multiple requests (in fact, its > > >>> granularity > > >>> > > >> is < > > >> > > >>> 1 request). This raises problems in practice with use cases like: > > >>> > > >>> User has a set of roles (lazy collection) > > >>> > > >>> I bring up the User page. It loads from Session #1 which > > >>> is then > > >>> closed. > > >>> I click on the "show roles" button. We go back to Tapestry > > >>> which > > >>> merrily does a user.getRoles().iterator() and promptly blows up > > >>> with a > > >>> > > >> lazy > > >> > > >>> initialization exception because Session #1 (the one which > > >>> produced the > > >>> user) no longer exists. > > >>> > > >>> That and creating a fresh session for each database > > >>> interaction, > > >>> while not quite as bad a plan as creating a new JDBC connection > > >>> for each > > >>> query, is still not a great performance idea :(. > > >>> > > >>> --- Pat > > >>> > > >>> > > >>>> -----Original Message----- > > >>>> From: Tomáš Drenčák [mailto:[EMAIL PROTECTED] > > >>>> Sent: Tuesday, August 30, 2005 1:58 PM > > >>>> To: Tapestry users > > >>>> Subject: Re: Transaction handling. Where? > > >>>> > > >>>> I use classes described in > > >>>> > > >>>> > > >> http://www.theserverside.com/articles/content/HivemindBuzz/ > > >> article.html. > > >> > > >>>> This is perfect approach for DAO pattern. Just declare DAO > > >>>> object as > > >>>> service with implementation and property of type > > >>>> org.hibernate.Session > > >>>> and setter setSession(Session). Session is then created uppon your > > >>>> request to service and always initialized and closed through > > >>>> ApplicationServlet which cleanups hivemind. There's also > > >>>> transaction > > >>>> interceptor... > > >>>> > > >>>> 2005/8/30, Chris Chiappone <[EMAIL PROTECTED]>: > > >>>> > > >>>>> Thanks, if I were to use this helperclass would I still go about > > >>>>> getting the session before a save or update and closing the > > >>>>> session > > >>>>> after complete, as i was before? > > >>>>> > > >>>>> Also have you thought about using something like HiveTrans to do > > >>>>> > > >> this > > >> > > >>>>> for you? I have been thinking about moving to tap 4 and using > > >>>>> hivemind with hivetrans to deal with the hibernate session > > >>>>> > > >> management. > > >> > > >>>>> Any thoughts?? > > >>>>> > > >>>>> On 8/30/05, Patrick Casey <[EMAIL PROTECTED]> wrote: > > >>>>> > > >>>>>> > > >>>>>> 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: tapestry-user- > > >>>>>>>>>> > > >>>> [EMAIL PROTECTED] > > >>>> > > >>>>>>>>>> For additional commands, e-mail: tapestry-user- > > >>>>>>>>>> > > >>>>>>> [EMAIL PROTECTED] > > >>>>>>> > > >>>>>>>>>> > > >>>>>>>>>> > > >>>>>>>>>> > > >>>>>>>>> > > >>>>>>>>> > > >>>>>>>>> -- > > >>>>>>>>> ~chris > > >>>>>>>>> > > >>>>>>>>> ------------------------------------------------------------ > > >>>>>>>>> > > >> ---- > > >> > > >>>> ----- > > >>>> > > >>>>>>>>> To unsubscribe, e-mail: tapestry-user- > > >>>>>>>>> > > >>>> [EMAIL PROTECTED] > > >>>> > > >>>>>>>>> For additional commands, e-mail: tapestry-user- > > >>>>>>>>> > > >>>> [EMAIL PROTECTED] > > >>>> > > >>>>>>>> > > >>>>>>>> > > >>>>>>>> > > >>>>>>>> > > >>>>>>>> -------------------------------------------------------------- > > >>>>>>>> > > >> ---- > > >> > > >>>> --- > > >>>> > > >>>>>>>> To unsubscribe, e-mail: tapestry-user- > > >>>>>>>> > > >>>> [EMAIL PROTECTED] > > >>>> > > >>>>>>>> For additional commands, e-mail: tapestry-user- > > >>>>>>>> > > >>>> [EMAIL PROTECTED] > > >>>> > > >>>>>>>> > > >>>>>>>> > > >>>>>>>> > > >>>>>>> > > >>>>>>> > > >>>>>>> -- > > >>>>>>> ~chris > > >>>>>>> > > >>>>>>> ---------------------------------------------------------------- > > >>>>>>> > > >> ---- > > >> > > >>>> - > > >>>> > > >>>>>>> To unsubscribe, e-mail: tapestry-user- > > >>>>>>> > > >> [EMAIL PROTECTED] > > >> > > >>>>>>> For additional commands, e-mail: tapestry-user- > > >>>>>>> > > >>>> [EMAIL PROTECTED] > > >>>> > > >>>>>> > > >>>>>> > > >>>>>> > > >>>>>> ----------------------------------------------------------------- > > >>>>>> - > > >>>>>> > > >> --- > > >> > > >>>>>> To unsubscribe, e-mail: tapestry-user- > > >>>>>> > > >> [EMAIL PROTECTED] > > >> > > >>>>>> For additional commands, e-mail: tapestry-user- > > >>>>>> > > >> [EMAIL PROTECTED] > > >> > > >>>>>> > > >>>>>> > > >>>>>> > > >>>>>> > > >>>>> > > >>>>> > > >>>>> -- > > >>>>> ~chris > > >>>>> > > >>>>> ------------------------------------------------------------------ > > >>>>> -- > > >>>>> > > >> - > > >> > > >>>>> To unsubscribe, e-mail: tapestry-user- > > >>>>> [EMAIL PROTECTED] > > >>>>> For additional commands, e-mail: tapestry-user- > > >>>>> > > >> [EMAIL PROTECTED] > > >> > > >>>>> > > >>>>> > > >>>>> > > >>>> > > >>>> ------------------------------------------------------------------- > > >>>> -- > > >>>> To unsubscribe, e-mail: tapestry-user- > > >>>> [EMAIL PROTECTED] > > >>>> For additional commands, e-mail: tapestry-user- > > >>>> [EMAIL PROTECTED] > > >>>> > > >>> > > >>> > > >>> > > >>> > > >>> -------------------------------------------------------------------- > > >>> - > > >>> To unsubscribe, e-mail: [EMAIL PROTECTED] > > >>> For additional commands, e-mail: tapestry-user- > > >>> [EMAIL PROTECTED] > > >>> > > >>> > > >>> > > > > > > > > > > > > --------------------------------------------------------------------- > > > 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] > > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > -- ~chris
