On Wednesday, June 18, 2003, at 02:14 PM, Ugo Cei wrote:


Jeremy Quinn wrote:
Because (I just realised) the Session has to be thrown away if there is any kind of Hibernate Exception, I was beginning to realise the only way of handling that safely was to wrap each call to Hibernate with a new Session.

Not every call to Hibernate but every HTTP request processing, which might involve more than one call.

Yes, much better.


The problem I still have to face is that I have to use 'lazy initialisation' as I am editing trees of objects with child/parent relationships, and I don't want the whole database loaded at once ;)
The problem is that if you try to access a Bean property that is not initialised (because it is lazy), while the Session is closed, you run the risk of getting a LazyInitializationException.
The obvious time to close the Session is when you are ready to send a page, but it is after you have sent the page (from FlowScript) that access to the Bean properties from JXForm takes place.

Looks like you haven't read the URL I mentioned very carefully ;-).

Many thanks for persevering in the face of my stupidity!!!


The servlet filter you install (lazily) opens a session *before* letting Cocoon process the request. Then closes the session *after* the response has been sent. And all of this happens transparently, no need to wrap your code with try { ... } finally { session.close(); }.

Much better approach.


When the view is realized, the session is still open, but it closes automatically after the last byte of the response has been sent to the client. Thus, there are no problems with lazy initialization.

Excellent


This also implies that the session that is stored in the continuation is closed by the time the continuation is invoked again, and you need to get a new session, if you need it.

I understand.


See this pseudocode for an example:

function editItem(form, id) {
  var session = Persistence.getSession();

is that:


var session = Package.package.name.Persistence.getSession(); ?

or is Persistence something you have got from the Context or somewhere?

  var model = session.load(id);
  form.setModel(model);
  form.sendView("editPage");
  session = Persistence.getSession(); // this gets the new session

Would you do something like this, if you wanted to use Transactions? :


var transaction;
try {
  transaction = session.beginTransaction();

session.saveOrUpdate(model);

transaction.commit(); } catch (e) { Persistence.rollback(transaction); log.error(e.getMessage()); // send an error view }

Would you consider doing something like the above from inside a sendView validation function, adding a violation if you had to roll back?

  form.finish("editOK");
}


Anyway, thanks for the example, it's nice and clean.


There are some cases where this might not work, like for instance if you want to use pessimistic locking. In this case, you should override this pattern by not calling Persistence.getSession() (and since the session is lazily initialized, this will avoid opening a session altogether), directly opening a new Hibernate session yourself and locking your model for updates with LockMode.UPGRADE. Of course, you run the risk of having a record locked indefinitely, and you should take care to release the lock when the continuation expires.

This is why I avoid pessimistic locking in web applications like the plague ;-).

Thanks for the advice!! ;)



By what I understand now ..... what I require is the Persistence class from the page you sent me and a configuration to add to web.xml. What I am not sure I understand is what that configuration should be.


I have never used a Filter before, and have never had to learn what all that JNDI stuff is about (whoops!).

Is it enough to just declare the filter class and mapping?

Many thanks

This is a far better approach than the one I had.

regards Jeremy



Reply via email to