You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by lasitha <la...@gmail.com> on 2007/11/19 10:17:32 UTC

Re: T5: Tapestry-Hibernate, do we have to save()?

On Oct 31, 2007, Thiago H de Paula Figueiredo <th...@gmail.com> wrote:
> On Wed, 31 Oct 2007, Ognen Ivanovski <og...@netcetera.com.mk> wrote:
>
> > tapestry-ioc allows you to write interceptors on service method calls.
>
> I've already done that: http://tapestry-mine.sourceforge.net/hibertapestry/
>
> The source is Apache 2-licensed and was not released yet, but I'll do it
> soon.

Thiago, any chance you'll be releasing the source soon?
I'm looking forward to trying it out but am hesitant to do so without
first looking it over :).

Thanks,
lasitha

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 19, 2007 5:42 PM, Thiago H de Paula Figueiredo
<th...@gmail.com> wrote:
> On Mon, 19 Nov 2007 07:17:32 -0200, lasitha <la...@gmail.com>
> wrote:
>
> [.... a long descpription on the 'unintended save' problem ...]
>
> > On Oct 31, 2007, Thiago H de Paula Figueiredo <th...@gmail.com> wrote:
> >
> > Thiago, any chance you'll be releasing the source [of HiberTapestry] soon?
>
> I'm planning to release the sources until this weekend.

Thiago, thanks for releasing that, i've finally had some time to look
into it this weekend.  Looks neat - well done :).

Some thoughts relevant to the 'unintended save' problem:
* I think HiberTapestry mostly solves it.
* The only hole i can see is that even though we only commit
explicitly at the successful completion of a @Transactional method, i
think it's possible that hibernate will automatically flush the
session at unexpected moments.  The default FlushMode.AUTO
documentation specifies: "The Session is sometimes flushed before
query execution in order to ensure that queries never return stale
state".  If this happens before we are ready, we may still be open to
unintentional saves.  Would it be safer to set the flush mode to
COMMIT instead?

More general feedback:
* In our own solution to the problem (see below), we found it useful
to be able to annotate page/component methods.  In fact i think our
most common case is to mark the onSuccess event as the commit point.
Since tapestry-ioc doesn't decorate pages and components, we are
contributing a ComponentClassTransformWorker that injects the
transactional code into pages.  This may be some neat functionality to
add to HiberTapestry.
* I'm not sure if https://issues.apache.org/jira/browse/TAPESTRY-1874
is still valid.  I am able to get Match("*") to work without tapestry
complaning about IOC services.  Might be something to look into as it
would elimante the naming convention limitation.

Our homegrown solution so far:
* We override and alias the HibernateSessionManager so that it always
_rolls back_ on thread cleanup.
* We set the flush mode to AUTO (also by overriding the HSM).
* We introduce a @CommitOnCompletion annotation that tells the
framework to call HSM.commit() when the marked method completes.  This
will commit the transaction that was begun when the session was first
created, and begin a new one for the rest of the request cycle.  If
the method is never called or hits an exception everything is rolled
back.

If you see any problem with that solution, please let us know.

In any case, i suspect this whole problem will be superceded by the
(hopefully) upcoming support for 'conversations'.

Be well, lasitha.

P.S.  I am leaving my current job (and considering a career change :),
so i may not do a good job of following up on this thread.  My
apologies in advance.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 20, 2007 12:11 AM, Ezra Epstein <ez...@yahoo.com> wrote:
> I imagine that if you use Spring's declarative transactions on the service layer so that the read()/get() method does not start a read/write transaction but the save() method does then changing the object without calling "save()" should just work - you won't be in a read/write tx and so the changes to the object won't be persisted.  I haven't tested this.

Ezra, i ran across the following thread when researching related issues:
http://forum.hibernate.org/viewtopic.php?t=972377

