You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Howard Lewis Ship <hl...@gmail.com> on 2006/06/12 17:45:20 UTC

Chat with James Carman r.e. Managing Transactions

James has been working on HiveMind + Spring libraries to implement the
transaction-per-request model for managing transactions within a Tapestry
application.

---------- Forwarded message ----------
From: James Carman <jw...@gmail.com>
Date: Mon Jun 12 08:39:43 PDT 2006
Subject: Chat with James Carman
To: hlship@gmail.com

7:44 AM James: You there, man?
 me: yes
7:45 AM James: didn't see you on or I would have asked you
  Jesse and I came up with an idea
  Wanna run it by you
  What if I put an interceptor on ListenerInvoker and ResponseRenderer to do
the tx stuff?
 me: ResponseRenderer makes sense.
 James: The one on ListenerInvoker would open up the committing transaction
and the one on ResponseRenderer would open up the one that gets rolled back
  The read-only one
7:46 AM me: ListenerInvoker a little less so ... it gets invoked anytime any
listener method gets invoked, which may be multiple times (especially with
the ajax stuff).
 James: ahhh, where do you suggest I "hook in" then?
7:47 AM me: In ePluribus, I do the commit after invoking annotated service
methods.
  But to avoid that, I would do it at the start of ResponseRenderer.
  You could actually replace ResponseRenderer, and have your impl invoke the
standard impl.
 James: Commit the 'global" transaction and start up a new one that gets
rolled back?
7:48 AM Commit the one that gets started by the TapernateFilter and then
start up a new read-only one?
  The tapernate filter will then take care of cleaning that up.
 me: Yes. Still on the fence about whether the render phase transaction
should be comitted or rolled back.
7:49 AM James: Well, one concern folks have is that the rendering code
doesn't alter any persistent objects
  But, that's a more JSP-oriented concern, I think. Could still be valid in
tap, though
7:50 AM Of course, you can turn off transaction-per-request and put
interceptors on your HiveMind services.
  That would start/commit a tx around it
7:51 AM me: .... so when are is HiveMind moving to
http://hivemind.apache.org?
7:52 AM James: As soon as infra gets done with the requests. I think they
asked me to clarify them a bit.
  I thought I did everything, but nothing has been moving, so I might have
to revisit that.
7:53 AM me: Standard stuff ... few people have the expertise and interest
and time and it's boring infrastructure stuff on top of that.
  Apache can't scale til much more of this stuff is automated, lke a
SourceForge.
 James: Yeah, I couldn't believe that it took weeks for someone to ask me to
give some clarification
7:55 AM So, what do you think is the best course of action for Tapernate? We
could just do a flush() before rendering begins
  And, not commit.
  Flush will check integrity and stuff
7:56 AM That's almost too simple, really
 me: You want to do a full commit, only way to ensure that changes are saved
and any locking conflicts identified.
7:57 AM James: Well, the lock conflicts should get identified during flush,
I would think
7:58 AM How many times does the ResponseRenderer get called during one
request cycle?
7:59 AM me: Just once, unless there's an exception, in which case it may be
called a second time. This is from memory.
 James: Oooh. Yuck.
  Is it nested?
 me: Also, I haven't looked at Jesse's 4.1. changes, which largely seem to
affect response rendering.
 James: I mean is the second call nested within the first call to
ResponseRenderer
8:00 AM me: I'm not sure.
 James: Or, the exception gets thrown from the renderResponse and the
ExceptionPresenter picks it up and tries to render the exception page?
8:01 AM ResponseRendererImpl doesn't have any try/catch logic in the
renderResponse method.
  It's actually surprisingly slim. Thanks to HiveMind! :-)
 me: I think BaseEngine catches any exception and re-invoked
ResponseRenderer after setting up the Exception page.
8:02 AM Yes ... I look at Spring code and it's really monolithic.
 James: Where does ExceptionPresenter enter the picture?
 me: I think it's what gets invoked by the Engine to present the exception.
It in turn invoked ResponseRenderer. Idea is that applications will override
this to change how Exceptions are presented (I often save an XML file with
the data, and jump back to Home).
8:03 AM James: Ahhhh, cool
  Okay, so where would you put the hook to start up the actual processing
transaction? Would you leave it as a WebRequestServicerFilter?
8:04 AM Or, would you hook in somewhere else? And, put a transaction
interceptor (with read-only tx demarcation) on the ResponseRenderer
servicee?
 me: Absolutely.
 James: service
  I could use PROPAGATION_REQUIRES_NEW, but I think that starts a new
Session
  That would suck, cause I want to use the stuff in my current session
  PROPAGATION_REQUIRES_NEW,readOnly
8:05 AM On the response renderer
8:06 AM me: BTW ... I'm going to forward this chat to the tap dev list.
 James: No problem. I'll try not to say anything nasty (hi folks).
  :-)
8:07 AM I would really like to get this right. It would be nice if I can put
an interceptor on another service that would be where "normal" update/insert
processing should occur.
8:08 AM update/insert/delete, that is
  Sorry
 me: I think just doing a commit before ResponseRenderer is the way to go.
In the rare case that there's a render-time exception, you'
 James: Then, the TapernateFilter would only be opening a session.
8:09 AM Well, that's the problem. Folks can turn off transaction-per-request
with Tapernate
  So, I don't necessarily have a tx going on at that point
8:10 AM Or, I could require that folks use transaction-per-request. :-)
  hehe
  I don't want to do that, though
 me: Your wrapper around ResponseRenderer can be sensitive to whether
transaction-per-request is enabled.
8:11 AM James: I'm trying to work through the scenario when someone has
turned it off and they're using an interceptor on their service method.
8:12 AM Hmmmmm
8:13 AM me: If transaction-per-request is off, then you start/commit a
transaction around each (intercepted) service method.
  Which is why you want transaction-per-request.
8:14 AM James: Ooooh. Side note. Do you think I should have done my Acegi
stuff using a ListenerInvokerFilter rather that Javassist stuff?
  And, maybe we could just require annotations for Tapernate and put another
ListenerInvokerFilter in there for that.
 me: I haven't looked at the Acegi stuff, sorry. It sounds similar to what I
did using @Privileged for Vaisala, which I did using Javassist.
 James: But, if I want to have multiple things doing this kind of
intercepting, I'm going to get an exception
8:15 AM Because i use addMethod rather than extendMethodImplementation
  Know what I mean?
 me: The idea of ListenerInvokerFilter is that you are working with an
IActionListener which may or may not be a wrapper around a method. In olden
days, it was not.
 James: But, that's where most insert/update/delete stuff should go on,
correct?
 me: I know what you mean about add vs. extend.
  It's a problem.
 James: I didn't like coding it that way
8:16 AM But, there's no way to get at the annotations. Is that what you're
saying, via ListenerInvokerFilter?
 me: I have to cop-out with "Tapestry 5".
 James: I guess I could check to see if it's a ListenerMethodBinding rather
than a SyntheticListener.
8:17 AM me: Yes, short of down-casting the IActionFilter and picking that
object apart, you can't get at the Method.
 James: IActionListener?
  Not IActionFilter?
 me: Obviously, there's a lot of new use cases out there that didn't exist
even when I was working on Tapestry 3, never mind today.
 James: hehe
 me: Yes, IActionListener.
8:18 AM James: Ok, cool. I thought you lost me there for a minute
  So, we can agree that listeners are where the "processing" will go on,
right?
  Insert/update/delete
 me: yes. Mostly by delegating to services.
 James: Hmmmmm.
8:19 AM Well, I require Tap4 anyway. Are those old listeners still
supported?
  I would guess so, since the SyntheticListener is in there.
