Hi Simone,
It looks interesting and complicated! For the moment I’ve
decided to detach the object from the session by calling Hibernate.initialize()
on the collections and getters on the associations. This is implemented in the
object’s DAO. This can be used for objects that span a web session as
well as a flow. It would be handy if Hibernate provided a Hibernate.detach()
method. I know this will introduce unnecessary database fetching for
associations/collections that are not needed, though it’s probably better
than non-lazy loading.
I hope to spend sometime trying to implement your “flow”
wrapper – it looks interesting. Though I’m a little uncomfortable
having open sessions hanging around, though as you said it doesn’t hold
onto database connections.
From:
[EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Simone Gianni
Sent: 06 March 2006 18:31
To: [email protected]
Subject: Re: Flow and hibernate
sessions
Hi Mark,
we had the same problem with Hibernate. I solved it with a "flow"
wrapper. This wrapper wraps the flow interpreter of your choice (tested with
javaflow a lot, simple tests with _javascript_, but should not give big
problems), opens a new session when the flow is first accessed (map:call
function), detaches the session from the DB when the flow sends a page, then
retaches the same session when the continuation is invoked (map:call
continuation). It schedules a task to recollect and close sessions connected to
continuations which has been marked as invalid.
This magically gives you a coherent hibernate session inside your flow, but it
has some drawbacks :
- Sessions are left there, open (but disconnected from the database, so the DB
collection is free) for all the time it takes for the continuation tree to be
marked invalid, so potentially much more than needed, but there isn't currently
a notion of "flow finished", so i don't think there can be any other
way. This will increase memory usage.
- It's written for a hibernate + spring configuration, since it uses spring
transaction manager to set the session as "current session" while
executing the flow.
- Since the DB connection is detached, it forces a "flush never" to
avoid spring/hibernate to flush the connection and thus persist object while
they are, for example, being edited in a form or manipulated by the flow. This
means you must manually flush the connection (or the spring hibernate template
in DAOs, or whatever else) to persist your changes where needed (you can access
the session inside the flow with
request.getAttribute("HIBERNATE_SESSION") to do whatever you want
with it). This is again needed since there is no way of knowing automatically
when it is ok to flush the session and when we are just in an intermediate
sendpageandwait.
- Since the DB connection is detached, this can create potential problems in
database transaction for databases which does not support transactions spanning
different connections (which one does?) when not using another external
transaction system.
But also brings many advantages :
- You can use lazy loading everywhere, since the session will be there as long
as the continuation will be there.
- No more worries about objects being persisted in the middle of a flow-form interaction
(thus causing hibernate exceptions, or even worse data corruption)
- Hibernate persistence will now be "horizontal and transparent", at
least in your flow (DAO, or backend services, will always need to know
something about hibernate)
- No problems of merging, stale objects, duplicate objects ... that would arise
with other tecniques (object detach, retach; multiple sessions etc..)
We are currently developing a lot of stuff using cocoon + hibernate + spring
with this component.
You can find javadoc in the main HibernateFlowAdapter2 class, explaining how to
use it, feel free to ask everything you don't understand.
Unfortunately this code will not enter in the cocoon repository cause it would
include dependencies on hibernate, so i think we can use this thread to keep it
up to date in case you improve it.
Hope it helps!
Simone
Mark H wrote:
What is the best way to handle hibernate sessions in
flow? At the moment I’m using a servlet filter to close sessions after
each request but this makes it awkward when dealing with objects that span a
number of requests but are within one flow function (I’m using
flowscript). I could have the session span the flowscript function but if the
user never finishes the flow the session will never be closed.
--
Simone Gianni