Quote from one of the hibernate team:
"Read-only transactions are _not_ the same as session.setReadOnly() or
query.setReadOnly(). The first is a hint for weak DBMS implementations
that you only want to do SELECTs - a good DBMS transaction system
should figure this out automatically. The latter is a setting that
disables object snapshots at the Hibernate persistence context level."

I'm not using spring currently so haven't verified any of this.  Just
thought you might like to know.

Cheers, lasitha.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 20, 2007 12:11 AM, Ezra Epstein <ez...@yahoo.com> wrote:
> I imagine that if you use Spring's declarative transactions on the service layer so that the read()/get() method does not start a read/write transaction but the save() method does then changing the object without calling "save()" should just work - you won't be in a read/write tx and so the changes to the object won't be persisted.  I haven't tested this.

Thanks for that Ezra.  I'd like to see if we can do this without
resorting to spring (hence my interest in Thiago's HiberTapestry), but
the pattern is probably transferable.  Its similiar to Jonathan's
earlier suggestion, yes?

One caveat with this approach, as i understand it, is it relies on
additional configuration and programmer discipline for the most common
case:
@Transactional(readOnly=true)
Entity findEntity()
...
@Transactional()
void unitOfWork(Entity entity)

So if i - the careless, harried programmer - forget either to add the
annotation on the finder or to set the readOnly flag, i'm susceptible.
 Whats more the consequences of this may not be immediately noticeable
since we could easily not be testing for this odd case[1] and the save
could easily go through without error.

Anyway, it appears i have some work to do!
Cheers, lasitha.

[1] I'd probably test that validation kicks in and my mock dao isn't
called upon to save, but not that hibernate's flush didn't
inadvertently save.  Even if i did test this in an integration test,
i'd have to do this for every occurrence!

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Massimo Lusetti <ml...@gmail.com>.
On Nov 22, 2007 9:02 AM, lasitha <la...@gmail.com> wrote:

> Hmm, i must've missed where this was documented.  The api certainly
> doesn't mention anything about flushing on close, but i was
> uncomfortable assuming this, particularly since earlier versions of
> hibernate _did_ flush on close, if i recall.

"Force this session to flush. Must be called at the end of a unit of
work, before commiting the transaction and closing the session
(depending on flush-mode, Transaction.commit() calls this method)."

Taken from Session.flush() API from http://www.hibernate.org/hib_docs/v3/api/

Regards
-- 
Massimo
http://meridio.blogspot.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 22, 2007 1:20 PM, Massimo Lusetti <ml...@gmail.com> wrote:
> On Nov 22, 2007 8:37 AM, lasitha <la...@gmail.com> wrote:
>
> > A follow up for anyone keeping score:  i've just verified that
> > hibernate does _not_ automatically flush a Session when it is closed.
> > If anyone is interested i can pass along my learning test.
>
> That's clearly written in the API.
>

Hmm, i must've missed where this was documented.  The api certainly
doesn't mention anything about flushing on close, but i was
uncomfortable assuming this, particularly since earlier versions of
hibernate _did_ flush on close, if i recall.

In any case, my apologies for any unnecessary clutter.
lasitha.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Massimo Lusetti <ml...@gmail.com>.
On Nov 22, 2007 8:37 AM, lasitha <la...@gmail.com> wrote:

> A follow up for anyone keeping score:  i've just verified that
> hibernate does _not_ automatically flush a Session when it is closed.
> If anyone is interested i can pass along my learning test.

That's clearly written in the API.

Cheers
-- 
Massimo
http://meridio.blogspot.com

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 20, 2007 9:32 AM, lasitha <la...@gmail.com> wrote:
> ... In previous versions of hibernate, just
> closing a session automatically triggered a flush.

A follow up for anyone keeping score:  i've just verified that
hibernate does _not_ automatically flush a Session when it is closed.
If anyone is interested i can pass along my learning test.

Unfortunately, this isn't all that helpful in the context of
unexpected saves because in the default automatic flush mode, even a
simple query could trigger a flush.  If only i realized that _before_
spending time testing whether a close triggers a flush!

Cheers, lasitha.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Tue, 20 Nov 2007 02:02:18 -0200, lasitha <la...@gmail.com>  
wrote:

> Yes.  But my question pertains more to the span of the hibernate
> _session_ than to that of the transaction.
>
> A typical OSIV implementation keeps a single session open right until
> the end of a request so the view layer can access entities loaded in
> that request without having to worry about lazy-loading exceptions and
> such.

HiberTapestry follows the OSIV pattern. The difference with  
tapestry-hibernate is that HiberTapestry just opens a transaction when a  
@Transactional-annotated service method is invoked.

> If, otoh, it does keep a session open, does it flush the session at
> the end of the request?

At the end of a @Transactional-annotated service method that initiated a  
transaction, if no exception was thrown, the transaction is commited and,  
as a consequence, flushed. Otherwise, it is rolled back.

> Thanks for keeping up this thread - once i can look at your source i
> will bother you less :)