8:20 AM me: Yes, if you want to provide an IActionListener inner class via
ognl: rather than a listener method via listener:, it all still works.
 James: ok, figured
  If multiple listeners are invoked, would it be nested?
  Because that wouldn't cause multiple txs
8:21 AM It'd just be a nested one.
 me: There's really just the one listener.
8:22 AM Tapestry 5 will have a more involved, and easier to hook, event
system. It'll be a little more "pull" based, where you will annotate methods
to be invoked under certain circumstances, such as when a particular
component is triggered by the request.
 James: One IActionListener per RequestCycle? So, if I put a transaction
interceptor on the ListenerInvoker service point with PROPAGATION_REQUIRED
and one on the ResponseRenderer with PROPAGATION_REQUIRED,readOnly
  You don't think that'd work?
8:23 AM What about for services like Asset and ExternalLink? Do those even
call the response renderer?
8:24 AM me: Nope; components like Hidden and InvokeListener will invoke
arbitrary listener methods as well. Also Submit.
 James: Not using the ListenerInvoker?
8:25 AM me: Services that don't respond with complete pages will not invoke
ResponseRenderer. Caveat Jesse's changes.
 James: Hmmmmm
  I think we're circling back to leaving it as a WebRequestServicerFilter.
8:26 AM But, services that don't render themselves shouldn't all necessarily
be committing data.
  A listener method might
  Like a DirectService
8:27 AM Do you think we should take this to the dev list to get more folks
thinking it through?
  My brain hurts. :-)
  Of course, we don't have to cover 100% of the cases. Just the most common.
8:28 AM If folks want to work outside the box, they can customize at will
8:31 AM me: yes, most common is the way to go.
  It's either commit or discard changes. And a commit with no actual changes
will be very cheap.
8:32 AM James: For the rendering part, I'm going to use
PROPAGATION_REQUIRED,readOnly
  So, whatever Spring does to clean up read-only transactions
  I don't know if they just roll it back or commit it somehow
8:37 AM me: Cool. I probably switch epluribus over when more of this is in
place.
  done?
 James: You mean our conversation?
 me: yes
 James: Well, I don't exactly know where to put the read/write tx stuff at
this point. Have we decided on the best approach?
8:38 AM I know we've gone around in circles quite a bit, so I may have just
missed it if we decided
8:39 AM me: I still favor hooking ResponseRenderer to commit the active
transaction before rendering the response.
 James: That should cover the majority
  But, if the whole thing was wrapped in a read-only tx
  oh, you're gone


-- 
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Jakarta HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

Re: Chat with James Carman r.e. Managing Transactions

