RE: [Webwork-devel] Sessionable Actions
Brought to you by:
baldree,
rickardoberg
|
From: Jason C. <jas...@no...> - 2001-11-29 14:11:36
|
> -----Original Message-----
> From: Rickard Öberg [mailto:ri...@xp...]
>
> The problem is that the action is instantiated on the client with CSD.
> So, you have no way of intercepting it.
>
> This might change in the future so that one may really call
> ActionFactory.getAction() even on the client, which would go to the
> server and get it (in order to perform prepare() properly). But then
> you'd send a lot of state back and forth three times for each action
> that is invoked.
This is not something you'd use with CSD. Lets take an example that's a form
that's got 200 fields. With CSD, you could instantiate the Action on the
client side, then show the form to the user 50 fields at a time, and put the
data into the Action as they finish each page, with maybe some page-by-page
data validation.
In this case you've got one Action, multiple pages. You keep using the
Action across all of those pages, until you're ready to submit the data,
then you send the Action over the wire to the server.
On the web side, things aren't nearly so nice. Multiple pages means multiple
page submits, multiple actions being created, and having to find a way to
keep the previous data ready for them to go back to. Maybe you can create a
framework to make this easier, but my question is, why? If you just kept
using the same Action, like you would in the case of CSD, wouldn't things
just be an order of magnitude easier? The data's there because the Action is
the same action as last time, and when you're ready to go back, it's still
there. No new objects, no copying data field by field, it's just there.
Think about how much easier this could make things like remembering the last
tab selected in a tabbed pane was, 5 minutes and 4 pages ago, or which
column to sort a table by. Yes, this could all be manually saved to the
session and pulled back out, but it's so much easier to just automate it and
reuse the same Action.
>
> I want the actions to be as shortlived and stateless *as possible*.
>
> Are there any problems with having the action save the state in a
> session? Remember that it *can* (if it so chooses) store itself into a
> session, and then get it and use BeanUtil.copy to perform pretty much
> the same thing. The difference is that the framework doesn't have to
> know about it, or be changed to accomodate it.
The problem is that I have to do it, and re-do it, etc. It's a lot of code
to have to develop and maintain if it's done in the application layer,
instead of the webwork framework layer.
> I would perform this by having a generic action that can be used for
> these kinds of things instead. I.e. in your action that wants to save
> itself it would do:
> StateAction state =
> (StateAction)ActionFactory.getAction(StateAction.class);
> state.load(this, changeCount); // Copy stored action into this action
> .. do things..
> state.store(this); // Store action back into session, and have it
> increase changeCount
>
> Then only StateAction would have to be SessionAware. The changeCount is
> incremented for each run, so that if double submitting is done the
> changeCount in load() is less then what is in the state store (=session)
> then the load fails, since another action has already "used" up the
> state of that changeCount(/timestamp).
This seems like a lot of extra work compared to what I had to do to get this
working with the ActionFactoryProxy framework.
>
>
> Hm.. this might be idealistic since there's often a difference between
> non-wizard and wizard mode in terms of process state changes and
> awareness. The above should work better, and also be possible to put in
> a base class, e.g.:
>
> protected String doExecute()
> {
> StateAction state =
> (StateAction)ActionFactory.getAction(StateAction.class);
> state.load(this, changeCount);
> doWizard();
> state.store(this);
> }
>
> Something like that. Now all you have to do is implement doWizard(),
> which in turn may delegate to methods for each wizard step.
>
> This approach needs to be tested, but IMHO it will solve the same
> problem in a better way since it will not make actions themselves
> long-lived (which I really really want to avoid. Gut feeling tells me
> its the right thing to do).
How about if I send you the stuff I built and you can take a look? We need
an example of multi-page forms anyway, so maybe this is a good time to work
through this. I took the form test action, extended it, made the subclass
implement Sessionable, and added a command operation (doPage2), and overrode
doValidation() to null out the errors before calling super.doValidation
because otherwise the error messages carry over, and that was all it took to
make that form action be saved in the session and support multiple pages
(except of course copying the JSP and creating 2 pages from it, and adding
some view mappings).
>
>
> > This only works with the synchronization I mentioned.
> Otherwise, you could
> > have the setters being called during the execution of the Action from a
> > previous request, since it's multithreaded.
>
> Hm.. what if the prepare() method did the check? Then it could barf at
> that point.
>
> Also, if the action itself is not longlived, who cares if the setters
> are called? Big deal. It's thrown away anyway. :-)
I think even if you start setting "in use" flags, you have synchronization
issues unless you synchronize all of the accessors and doXXX methods. If
it's a big deal that it not be submitted twice, then you have to
synchronize. At least if you are using the same Action and saving it in the
session, it gives you something to synchronize on.
Jason
|