I'm just polishing it and adding more unit tests before I show my little  
creation for the world to see. :) Or you're not bothering me at all. :)

-- 
Thiago H. de Paula Figueiredo
Desenvolvedor, Instrutor e Consultor de Tecnologia
Eteg Tecnologia da Informação Ltda.
http://www.eteg.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 20, 2007 12:31 AM, Thiago H de Paula Figueiredo
<th...@gmail.com> wrote:
> On Mon, 19 Nov 2007 16:34:46 -0200, lasitha <la...@gmail.com>
> wrote:
>
> HiberTapestry does not work like tapestry-hibernate*, just opening a
> transaction when a transactional method is invoked. A method is
> transactional if it is @Transactional (an annotation of HiberTapestry) and
> it is declared in a service built by Tapestry-IoC. Therefore, in the
> scenario described above by Lasitha, no service method would be invoked
> and no changes to the edited object is propagated to the database.
>
> * As far as I can remember, tapestry-hibernate opens a session when the
> request starts and commits it at the end of it. Am I right?

Yes.  But my question pertains more to the span of the hibernate
_session_ than to that of the transaction.

A typical OSIV implementation keeps a single session open right until
the end of a request so the view layer can access entities loaded in
that request without having to worry about lazy-loading exceptions and
such.

If HiberTapestry doesn't keep a session open like this, then you're
right: you won't run into this problem.  But this then doesn't provide
the benefits of an OSIV.

If, otoh, it does keep a session open, does it flush the session at
the end of the request?  In previous versions of hibernate, just
closing a session automatically triggered a flush.  I will have to
check whether this is still the case.

Thanks for keeping up this thread - once i can look at your source i
will bother you less :)
lasitha.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Mon, 19 Nov 2007 16:34:46 -0200, lasitha <la...@gmail.com>  
wrote:

> Let me describe the problem in a little more detail. Assuming a
> typical OSIV setup, consider the following sequence of events:
> 1. A form is submitted.
> 2. The entity that backs the form is retrieved from the db in
> onActivate() or onPrepare().
> 3. The first set of validations pass and the entity's fields are
> populated by tapestry.
> 4. Our onValidate() method finds some problem and records errors on
> the validation tracker.
> 5. Tapestry redirects back to the same page so the user can correct
> their inputs.
> 6. The request ends and the active session is flushed.

HiberTapestry does not work like tapestry-hibernate*, just opening a  
transaction when a transactional method is invoked. A method is  
transactional if it is @Transactional (an annotation of HiberTapestry) and  
it is declared in a service built by Tapestry-IoC. Therefore, in the  
scenario described above by Lasitha, no service method would be invoked  
and no changes to the edited object is propagated to the database.

* As far as I can remember, tapestry-hibernate opens a session when the  
request starts and commits it at the end of it. Am I right?