Posted by Jesse Kuhnert <jk...@gmail.com>.
Sorry I didn't reply earlier today, verizon was screwing up my dsl service
and then decided to torture me for a couple hours with people who are only
allowed to follow a scripted support protocol :( (.. open ie do you see this
address ? no .. ok ...let's see what happens if you hit this address instead
- 'but I said already that the ppoe handshake is working fine and I'm
connected to your local dsl network, just not outside of that. the problem
is on verizons side somewhere else. my computer is fine. I dont want to
unplug anything anymore' - yes  ..umm...anyways go open blah .....)
garrr....

I like the general idea of one transaction wrapping direct requests (ie Form
submissions / links / whatever ) and another to handle the rendering phase
via ResponseRenderer .

It sounds like the transactional failure/update semantics are all that's
left to resolve? I know you would in theory be able to check if the request
was for a Form and then check that Form's ValidationDelegate for any errors
to do an auto-rollback if that was desired?

People will definitely need the transactional parts to be ~very~
configurable either way....Hmmmm...

Maybe you should humor us with a quick state transition table that outlines
a few of the possible scenerios so we know what "problem" we're dealing with
and then come up with a solution? I'd be more helpful but this looks like
the part you get to suffer through for the benefit in enjoying the tapernate
glory :) (Of course I/Howard will be helpful in directing you to specific
pieces of code /etc once you know what it is that you want to do )

Or something like that...Blehh ..

On 6/12/06, Ted Steen <te...@gmail.com> wrote:
>
> I just want to add this to the discussion, it is a copy from an old
> post i made on the users-list a couple of weeks ago.
>
> "If I work directly on my domain model in the "tapestry layer", then
> data on forms that do _not_ validate, get persisted. This on the other
> hand could be solved by calling setRollBackOnly() if the form didn't
> validate (which, I think, is not very clean).
>
> But if the edited object get passed around on different pages (e.g.
> some kind of preview service or multiple step form wizard etc..) the
> object gets saved outside of my control.
> I want my altered objects to go through my business layer before they
> get persisted.
>
> Any suggestions here? I need to settle for a design that gives me
> total control of what is persisted and what is not.
> Maybe I shouldn't have domain objects in my tapestry layer...?"
>
>
> 2006/6/12, Howard Lewis Ship <hl...@gmail.com>:
> > Everyone else took at step backwards :-)
> >
> > On 6/12/06, James Carman <ja...@carmanconsulting.com> wrote:
> > >
> > > How about if we buffer the response data and only write it back out if
> the
> > > wrapping transaction commits successfully?
> > >
> > >
> > > -----Original Message-----
> > > From: Howard Lewis Ship [mailto:hlship@gmail.com]
> > > Sent: Monday, June 12, 2006 11:45 AM
> > > To: Tapestry development
> > > Subject: Chat with James Carman r.e. Managing Transactions
> > >
> > > James has been working on HiveMind + Spring libraries to implement the
> > > transaction-per-request model for managing transactions within a
> Tapestry
> > > application.
> > >
> > > ---------- Forwarded message ----------
> > > From: James Carman <jw...@gmail.com>
> > > Date: Mon Jun 12 08:39:43 PDT 2006
> > > Subject: Chat with James Carman
> > > To: hlship@gmail.com
> > >
> > > 7:44 AM James: You there, man?
> > > me: yes
> > > 7:45 AM James: didn't see you on or I would have asked you
> > >   Jesse and I came up with an idea
> > >   Wanna run it by you
> > >   What if I put an interceptor on ListenerInvoker and ResponseRenderer
> to
> > > do
> > > the tx stuff?
> > > me: ResponseRenderer makes sense.
> > > James: The one on ListenerInvoker would open up the committing
> transaction
> > > and the one on ResponseRenderer would open up the one that gets rolled
> > > back
> > >   The read-only one
> > > 7:46 AM me: ListenerInvoker a little less so ... it gets invoked
> anytime
> > > any
> > > listener method gets invoked, which may be multiple times (especially
> with
> > > the ajax stuff).
> > > James: ahhh, where do you suggest I "hook in" then?
> > > 7:47 AM me: In ePluribus, I do the commit after invoking annotated
> service
> > > methods.
> > >   But to avoid that, I would do it at the start of ResponseRenderer.
> > >   You could actually replace ResponseRenderer, and have your impl
> invoke
> > > the
> > > standard impl.
> > > James: Commit the 'global" transaction and start up a new one that
> gets
> > > rolled back?
> > > 7:48 AM Commit the one that gets started by the TapernateFilter and
> then
> > > start up a new read-only one?
> > >   The tapernate filter will then take care of cleaning that up.
> > > me: Yes. Still on the fence about whether the render phase transaction
> > > should be comitted or rolled back.
> > > 7:49 AM James: Well, one concern folks have is that the rendering code
> > > doesn't alter any persistent objects
> > >   But, that's a more JSP-oriented concern, I think. Could still be
> valid
> > > in
> > > tap, though
> > > 7:50 AM Of course, you can turn off transaction-per-request and put
> > > interceptors on your HiveMind services.
> > >   That would start/commit a tx around it
> > > 7:51 AM me: .... so when are is HiveMind moving to
> > > http://hivemind.apache.org?
> > > 7:52 AM James: As soon as infra gets done with the requests. I think
> they
> > > asked me to clarify them a bit.
> > >   I thought I did everything, but nothing has been moving, so I might
> have
> > > to revisit that.
> > > 7:53 AM me: Standard stuff ... few people have the expertise and
> interest
> > > and time and it's boring infrastructure stuff on top of that.
> > >   Apache can't scale til much more of this stuff is automated, lke a
> > > SourceForge.
> > > James: Yeah, I couldn't believe that it took weeks for someone to ask
> me
> > > to
> > > give some clarification
> > > 7:55 AM So, what do you think is the best course of action for
> Tapernate?
> > > We
> > > could just do a flush() before rendering begins
> > >   And, not commit.
> > >   Flush will check integrity and stuff
> > > 7:56 AM That's almost too simple, really
> > > me: You want to do a full commit, only way to ensure that changes are
> > > saved
> > > and any locking conflicts identified.
> > > 7:57 AM James: Well, the lock conflicts should get identified during
> > > flush,
> > > I would think
> > > 7:58 AM How many times does the ResponseRenderer get called during one
> > > request cycle?
> > > 7:59 AM me: Just once, unless there's an exception, in which case it
> may
> > > be
> > > called a second time. This is from memory.
> > > James: Oooh. Yuck.
> > >   Is it nested?
> > > me: Also, I haven't looked at Jesse's 4.1. changes, which largely seem
> to
> > > affect response rendering.
> > > James: I mean is the second call nested within the first call to
> > > ResponseRenderer
> > > 8:00 AM me: I'm not sure.
> > > James: Or, the exception gets thrown from the renderResponse and the
> > > ExceptionPresenter picks it up and tries to render the exception page?
> > > 8:01 AM ResponseRendererImpl doesn't have any try/catch logic in the
> > > renderResponse method.
> > >   It's actually surprisingly slim. Thanks to HiveMind! :-)
> > > me: I think BaseEngine catches any exception and re-invoked
> > > ResponseRenderer after setting up the Exception page.
> > > 8:02 AM Yes ... I look at Spring code and it's really monolithic.
> > > James: Where does ExceptionPresenter enter the picture?
> > > me: I think it's what gets invoked by the Engine to present the
> exception.
> > > It in turn invoked ResponseRenderer. Idea is that applications will
> > > override
> > > this to change how Exceptions are presented (I often save an XML file
> with
> > > the data, and jump back to Home).
> > > 8:03 AM James: Ahhhh, cool
> > >   Okay, so where would you put the hook to start up the actual
> processing
> > > transaction? Would you leave it as a WebRequestServicerFilter?
> > > 8:04 AM Or, would you hook in somewhere else? And, put a transaction
> > > interceptor (with read-only tx demarcation) on the ResponseRenderer
> > > servicee?
> > > me: Absolutely.
> > > James: service
> > >   I could use PROPAGATION_REQUIRES_NEW, but I think that starts a new
> > > Session
> > >   That would suck, cause I want to use the stuff in my current session
> > >   PROPAGATION_REQUIRES_NEW,readOnly
> > > 8:05 AM On the response renderer
> > > 8:06 AM me: BTW ... I'm going to forward this chat to the tap dev
> list.
> > > James: No problem. I'll try not to say anything nasty (hi folks).
> > >   :-)
> > > 8:07 AM I would really like to get this right. It would be nice if I
> can
> > > put
> > > an interceptor on another service that would be where "normal"
> > > update/insert
> > > processing should occur.
> > > 8:08 AM update/insert/delete, that is
> > >   Sorry
> > > me: I think just doing a commit before ResponseRenderer is the way to
> go.
> > > In the rare case that there's a render-time exception, you'
> > > James: Then, the TapernateFilter would only be opening a session.
> > > 8:09 AM Well, that's the problem. Folks can turn off
> > > transaction-per-request
> > > with Tapernate
> > >   So, I don't necessarily have a tx going on at that point
> > > 8:10 AM Or, I could require that folks use transaction-per-request.
> :-)
> > >   hehe
> > >   I don't want to do that, though
> > > me: Your wrapper around ResponseRenderer can be sensitive to whether
> > > transaction-per-request is enabled.
> > > 8:11 AM James: I'm trying to work through the scenario when someone
> has
> > > turned it off and they're using an interceptor on their service
> method.
> > > 8:12 AM Hmmmmm
> > > 8:13 AM me: If transaction-per-request is off, then you start/commit a
> > > transaction around each (intercepted) service method.
> > >   Which is why you want transaction-per-request.
> > > 8:14 AM James: Ooooh. Side note. Do you think I should have done my
> Acegi
> > > stuff using a ListenerInvokerFilter rather that Javassist stuff?
> > >   And, maybe we could just require annotations for Tapernate and put
> > > another
> > > ListenerInvokerFilter in there for that.
> > > me: I haven't looked at the Acegi stuff, sorry. It sounds similar to
> what
> > > I
> > > did using @Privileged for Vaisala, which I did using Javassist.
> > > James: But, if I want to have multiple things doing this kind of
> > > intercepting, I'm going to get an exception
> > > 8:15 AM Because i use addMethod rather than extendMethodImplementation
> > >   Know what I mean?
> > > me: The idea of ListenerInvokerFilter is that you are working with an
> > > IActionListener which may or may not be a wrapper around a method. In
> > > olden
> > > days, it was not.
> > > James: But, that's where most insert/update/delete stuff should go on,
> > > correct?
> > > me: I know what you mean about add vs. extend.
> > >   It's a problem.
> > > James: I didn't like coding it that way
> > > 8:16 AM But, there's no way to get at the annotations. Is that what
> you're
> > > saying, via ListenerInvokerFilter?
> > > me: I have to cop-out with "Tapestry 5".
> > > James: I guess I could check to see if it's a ListenerMethodBinding
> rather
> > > than a SyntheticListener.
> > > 8:17 AM me: Yes, short of down-casting the IActionFilter and picking
> that
> > > object apart, you can't get at the Method.
> > > James: IActionListener?
> > >   Not IActionFilter?
> > > me: Obviously, there's a lot of new use cases out there that didn't
> exist
> > > even when I was working on Tapestry 3, never mind today.
> > > James: hehe
> > > me: Yes, IActionListener.
> > > 8:18 AM James: Ok, cool. I thought you lost me there for a minute
> > >   So, we can agree that listeners are where the "processing" will go
> on,
> > > right?
> > >   Insert/update/delete
> > > me: yes. Mostly by delegating to services.
> > > James: Hmmmmm.
> > > 8:19 AM Well, I require Tap4 anyway. Are those old listeners still
> > > supported?
> > >   I would guess so, since the SyntheticListener is in there.
> > > 8:20 AM me: Yes, if you want to provide an IActionListener inner class
> via
> > > ognl: rather than a listener method via listener:, it all still works.
> > > James: ok, figured
> > >   If multiple listeners are invoked, would it be nested?
> > >   Because that wouldn't cause multiple txs
> > > 8:21 AM It'd just be a nested one.
> > > me: There's really just the one listener.
> > > 8:22 AM Tapestry 5 will have a more involved, and easier to hook,
> event
> > > system. It'll be a little more "pull" based, where you will annotate
> > > methods
> > > to be invoked under certain circumstances, such as when a particular
> > > component is triggered by the request.
> > > James: One IActionListener per RequestCycle? So, if I put a
> transaction
> > > interceptor on the ListenerInvoker service point with
> PROPAGATION_REQUIRED
> > > and one on the ResponseRenderer with PROPAGATION_REQUIRED,readOnly
> > >   You don't think that'd work?
> > > 8:23 AM What about for services like Asset and ExternalLink? Do those
> even
> > > call the response renderer?
> > > 8:24 AM me: Nope; components like Hidden and InvokeListener will
> invoke
> > > arbitrary listener methods as well. Also Submit.
> > > James: Not using the ListenerInvoker?
> > > 8:25 AM me: Services that don't respond with complete pages will not
> > > invoke
> > > ResponseRenderer. Caveat Jesse's changes.
> > > James: Hmmmmm
> > >   I think we're circling back to leaving it as a
> WebRequestServicerFilter.
> > > 8:26 AM But, services that don't render themselves shouldn't all
> > > necessarily
> > > be committing data.
> > >   A listener method might
> > >   Like a DirectService
> > > 8:27 AM Do you think we should take this to the dev list to get more
> folks
> > > thinking it through?
> > >   My brain hurts. :-)
> > >   Of course, we don't have to cover 100% of the cases. Just the most
> > > common.
> > > 8:28 AM If folks want to work outside the box, they can customize at
> will
> > > 8:31 AM me: yes, most common is the way to go.
> > >   It's either commit or discard changes. And a commit with no actual
> > > changes
> > > will be very cheap.
> > > 8:32 AM James: For the rendering part, I'm going to use
> > > PROPAGATION_REQUIRED,readOnly
> > >   So, whatever Spring does to clean up read-only transactions
> > >   I don't know if they just roll it back or commit it somehow
> > > 8:37 AM me: Cool. I probably switch epluribus over when more of this
> is in
> > > place.
> > >   done?
> > > James: You mean our conversation?
> > > me: yes
> > > James: Well, I don't exactly know where to put the read/write tx stuff
> at
> > > this point. Have we decided on the best approach?
> > > 8:38 AM I know we've gone around in circles quite a bit, so I may have
> > > just
> > > missed it if we decided
> > > 8:39 AM me: I still favor hooking ResponseRenderer to commit the
> active
> > > transaction before rendering the response.
> > > James: That should cover the majority
> > >   But, if the whole thing was wrapped in a read-only tx
> > >   oh, you're gone
> > >
> > >
> > > --
> > > Howard M. Lewis Ship
> > > Independent J2EE / Open-Source Java Consultant
> > > Creator and PMC Chair, Apache Tapestry
> > > Creator, Jakarta HiveMind
> > >
> > > Professional Tapestry training, mentoring, support
> > > and project work.  http://howardlewisship.com
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> > > For additional commands, e-mail: dev-help@tapestry.apache.org
> > >
> > >
> >
> >
> > --
> > Howard M. Lewis Ship
> > Independent J2EE / Open-Source Java Consultant
> > Creator and PMC Chair, Apache Tapestry
> > Creator, Jakarta HiveMind
> >
> > Professional Tapestry training, mentoring, support
> > and project work.  http://howardlewisship.com
> >
> >
>
>
> --
> ted
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Jesse Kuhnert
Tacos/Tapestry, team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind.

Re: Chat with James Carman r.e. Managing Transactions

Posted by Ted Steen <te...@gmail.com>.
I just want to add this to the discussion, it is a copy from an old
post i made on the users-list a couple of weeks ago.

"If I work directly on my domain model in the "tapestry layer", then
data on forms that do _not_ validate, get persisted. This on the other
hand could be solved by calling setRollBackOnly() if the form didn't
validate (which, I think, is not very clean).

But if the edited object get passed around on different pages (e.g.
some kind of preview service or multiple step form wizard etc..) the
object gets saved outside of my control.
I want my altered objects to go through my business layer before they
get persisted.

Any suggestions here? I need to settle for a design that gives me
total control of what is persisted and what is not.
Maybe I shouldn't have domain objects in my tapestry layer...?"


2006/6/12, Howard Lewis Ship <hl...@gmail.com>:
> Everyone else took at step backwards :-)
>
> On 6/12/06, James Carman <ja...@carmanconsulting.com> wrote:
> >
> > How about if we buffer the response data and only write it back out if the
> > wrapping transaction commits successfully?
> >
> >
> > -----Original Message-----
> > From: Howard Lewis Ship [mailto:hlship@gmail.com]
> > Sent: Monday, June 12, 2006 11:45 AM
> > To: Tapestry development
> > Subject: Chat with James Carman r.e. Managing Transactions
> >
> > James has been working on HiveMind + Spring libraries to implement the
> > transaction-per-request model for managing transactions within a Tapestry
> > application.
> >
> > ---------- Forwarded message ----------
> > From: James Carman <jw...@gmail.com>
> > Date: Mon Jun 12 08:39:43 PDT 2006
> > Subject: Chat with James Carman
> > To: hlship@gmail.com
> >
> > 7:44 AM James: You there, man?
> > me: yes
> > 7:45 AM James: didn't see you on or I would have asked you
> >   Jesse and I came up with an idea
> >   Wanna run it by you
> >   What if I put an interceptor on ListenerInvoker and ResponseRenderer to
> > do
> > the tx stuff?
> > me: ResponseRenderer makes sense.
> > James: The one on ListenerInvoker would open up the committing transaction
> > and the one on ResponseRenderer would open up the one that gets rolled
> > back
> >   The read-only one
> > 7:46 AM me: ListenerInvoker a little less so ... it gets invoked anytime
> > any
> > listener method gets invoked, which may be multiple times (especially with
> > the ajax stuff).
> > James: ahhh, where do you suggest I "hook in" then?
> > 7:47 AM me: In ePluribus, I do the commit after invoking annotated service
> > methods.
> >   But to avoid that, I would do it at the start of ResponseRenderer.
> >   You could actually replace ResponseRenderer, and have your impl invoke
> > the
> > standard impl.
> > James: Commit the 'global" transaction and start up a new one that gets
> > rolled back?
> > 7:48 AM Commit the one that gets started by the TapernateFilter and then
> > start up a new read-only one?
> >   The tapernate filter will then take care of cleaning that up.
> > me: Yes. Still on the fence about whether the render phase transaction
> > should be comitted or rolled back.
> > 7:49 AM James: Well, one concern folks have is that the rendering code
> > doesn't alter any persistent objects
> >   But, that's a more JSP-oriented concern, I think. Could still be valid
> > in
> > tap, though
> > 7:50 AM Of course, you can turn off transaction-per-request and put
> > interceptors on your HiveMind services.
> >   That would start/commit a tx around it
> > 7:51 AM me: .... so when are is HiveMind moving to
> > http://hivemind.apache.org?
> > 7:52 AM James: As soon as infra gets done with the requests. I think they
> > asked me to clarify them a bit.
> >   I thought I did everything, but nothing has been moving, so I might have
> > to revisit that.
> > 7:53 AM me: Standard stuff ... few people have the expertise and interest
> > and time and it's boring infrastructure stuff on top of that.
> >   Apache can't scale til much more of this stuff is automated, lke a
> > SourceForge.
> > James: Yeah, I couldn't believe that it took weeks for someone to ask me
> > to
> > give some clarification
> > 7:55 AM So, what do you think is the best course of action for Tapernate?
> > We
> > could just do a flush() before rendering begins
> >   And, not commit.
> >   Flush will check integrity and stuff
> > 7:56 AM That's almost too simple, really
> > me: You want to do a full commit, only way to ensure that changes are
> > saved
> > and any locking conflicts identified.
> > 7:57 AM James: Well, the lock conflicts should get identified during
> > flush,
> > I would think
> > 7:58 AM How many times does the ResponseRenderer get called during one
> > request cycle?
> > 7:59 AM me: Just once, unless there's an exception, in which case it may
> > be
> > called a second time. This is from memory.
> > James: Oooh. Yuck.
> >   Is it nested?
> > me: Also, I haven't looked at Jesse's 4.1. changes, which largely seem to
> > affect response rendering.
> > James: I mean is the second call nested within the first call to
> > ResponseRenderer
> > 8:00 AM me: I'm not sure.
> > James: Or, the exception gets thrown from the renderResponse and the
> > ExceptionPresenter picks it up and tries to render the exception page?
> > 8:01 AM ResponseRendererImpl doesn't have any try/catch logic in the
> > renderResponse method.
> >   It's actually surprisingly slim. Thanks to HiveMind! :-)
> > me: I think BaseEngine catches any exception and re-invoked
> > ResponseRenderer after setting up the Exception page.
> > 8:02 AM Yes ... I look at Spring code and it's really monolithic.
> > James: Where does ExceptionPresenter enter the picture?
> > me: I think it's what gets invoked by the Engine to present the exception.
> > It in turn invoked ResponseRenderer. Idea is that applications will
> > override
> > this to change how Exceptions are presented (I often save an XML file with
> > the data, and jump back to Home).
> > 8:03 AM James: Ahhhh, cool
> >   Okay, so where would you put the hook to start up the actual processing
> > transaction? Would you leave it as a WebRequestServicerFilter?
> > 8:04 AM Or, would you hook in somewhere else? And, put a transaction
> > interceptor (with read-only tx demarcation) on the ResponseRenderer
> > servicee?
> > me: Absolutely.
> > James: service
> >   I could use PROPAGATION_REQUIRES_NEW, but I think that starts a new
> > Session
> >   That would suck, cause I want to use the stuff in my current session
> >   PROPAGATION_REQUIRES_NEW,readOnly
> > 8:05 AM On the response renderer
> > 8:06 AM me: BTW ... I'm going to forward this chat to the tap dev list.
> > James: No problem. I'll try not to say anything nasty (hi folks).
> >   :-)
> > 8:07 AM I would really like to get this right. It would be nice if I can
> > put
> > an interceptor on another service that would be where "normal"
> > update/insert
> > processing should occur.
> > 8:08 AM update/insert/delete, that is
> >   Sorry
> > me: I think just doing a commit before ResponseRenderer is the way to go.
> > In the rare case that there's a render-time exception, you'
> > James: Then, the TapernateFilter would only be opening a session.
> > 8:09 AM Well, that's the problem. Folks can turn off
> > transaction-per-request
> > with Tapernate
> >   So, I don't necessarily have a tx going on at that point
> > 8:10 AM Or, I could require that folks use transaction-per-request. :-)
> >   hehe
> >   I don't want to do that, though
> > me: Your wrapper around ResponseRenderer can be sensitive to whether
> > transaction-per-request is enabled.
> > 8:11 AM James: I'm trying to work through the scenario when someone has
> > turned it off and they're using an interceptor on their service method.
> > 8:12 AM Hmmmmm
> > 8:13 AM me: If transaction-per-request is off, then you start/commit a
> > transaction around each (intercepted) service method.
> >   Which is why you want transaction-per-request.
> > 8:14 AM James: Ooooh. Side note. Do you think I should have done my Acegi
> > stuff using a ListenerInvokerFilter rather that Javassist stuff?
> >   And, maybe we could just require annotations for Tapernate and put
> > another
> > ListenerInvokerFilter in there for that.
> > me: I haven't looked at the Acegi stuff, sorry. It sounds similar to what
> > I
> > did using @Privileged for Vaisala, which I did using Javassist.
> > James: But, if I want to have multiple things doing this kind of
> > intercepting, I'm going to get an exception
> > 8:15 AM Because i use addMethod rather than extendMethodImplementation
> >   Know what I mean?
> > me: The idea of ListenerInvokerFilter is that you are working with an
> > IActionListener which may or may not be a wrapper around a method. In
> > olden
> > days, it was not.
> > James: But, that's where most insert/update/delete stuff should go on,
> > correct?
> > me: I know what you mean about add vs. extend.
> >   It's a problem.
> > James: I didn't like coding it that way
> > 8:16 AM But, there's no way to get at the annotations. Is that what you're
> > saying, via ListenerInvokerFilter?
> > me: I have to cop-out with "Tapestry 5".
> > James: I guess I could check to see if it's a ListenerMethodBinding rather
> > than a SyntheticListener.
> > 8:17 AM me: Yes, short of down-casting the IActionFilter and picking that
> > object apart, you can't get at the Method.
> > James: IActionListener?
> >   Not IActionFilter?
> > me: Obviously, there's a lot of new use cases out there that didn't exist
> > even when I was working on Tapestry 3, never mind today.
> > James: hehe
> > me: Yes, IActionListener.
> > 8:18 AM James: Ok, cool. I thought you lost me there for a minute
> >   So, we can agree that listeners are where the "processing" will go on,
> > right?
> >   Insert/update/delete
> > me: yes. Mostly by delegating to services.
> > James: Hmmmmm.
> > 8:19 AM Well, I require Tap4 anyway. Are those old listeners still
> > supported?
> >   I would guess so, since the SyntheticListener is in there.
> > 8:20 AM me: Yes, if you want to provide an IActionListener inner class via
> > ognl: rather than a listener method via listener:, it all still works.
> > James: ok, figured
> >   If multiple listeners are invoked, would it be nested?
> >   Because that wouldn't cause multiple txs
> > 8:21 AM It'd just be a nested one.
> > me: There's really just the one listener.
> > 8:22 AM Tapestry 5 will have a more involved, and easier to hook, event
> > system. It'll be a little more "pull" based, where you will annotate
> > methods
> > to be invoked under certain circumstances, such as when a particular
> > component is triggered by the request.
> > James: One IActionListener per RequestCycle? So, if I put a transaction
> > interceptor on the ListenerInvoker service point with PROPAGATION_REQUIRED
> > and one on the ResponseRenderer with PROPAGATION_REQUIRED,readOnly
> >   You don't think that'd work?
> > 8:23 AM What about for services like Asset and ExternalLink? Do those even
> > call the response renderer?
> > 8:24 AM me: Nope; components like Hidden and InvokeListener will invoke
> > arbitrary listener methods as well. Also Submit.
> > James: Not using the ListenerInvoker?
> > 8:25 AM me: Services that don't respond with complete pages will not
> > invoke
> > ResponseRenderer. Caveat Jesse's changes.
> > James: Hmmmmm
> >   I think we're circling back to leaving it as a WebRequestServicerFilter.
> > 8:26 AM But, services that don't render themselves shouldn't all
> > necessarily
> > be committing data.
> >   A listener method might
> >   Like a DirectService
> > 8:27 AM Do you think we should take this to the dev list to get more folks
> > thinking it through?
> >   My brain hurts. :-)
> >   Of course, we don't have to cover 100% of the cases. Just the most
> > common.
> > 8:28 AM If folks want to work outside the box, they can customize at will
> > 8:31 AM me: yes, most common is the way to go.
> >   It's either commit or discard changes. And a commit with no actual
> > changes
> > will be very cheap.
> > 8:32 AM James: For the rendering part, I'm going to use
> > PROPAGATION_REQUIRED,readOnly
> >   So, whatever Spring does to clean up read-only transactions
> >   I don't know if they just roll it back or commit it somehow
> > 8:37 AM me: Cool. I probably switch epluribus over when more of this is in
> > place.
> >   done?
> > James: You mean our conversation?
> > me: yes
> > James: Well, I don't exactly know where to put the read/write tx stuff at
> > this point. Have we decided on the best approach?
> > 8:38 AM I know we've gone around in circles quite a bit, so I may have
> > just
> > missed it if we decided
> > 8:39 AM me: I still favor hooking ResponseRenderer to commit the active
> > transaction before rendering the response.
> > James: That should cover the majority
> >   But, if the whole thing was wrapped in a read-only tx
> >   oh, you're gone
> >
> >
> > --
> > Howard M. Lewis Ship
> > Independent J2EE / Open-Source Java Consultant
> > Creator and PMC Chair, Apache Tapestry
> > Creator, Jakarta HiveMind
> >
> > Professional Tapestry training, mentoring, support
> > and project work.  http://howardlewisship.com
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> > For additional commands, e-mail: dev-help@tapestry.apache.org
> >
> >
>
>
> --
> Howard M. Lewis Ship
> Independent J2EE / Open-Source Java Consultant
> Creator and PMC Chair, Apache Tapestry
> Creator, Jakarta HiveMind
>
> Professional Tapestry training, mentoring, support
> and project work.  http://howardlewisship.com
>
>