-- 
Thiago H. de Paula Figueiredo
Desenvolvedor, Instrutor e Consultor de Tecnologia
Eteg Tecnologia da Informação Ltda.
http://www.eteg.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Mon, 19 Nov 2007 16:41:09 -0200, Ezra Epstein <ez...@yahoo.com>  
wrote:

> I imagine that if you use Spring's declarative transactions on the  
> service layer so that the read()/get() method does not start a  
> read/write transaction but the save() method does then changing the  
> object without calling "save()" should just work - you won't be in a  
> read/write tx and so the changes to the object won't be persisted.  I  
> haven't tested this.

HiberTapestry works similarly to Spring's declarative transactions,  
opening a transaction when a method is invoked and closing it when it  
finishes (commit or rollback, depending on whether the invoked method  
raised an exception of not).

-- 
Thiago H. de Paula Figueiredo
Desenvolvedor, Instrutor e Consultor de Tecnologia
Eteg Tecnologia da Informação Ltda.
http://www.eteg.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Ezra Epstein <ez...@yahoo.com>.
I imagine that if you use Spring's declarative transactions on the service layer so that the read()/get() method does not start a read/write transaction but the save() method does then changing the object without calling "save()" should just work - you won't be in a read/write tx and so the changes to the object won't be persisted.  I haven't tested this.

lasitha <la...@gmail.com> wrote: On Nov 19, 2007 10:35 PM, Thiago H de Paula Figueiredo
 wrote:
> I havent't noticed this problem before. Until now, HiberTapestry opens a
> transaction when a service method annotated with @Transactional is invoked
> and commits it when the method finishes without exceptions. Otherwise, the
> transaction is aborted.

Let me describe the problem in a little more detail. Assuming a
typical OSIV setup, consider the following sequence of events:
1. A form is submitted.
2. The entity that backs the form is retrieved from the db in
onActivate() or onPrepare().
3. The first set of validations pass and the entity's fields are
populated by tapestry.
4. Our onValidate() method finds some problem and records errors on
the validation tracker.
5. Tapestry redirects back to the same page so the user can correct
their inputs.
6. The request ends and the active session is flushed.

In the above sequence, we don't want to commit the modifications to
our entity, but the automatic dirty check initiated when the session
is flushed will detect and commit the changes from step 3.  Note that
the method to save our changes (that is presumably @Transactional) is
not even reached in this scenario because we never hit onSuccess().

Does that make sense?  Max, Jonathan and Ognen seem to confirm that
this is indeed a real consideration.

I suspect the solution is as simple as setting the hibernate flush
mode to MANUAL (and switching it AUTO just for the duration of an
explicitly declared transaction) - the way the spring folks do it.

Cheers, lasitha.

P.S. I goofed up the link to the spring OSIV interceptor in my
previous post.  Here's the correct one:
http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.html

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org



Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 19, 2007 10:35 PM, Thiago H de Paula Figueiredo
<th...@gmail.com> wrote:
> I havent't noticed this problem before. Until now, HiberTapestry opens a
> transaction when a service method annotated with @Transactional is invoked
> and commits it when the method finishes without exceptions. Otherwise, the
> transaction is aborted.

Let me describe the problem in a little more detail. Assuming a
typical OSIV setup, consider the following sequence of events:
1. A form is submitted.
2. The entity that backs the form is retrieved from the db in
onActivate() or onPrepare().
3. The first set of validations pass and the entity's fields are
populated by tapestry.
4. Our onValidate() method finds some problem and records errors on
the validation tracker.
5. Tapestry redirects back to the same page so the user can correct
their inputs.
6. The request ends and the active session is flushed.

In the above sequence, we don't want to commit the modifications to
our entity, but the automatic dirty check initiated when the session
is flushed will detect and commit the changes from step 3.  Note that
the method to save our changes (that is presumably @Transactional) is
not even reached in this scenario because we never hit onSuccess().

Does that make sense?  Max, Jonathan and Ognen seem to confirm that
this is indeed a real consideration.