-- 
ted

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


Re: Chat with James Carman r.e. Managing Transactions

Posted by Howard Lewis Ship <hl...@gmail.com>.
Everyone else took at step backwards :-)

On 6/12/06, James Carman <ja...@carmanconsulting.com> wrote:
>
> How about if we buffer the response data and only write it back out if the
> wrapping transaction commits successfully?
>
>
> -----Original Message-----
> From: Howard Lewis Ship [mailto:hlship@gmail.com]
> Sent: Monday, June 12, 2006 11:45 AM
> To: Tapestry development
> Subject: Chat with James Carman r.e. Managing Transactions
>
> James has been working on HiveMind + Spring libraries to implement the
> transaction-per-request model for managing transactions within a Tapestry
> application.
>
> ---------- Forwarded message ----------
> From: James Carman <jw...@gmail.com>
> Date: Mon Jun 12 08:39:43 PDT 2006
> Subject: Chat with James Carman
> To: hlship@gmail.com
>
> 7:44 AM James: You there, man?
> me: yes
> 7:45 AM James: didn't see you on or I would have asked you
>   Jesse and I came up with an idea
>   Wanna run it by you
>   What if I put an interceptor on ListenerInvoker and ResponseRenderer to
> do
> the tx stuff?
> me: ResponseRenderer makes sense.
> James: The one on ListenerInvoker would open up the committing transaction
> and the one on ResponseRenderer would open up the one that gets rolled
> back
>   The read-only one
> 7:46 AM me: ListenerInvoker a little less so ... it gets invoked anytime
> any
> listener method gets invoked, which may be multiple times (especially with
> the ajax stuff).
> James: ahhh, where do you suggest I "hook in" then?
> 7:47 AM me: In ePluribus, I do the commit after invoking annotated service
> methods.
>   But to avoid that, I would do it at the start of ResponseRenderer.
>   You could actually replace ResponseRenderer, and have your impl invoke
> the
> standard impl.
> James: Commit the 'global" transaction and start up a new one that gets
> rolled back?
> 7:48 AM Commit the one that gets started by the TapernateFilter and then
> start up a new read-only one?
>   The tapernate filter will then take care of cleaning that up.
> me: Yes. Still on the fence about whether the render phase transaction
> should be comitted or rolled back.
> 7:49 AM James: Well, one concern folks have is that the rendering code
> doesn't alter any persistent objects
>   But, that's a more JSP-oriented concern, I think. Could still be valid
> in
> tap, though
> 7:50 AM Of course, you can turn off transaction-per-request and put
> interceptors on your HiveMind services.
>   That would start/commit a tx around it
> 7:51 AM me: .... so when are is HiveMind moving to
> http://hivemind.apache.org?
> 7:52 AM James: As soon as infra gets done with the requests. I think they
> asked me to clarify them a bit.
>   I thought I did everything, but nothing has been moving, so I might have
> to revisit that.
> 7:53 AM me: Standard stuff ... few people have the expertise and interest
> and time and it's boring infrastructure stuff on top of that.
>   Apache can't scale til much more of this stuff is automated, lke a
> SourceForge.
> James: Yeah, I couldn't believe that it took weeks for someone to ask me
> to
> give some clarification
> 7:55 AM So, what do you think is the best course of action for Tapernate?
> We
> could just do a flush() before rendering begins
>   And, not commit.
>   Flush will check integrity and stuff
> 7:56 AM That's almost too simple, really
> me: You want to do a full commit, only way to ensure that changes are
> saved
> and any locking conflicts identified.
> 7:57 AM James: Well, the lock conflicts should get identified during
> flush,
> I would think
> 7:58 AM How many times does the ResponseRenderer get called during one
> request cycle?
> 7:59 AM me: Just once, unless there's an exception, in which case it may
> be
> called a second time. This is from memory.
> James: Oooh. Yuck.
>   Is it nested?
> me: Also, I haven't looked at Jesse's 4.1. changes, which largely seem to
> affect response rendering.
> James: I mean is the second call nested within the first call to
> ResponseRenderer
> 8:00 AM me: I'm not sure.
> James: Or, the exception gets thrown from the renderResponse and the
> ExceptionPresenter picks it up and tries to render the exception page?
> 8:01 AM ResponseRendererImpl doesn't have any try/catch logic in the
> renderResponse method.
>   It's actually surprisingly slim. Thanks to HiveMind! :-)
> me: I think BaseEngine catches any exception and re-invoked
> ResponseRenderer after setting up the Exception page.
> 8:02 AM Yes ... I look at Spring code and it's really monolithic.
> James: Where does ExceptionPresenter enter the picture?
> me: I think it's what gets invoked by the Engine to present the exception.
> It in turn invoked ResponseRenderer. Idea is that applications will
> override
> this to change how Exceptions are presented (I often save an XML file with
> the data, and jump back to Home).
> 8:03 AM James: Ahhhh, cool
>   Okay, so where would you put the hook to start up the actual processing
> transaction? Would you leave it as a WebRequestServicerFilter?
> 8:04 AM Or, would you hook in somewhere else? And, put a transaction
> interceptor (with read-only tx demarcation) on the ResponseRenderer
> servicee?
> me: Absolutely.
> James: service
>   I could use PROPAGATION_REQUIRES_NEW, but I think that starts a new
> Session
>   That would suck, cause I want to use the stuff in my current session
>   PROPAGATION_REQUIRES_NEW,readOnly
> 8:05 AM On the response renderer
> 8:06 AM me: BTW ... I'm going to forward this chat to the tap dev list.
> James: No problem. I'll try not to say anything nasty (hi folks).
>   :-)
> 8:07 AM I would really like to get this right. It would be nice if I can
> put
> an interceptor on another service that would be where "normal"
> update/insert
> processing should occur.
> 8:08 AM update/insert/delete, that is
>   Sorry
> me: I think just doing a commit before ResponseRenderer is the way to go.
> In the rare case that there's a render-time exception, you'
> James: Then, the TapernateFilter would only be opening a session.
> 8:09 AM Well, that's the problem. Folks can turn off
> transaction-per-request
> with Tapernate
>   So, I don't necessarily have a tx going on at that point
> 8:10 AM Or, I could require that folks use transaction-per-request. :-)
>   hehe
>   I don't want to do that, though
> me: Your wrapper around ResponseRenderer can be sensitive to whether
> transaction-per-request is enabled.
> 8:11 AM James: I'm trying to work through the scenario when someone has
> turned it off and they're using an interceptor on their service method.
> 8:12 AM Hmmmmm
> 8:13 AM me: If transaction-per-request is off, then you start/commit a
> transaction around each (intercepted) service method.
>   Which is why you want transaction-per-request.
> 8:14 AM James: Ooooh. Side note. Do you think I should have done my Acegi
> stuff using a ListenerInvokerFilter rather that Javassist stuff?
>   And, maybe we could just require annotations for Tapernate and put
> another
> ListenerInvokerFilter in there for that.
> me: I haven't looked at the Acegi stuff, sorry. It sounds similar to what
> I
> did using @Privileged for Vaisala, which I did using Javassist.
> James: But, if I want to have multiple things doing this kind of
> intercepting, I'm going to get an exception
> 8:15 AM Because i use addMethod rather than extendMethodImplementation
>   Know what I mean?
> me: The idea of ListenerInvokerFilter is that you are working with an
> IActionListener which may or may not be a wrapper around a method. In
> olden
> days, it was not.
> James: But, that's where most insert/update/delete stuff should go on,
> correct?
> me: I know what you mean about add vs. extend.
>   It's a problem.
> James: I didn't like coding it that way
> 8:16 AM But, there's no way to get at the annotations. Is that what you're
> saying, via ListenerInvokerFilter?
> me: I have to cop-out with "Tapestry 5".
> James: I guess I could check to see if it's a ListenerMethodBinding rather
> than a SyntheticListener.
> 8:17 AM me: Yes, short of down-casting the IActionFilter and picking that
> object apart, you can't get at the Method.
> James: IActionListener?
>   Not IActionFilter?
> me: Obviously, there's a lot of new use cases out there that didn't exist
> even when I was working on Tapestry 3, never mind today.
> James: hehe
> me: Yes, IActionListener.
> 8:18 AM James: Ok, cool. I thought you lost me there for a minute
>   So, we can agree that listeners are where the "processing" will go on,
> right?
>   Insert/update/delete
> me: yes. Mostly by delegating to services.
> James: Hmmmmm.
> 8:19 AM Well, I require Tap4 anyway. Are those old listeners still
> supported?
>   I would guess so, since the SyntheticListener is in there.
> 8:20 AM me: Yes, if you want to provide an IActionListener inner class via
> ognl: rather than a listener method via listener:, it all still works.
> James: ok, figured
>   If multiple listeners are invoked, would it be nested?
>   Because that wouldn't cause multiple txs
> 8:21 AM It'd just be a nested one.
> me: There's really just the one listener.
> 8:22 AM Tapestry 5 will have a more involved, and easier to hook, event
> system. It'll be a little more "pull" based, where you will annotate
> methods
> to be invoked under certain circumstances, such as when a particular
> component is triggered by the request.
> James: One IActionListener per RequestCycle? So, if I put a transaction
> interceptor on the ListenerInvoker service point with PROPAGATION_REQUIRED
> and one on the ResponseRenderer with PROPAGATION_REQUIRED,readOnly
>   You don't think that'd work?
> 8:23 AM What about for services like Asset and ExternalLink? Do those even
> call the response renderer?
> 8:24 AM me: Nope; components like Hidden and InvokeListener will invoke
> arbitrary listener methods as well. Also Submit.
> James: Not using the ListenerInvoker?
> 8:25 AM me: Services that don't respond with complete pages will not
> invoke
> ResponseRenderer. Caveat Jesse's changes.
> James: Hmmmmm
>   I think we're circling back to leaving it as a WebRequestServicerFilter.
> 8:26 AM But, services that don't render themselves shouldn't all
> necessarily
> be committing data.
>   A listener method might
>   Like a DirectService
> 8:27 AM Do you think we should take this to the dev list to get more folks
> thinking it through?
>   My brain hurts. :-)
>   Of course, we don't have to cover 100% of the cases. Just the most
> common.
> 8:28 AM If folks want to work outside the box, they can customize at will
> 8:31 AM me: yes, most common is the way to go.
>   It's either commit or discard changes. And a commit with no actual
> changes
> will be very cheap.
> 8:32 AM James: For the rendering part, I'm going to use
> PROPAGATION_REQUIRED,readOnly
>   So, whatever Spring does to clean up read-only transactions
>   I don't know if they just roll it back or commit it somehow
> 8:37 AM me: Cool. I probably switch epluribus over when more of this is in
> place.
>   done?
> James: You mean our conversation?
> me: yes
> James: Well, I don't exactly know where to put the read/write tx stuff at
> this point. Have we decided on the best approach?
> 8:38 AM I know we've gone around in circles quite a bit, so I may have
> just
> missed it if we decided
> 8:39 AM me: I still favor hooking ResponseRenderer to commit the active
> transaction before rendering the response.
> James: That should cover the majority
>   But, if the whole thing was wrapped in a read-only tx
>   oh, you're gone
>
>
> --
> Howard M. Lewis Ship
> Independent J2EE / Open-Source Java Consultant
> Creator and PMC Chair, Apache Tapestry
> Creator, Jakarta HiveMind
>
> Professional Tapestry training, mentoring, support
> and project work.  http://howardlewisship.com
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Jakarta HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

RE: Chat with James Carman r.e. Managing Transactions

Posted by James Carman <ja...@carmanconsulting.com>.
How about if we buffer the response data and only write it back out if the
wrapping transaction commits successfully?


-----Original Message-----
From: Howard Lewis Ship [mailto:hlship@gmail.com] 
Sent: Monday, June 12, 2006 11:45 AM
To: Tapestry development
Subject: Chat with James Carman r.e. Managing Transactions

James has been working on HiveMind + Spring libraries to implement the
transaction-per-request model for managing transactions within a Tapestry
application.

---------- Forwarded message ----------
From: James Carman <jw...@gmail.com>
Date: Mon Jun 12 08:39:43 PDT 2006
Subject: Chat with James Carman
To: hlship@gmail.com

7:44 AM James: You there, man?
 me: yes
7:45 AM James: didn't see you on or I would have asked you
  Jesse and I came up with an idea
  Wanna run it by you
  What if I put an interceptor on ListenerInvoker and ResponseRenderer to do
the tx stuff?
 me: ResponseRenderer makes sense.
 James: The one on ListenerInvoker would open up the committing transaction
and the one on ResponseRenderer would open up the one that gets rolled back
  The read-only one
7:46 AM me: ListenerInvoker a little less so ... it gets invoked anytime any
listener method gets invoked, which may be multiple times (especially with
the ajax stuff).
 James: ahhh, where do you suggest I "hook in" then?