I suspect the solution is as simple as setting the hibernate flush
mode to MANUAL (and switching it AUTO just for the duration of an
explicitly declared transaction) - the way the spring folks do it.

Cheers, lasitha.

P.S. I goofed up the link to the spring OSIV interceptor in my
previous post.  Here's the correct one:
http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.html

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Mon, 19 Nov 2007 14:19:28 -0200, lasitha <la...@gmail.com>  
wrote:

> On Nov 19, 2007 5:42 PM, Thiago H de Paula Figueiredo
> <th...@gmail.com> wrote:
>>
>> Hi, Lasitha! (By the way, where are you from?)
> Oh, the beautiful town of kandy, sri lanka :)

I'm from the not so beautiful city of Belo Horizonte, Minas Gerais state,  
Brazil. :)

> In the meantime, may i ask whether/how HiberTapestry solves the
> problem posed in this thread? To wit: hibernate will detect and commit
> changes to dirty objects even if we've realized mid way through the
> unit-of-work that it should be rejected.

I havent't noticed this problem before. Until now, HiberTapestry opens a  
transaction when a service method annotated with @Transactional is invoked  
and commits it when the method finishes without exceptions. Otherwise, the  
transaction is aborted.

> The Spring OSIV filter/interceptor avoids this problem by turning off
> automatic session flushing and relying on service layers to explicitly
> commit (either manually or declaratively)[2].

See paragraph above. :)

-- 
Thiago H. de Paula Figueiredo
Desenvolvedor, Instrutor e Consultor de Tecnologia
Eteg Tecnologia da Informação Ltda.
http://www.eteg.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by lasitha <la...@gmail.com>.
On Nov 19, 2007 5:42 PM, Thiago H de Paula Figueiredo
<th...@gmail.com> wrote:
>
> Hi, Lasitha! (By the way, where are you from?)
Oh, the beautiful town of kandy, sri lanka :)

> I'm planning to release the sources until this weekend.
Great, thanks!  Will be looking forward to it.

In the meantime, may i ask whether/how HiberTapestry solves the
problem posed in this thread? To wit: hibernate will detect and commit
changes to dirty objects even if we've realized mid way through the
unit-of-work that it should be rejected.

Earlier replies have suggested either intermediate objects or marking
retrieved objects as read only[1].

The Spring OSIV filter/interceptor avoids this problem by turning off
automatic session flushing and relying on service layers to explicitly
commit (either manually or declaratively)[2].

I've run across a variation of this where the
filter/interceptor/decorator always rolled back the active transaction
at the end of the request cycle. Service layers are again responsible
for committing desirable changes and a commit immediately begins a new
transaction on the same session (checkpointing?), so the rollback is a
no-op on most requests.

I suppose another option is to 'tell' the framework that we don't want
to commit by throwing an exception (ugh!).

Looking forward to your and other folks' thoughts on this.

> This is one of the best reasons to use open-source code: you don't need to
> trust something you don't know how it works. :)
>
Absolutely!  Gotta love it.

Cheers,
lasitha

Notes:
[1] http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Query.html#setReadOnly(boolean)
[2] http://static.springframework.org/spring/docs/2.0.x/api/index.html

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: T5: Tapestry-Hibernate, do we have to save()?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Mon, 19 Nov 2007 07:17:32 -0200, lasitha <la...@gmail.com>  
wrote:

> On Oct 31, 2007, Thiago H de Paula Figueiredo <th...@gmail.com> wrote:
>
> Thiago, any chance you'll be releasing the source soon?

Hi, Lasitha! (By the way, where are you from?)

I'm planning to release the sources until this weekend.

> I'm looking forward to trying it out but am hesitant to do so without
> first looking it over :).

This is one of the best reasons to use open-source code: you don't need to  
trust something you don't know how it works. :)

-- 
Thiago H. de Paula Figueiredo
Desenvolvedor, Instrutor e Consultor de Tecnologia
Eteg Tecnologia da Informação Ltda.
http://www.eteg.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org