7:47 AM me: In ePluribus, I do the commit after invoking annotated service
methods.
  But to avoid that, I would do it at the start of ResponseRenderer.
  You could actually replace ResponseRenderer, and have your impl invoke the
standard impl.
 James: Commit the 'global" transaction and start up a new one that gets
rolled back?
7:48 AM Commit the one that gets started by the TapernateFilter and then
start up a new read-only one?
  The tapernate filter will then take care of cleaning that up.
 me: Yes. Still on the fence about whether the render phase transaction
should be comitted or rolled back.
7:49 AM James: Well, one concern folks have is that the rendering code
doesn't alter any persistent objects
  But, that's a more JSP-oriented concern, I think. Could still be valid in
tap, though
7:50 AM Of course, you can turn off transaction-per-request and put
interceptors on your HiveMind services.
  That would start/commit a tx around it
7:51 AM me: .... so when are is HiveMind moving to
http://hivemind.apache.org?
7:52 AM James: As soon as infra gets done with the requests. I think they
asked me to clarify them a bit.
  I thought I did everything, but nothing has been moving, so I might have
to revisit that.
7:53 AM me: Standard stuff ... few people have the expertise and interest
and time and it's boring infrastructure stuff on top of that.
  Apache can't scale til much more of this stuff is automated, lke a
SourceForge.
 James: Yeah, I couldn't believe that it took weeks for someone to ask me to
give some clarification
7:55 AM So, what do you think is the best course of action for Tapernate? We
could just do a flush() before rendering begins
  And, not commit.
  Flush will check integrity and stuff
7:56 AM That's almost too simple, really
 me: You want to do a full commit, only way to ensure that changes are saved
and any locking conflicts identified.
7:57 AM James: Well, the lock conflicts should get identified during flush,
I would think
7:58 AM How many times does the ResponseRenderer get called during one
request cycle?
7:59 AM me: Just once, unless there's an exception, in which case it may be
called a second time. This is from memory.
 James: Oooh. Yuck.
  Is it nested?
 me: Also, I haven't looked at Jesse's 4.1. changes, which largely seem to
affect response rendering.
 James: I mean is the second call nested within the first call to
ResponseRenderer
8:00 AM me: I'm not sure.
 James: Or, the exception gets thrown from the renderResponse and the
ExceptionPresenter picks it up and tries to render the exception page?
8:01 AM ResponseRendererImpl doesn't have any try/catch logic in the
renderResponse method.
  It's actually surprisingly slim. Thanks to HiveMind! :-)
 me: I think BaseEngine catches any exception and re-invoked
ResponseRenderer after setting up the Exception page.
8:02 AM Yes ... I look at Spring code and it's really monolithic.
 James: Where does ExceptionPresenter enter the picture?
 me: I think it's what gets invoked by the Engine to present the exception.
It in turn invoked ResponseRenderer. Idea is that applications will override
this to change how Exceptions are presented (I often save an XML file with
the data, and jump back to Home).
8:03 AM James: Ahhhh, cool
  Okay, so where would you put the hook to start up the actual processing
transaction? Would you leave it as a WebRequestServicerFilter?
8:04 AM Or, would you hook in somewhere else? And, put a transaction
interceptor (with read-only tx demarcation) on the ResponseRenderer
servicee?
 me: Absolutely.
 James: service
  I could use PROPAGATION_REQUIRES_NEW, but I think that starts a new
Session
  That would suck, cause I want to use the stuff in my current session
  PROPAGATION_REQUIRES_NEW,readOnly
8:05 AM On the response renderer
8:06 AM me: BTW ... I'm going to forward this chat to the tap dev list.
 James: No problem. I'll try not to say anything nasty (hi folks).
  :-)
8:07 AM I would really like to get this right. It would be nice if I can put
an interceptor on another service that would be where "normal" update/insert
processing should occur.
8:08 AM update/insert/delete, that is
  Sorry
 me: I think just doing a commit before ResponseRenderer is the way to go.
In the rare case that there's a render-time exception, you'
 James: Then, the TapernateFilter would only be opening a session.
8:09 AM Well, that's the problem. Folks can turn off transaction-per-request
with Tapernate
  So, I don't necessarily have a tx going on at that point
8:10 AM Or, I could require that folks use transaction-per-request. :-)
  hehe
  I don't want to do that, though
 me: Your wrapper around ResponseRenderer can be sensitive to whether
transaction-per-request is enabled.
8:11 AM James: I'm trying to work through the scenario when someone has
turned it off and they're using an interceptor on their service method.
8:12 AM Hmmmmm
8:13 AM me: If transaction-per-request is off, then you start/commit a
transaction around each (intercepted) service method.
  Which is why you want transaction-per-request.
8:14 AM James: Ooooh. Side note. Do you think I should have done my Acegi
stuff using a ListenerInvokerFilter rather that Javassist stuff?
  And, maybe we could just require annotations for Tapernate and put another
ListenerInvokerFilter in there for that.
 me: I haven't looked at the Acegi stuff, sorry. It sounds similar to what I
did using @Privileged for Vaisala, which I did using Javassist.
 James: But, if I want to have multiple things doing this kind of
intercepting, I'm going to get an exception
8:15 AM Because i use addMethod rather than extendMethodImplementation
  Know what I mean?
 me: The idea of ListenerInvokerFilter is that you are working with an
IActionListener which may or may not be a wrapper around a method. In olden
days, it was not.
 James: But, that's where most insert/update/delete stuff should go on,
correct?
 me: I know what you mean about add vs. extend.
  It's a problem.
 James: I didn't like coding it that way
8:16 AM But, there's no way to get at the annotations. Is that what you're
saying, via ListenerInvokerFilter?
 me: I have to cop-out with "Tapestry 5".
 James: I guess I could check to see if it's a ListenerMethodBinding rather
than a SyntheticListener.
8:17 AM me: Yes, short of down-casting the IActionFilter and picking that
object apart, you can't get at the Method.
 James: IActionListener?
  Not IActionFilter?
 me: Obviously, there's a lot of new use cases out there that didn't exist
even when I was working on Tapestry 3, never mind today.
 James: hehe
 me: Yes, IActionListener.
8:18 AM James: Ok, cool. I thought you lost me there for a minute
  So, we can agree that listeners are where the "processing" will go on,
right?
  Insert/update/delete
 me: yes. Mostly by delegating to services.
 James: Hmmmmm.
8:19 AM Well, I require Tap4 anyway. Are those old listeners still
supported?
  I would guess so, since the SyntheticListener is in there.
8:20 AM me: Yes, if you want to provide an IActionListener inner class via
ognl: rather than a listener method via listener:, it all still works.
 James: ok, figured
  If multiple listeners are invoked, would it be nested?
  Because that wouldn't cause multiple txs
8:21 AM It'd just be a nested one.
 me: There's really just the one listener.
8:22 AM Tapestry 5 will have a more involved, and easier to hook, event
system. It'll be a little more "pull" based, where you will annotate methods
to be invoked under certain circumstances, such as when a particular
component is triggered by the request.
 James: One IActionListener per RequestCycle? So, if I put a transaction
interceptor on the ListenerInvoker service point with PROPAGATION_REQUIRED
and one on the ResponseRenderer with PROPAGATION_REQUIRED,readOnly
  You don't think that'd work?
8:23 AM What about for services like Asset and ExternalLink? Do those even
call the response renderer?
8:24 AM me: Nope; components like Hidden and InvokeListener will invoke
arbitrary listener methods as well. Also Submit.
 James: Not using the ListenerInvoker?
8:25 AM me: Services that don't respond with complete pages will not invoke
ResponseRenderer. Caveat Jesse's changes.
 James: Hmmmmm
  I think we're circling back to leaving it as a WebRequestServicerFilter.
8:26 AM But, services that don't render themselves shouldn't all necessarily
be committing data.
  A listener method might
  Like a DirectService
8:27 AM Do you think we should take this to the dev list to get more folks
thinking it through?
  My brain hurts. :-)
  Of course, we don't have to cover 100% of the cases. Just the most common.
8:28 AM If folks want to work outside the box, they can customize at will
8:31 AM me: yes, most common is the way to go.
  It's either commit or discard changes. And a commit with no actual changes
will be very cheap.
8:32 AM James: For the rendering part, I'm going to use
PROPAGATION_REQUIRED,readOnly
  So, whatever Spring does to clean up read-only transactions
  I don't know if they just roll it back or commit it somehow
8:37 AM me: Cool. I probably switch epluribus over when more of this is in
place.
  done?
 James: You mean our conversation?
 me: yes
 James: Well, I don't exactly know where to put the read/write tx stuff at
this point. Have we decided on the best approach?
8:38 AM I know we've gone around in circles quite a bit, so I may have just
missed it if we decided
8:39 AM me: I still favor hooking ResponseRenderer to commit the active
transaction before rendering the response.
 James: That should cover the majority
  But, if the whole thing was wrapped in a read-only tx
  oh, you're gone


-- 
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Jakarta HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com



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