Dear Craig (and developers),

        Thank you very much for addressing our concerns.
        We think it is important to point out that our forwarding from
action to action (action->action) is not in order to share logic between
actions, but rather in order to do a form of pre- and post-processing. To
help better illustrate this, we have created an example of action->action
forwarding that properly -- and in a loosely-coupled manner -- illustrates
the problem:

        Say we have a jsp page that allows the user to input data neccessary
to calculate a mortgage premium.  This page fits into the pageflow of a
web-based system.  There are many ways to get to this page, and many pages
to go from this page.  But after this page is submitted, no matter where it
is coming from or going to, the mortgage premium must be calculcated from
the form data.
        Because this is a mortgage calculation web application, and the
mortgage premium is both needed on many of the web application pages and as
a general output of the system, we store the mortgage premium in the form.
This complies with Struts recommendation of form usage within a web
application, as is defined in the Struts User Guide.   It is possible to use
the HTTPSession to store these shared values, however we already have a form
bean which contains the data, and we use the populated form bean as the
output of the system.  The form bean is used to contain  only mortgage
information -- we may have other form beans that contain other types of
information, but they are not in the scope of this example.
        Say we have another jsp page in the same web application that
calculates the number of years to pay off a mortgage.  There are many paths
to get to this page, and possibly many places to go from this page.
However, before this page is displayed, no matter where it comes from, the
number of years to pay off the mortgage is calculated and stored in the form
bean for retrieval by other parts of the system (actions?).  We do this
calculation within an action.  Anybody who wishes to forward to this page
forwards to its '.do' in the struts-config.xml file.  For most pages this
goes directly to the jsp, but for some special pages (including this one) it
forwards to an action that does pre-processing for the page.
        Here's a diagram depicting the parts of the example we are
discussing:

Here's the mortgage premium page within the system:

                -> Premium.jsp -> PremiumAction -> 

Here's the years-to-pay-off-mortgage page within the system:

                -> CalcYearsAction -> Years.jsp ->

        Notice that these actions are not coupled in any way.  Neither of
them need to know where they coming from or where they are going to.  The
logic which handles this is in the struts-config.xml file, not with the
action java code.
        To continue with our example; most times when we go to the Years.jsp
page, the mortgage premium is already in the form, and so the
(pre-processing) CalcYearAction for the page merrily calculates its values.
However, when the mortgage premium is calculated and set within the
(post-processing) PremiumAction, AND the struts-config.xml specifies that
the user goes from Premium.jsp to Years.jsp, we run into a problem.  The
problem occurs because PremiumAction sets "mortgagePremium" in the form, and
control is forwarded to CalcYearsAction.  mortgagePremium was displayed
within Premium.jsp's HTTP form because the system displays the OLD
mortgagePremium value.  Thus, when we submit from Premium.jsp to
PremiumAction, a value for mortgagePremium is passed in the HTTPRequest.  So
now, it doesn't matter that we have set mortgagePremium in PremiumAction,
because when the request reaches CalcYearsAction, the value is reset by
Struts.
        We do not believe that forwarding from action to action is root of
the problem here.  Our example illustrates how you can have a completely
loosely-coupled system that forwards from action to action and still run
into this problem.  We also do not believe that we are not using
action->action forwarding improperly.  In fact, we might go so far as to say
that suggested solutions that suggest that action->action forwarding is the
problem do not address the problem at all.
        Our only hope is that we can illustrate the issue clearly enough
that it can be properly addressed. Once it is addressed, a solution can be
devised. We don't presume to know enough about the code to suggest any
solutions, but we do know that we seem to have arrived at this problem
through proper usage of Struts. If we can help in any way -- if you would
like more sample code or whatever -- please let us know.
        And thank you for your replies.

Sincerely,

        Daryl and Terry.



-----Original Message-----
From: Craig R. McClanahan [mailto:[EMAIL PROTECTED]]
Sent: Wednesday, April 24, 2002 11:49 AM
To: Struts Developers List
Subject: Re: ActionServlet re-populates form upon Actoin => Action call




On Wed, 24 Apr 2002, Nicolas De Loof wrote:

> Date: Wed, 24 Apr 2002 17:29:25 +0200
> From: Nicolas De Loof <[EMAIL PROTECTED]>
> Reply-To: Struts Developers List <[EMAIL PROTECTED]>
> To: Struts Developers List <[EMAIL PROTECTED]>
> Subject: Re: ActionServlet re-populates form upon Actoin => Action call
>
> I agree with Terrence about the poor way you can couple Actions.
>
> It would be interesting to chain two Actions, basing chaining on the
> "ActionForward" the first one returns, and assuming that request the
> FormBean is populated only once.
>
> I understand it is a different behaviour of current "forward" mecanism
that
> allow to forward to any URL.
>
> I would like to be able to define a forward that would be typed to
"chain",
> so that the associated action would be called without request parsing. So
we
> could reuse elementary actions working on request or session datas, and
> declare request-handling actions for application URLs, using a declarative
> way to define actions chaining.
>
> Perhaps it is what the workflow extension is assuming ?
>

In my own world view, actions are designed to be called by HTTP requests,
not by other actions.

Adding some sort of action chaining mechanism would address this concern.
However, IMHO, a better design is to refactor the logic you are trying to
share into separate classes that can be directly invoked from the first
action (after doing its own thing) and from the second action.

Imagine S is a chunk of shared logic that is the reason you want to chain
in the first place.

Instead of:

    A1 --> A2 (contains S)

think about:

    A1 (do its own processing, then call S)
    A2 (calls S)

If you need the logical-physical mapping support for calling S without
knowing its class name, that can be created fairly easily as well.

Servlet chaining was the worst thing that ever happened to servlets (in
the pre-Servlet-2.0 days).  I'm glad it never got supported in the real
servlet API, and am not real anxious to see us implement it in Struts.

Craig


>
> ----- Original Message -----
> From: "Terrence Xavier" <[EMAIL PROTECTED]>
> To: "'Struts Developers List'" <[EMAIL PROTECTED]>
> Sent: Wednesday, April 24, 2002 4:16 PM
> Subject: RE: ActionServlet re-populates form upon Actoin => Action call
>
>
> > Dear Martin,
> >
> > Thanks for your reply. Although you raise some good points, we still
> > have some trouble understanding the logic behind Struts' behaviour.
> > The Struts documentation encourages the use of the Form Bean across
> > actions, thus coupling -- whether tightly or loosely -- the actions
> > together. Or, you could look at it the other way around and say that the
> > Form Bean "provides a coupling mechanism".
> > Although we agree that it is the natural behaviour of Struts to
> > populate the form bean from the request parameters, we still have
trouble
> > understanding why it is natural that this would be done with EVERY
> > forwarded-to action (beyond the fact that the code currently does this).
> In
> > fact, it seems very unnatural that it would be done over and over --
> > especially when one may wish to populate the form bean AFTER Struts
> > populates it from the request parameters.
> > I don't think that having one Action set a Form Bean attribute and
> > having another Action read that attribute is considered "tightly
> coupling".
> > Is it unusual to use the Form Bean as a method of defining something
that
> > contains properties for all of the fields that will be used across pages
> > (and thus across requests AND Actions) like in a Wizard interface?
> > Although it may seem like our example code was tightly coupled, it
> > really doesn't matter what happens with the forwards in between actions.
> You
> > are right in assuming that we could be forwarding to another servlet
> before
> > forwarding back to another action. However, if we did this, we still
would
> > not want the form bean re-populated from the request when entering any
> > subsequent action.
> > When forwarding to a JSP, however, this is a completely different
> > matter. Because returning from a JSP will yield an entirely new request;
> and
> > thus the whole problem disappears.
> > Take this scenario as a loosely-coupled example of another place
> > where this problem could arise:
> > The user forwards to an action from a JSP. The Action populates the
> > form bean. The Action forwards to a servlet, which does its own thing.
> Then
> > that servlet forwards to another servlet, which does yet another thing.
> Then
> > a third non-Action servlet is forwarded to, which actually removes the
> Form
> > Bean from the session (for some unknown reason). When that servlet
> forwards
> > to another Action, the Action will re-create the removed Form Bean and
> > re-populate it from the request.
> > This is very loosely-coupled. In fact, the two actions don't care
> > about one another at all. The problem is that a very unnatural thing
> > happens; the Form Bean is recreated AND repopulated! Both of these
> > behaviours are contrary to what the code is trying to do.
> > It is true that actions do not know where they are going to or where
> > they are coming from; they don't need to. But Struts should know if it
has
> > processed the request parameters or not, so that it does not do the same
> > work over and over, and so that it does not override the Form Bean
> > attributes set by servlets/Actions.
> > Perhaps Struts should have a dirty marker that is placed in the
> > request after Struts processes the request parameters, so that it does
not
> > re-process them? It could set a request Attribute and the ActionServlet
> > could read this boolean value to see if the Form Bean has been populated
> > from the request parameters yet or not. Because some people already have
> > applications which rely on the current behaviour, it might also be a
good
> > idea to have this dirty marker be activated/disactivated from the Struts
> > config file?
> > Perhaps we are doing things completely incorrectly, but if we are,
> > then what is the right way? Your suggestion of having our Actions
agreeing
> > on retrieving the Form Bean from some other location would actually make
> our
> > Actions very tightly coupled, whereas right now they are not. This also
> > bypasses Struts completely. What we are doing in the mean time is
sending
> > our own values in the HTTPRequest from the JSP without using Struts form
> > elements, and setting the attributes of the Form Bean ourselves in the
> > Action class -- thus bypassing Struts which would do it upon EVERY
> > Action.perform() call. This bypasses Struts too, and we would like to
> > actually use the Struts form elements in our JSPs; but if we do... we
run
> > into the problem of Struts re-setting our Form Bean attributes on every
> > Action.perform() call. Is there anything we can do?
> >
> > Sincerely,
> >
> > Daryl and Terry.
> >
> >
> > -----Original Message-----
> > From: Martin Cooper [mailto:[EMAIL PROTECTED]]
> > Sent: Sunday, April 21, 2002 1:45 AM
> > To: Struts Developers List
> > Subject: Re: ActionServlet re-populates form upon Actoin => Action call
> >
> >
> > What you are seeing is a natural consequence of the Servlet spec, and in
> > particular the behaviour of the RequestDispatcher. Here are some points
to
> > consider:
> >
> > * When you forward a request, all of the request parameters are
preserved
> > and presented to whatever processes the forwarded request. Therefore, it
> is
> > natural that those original values be used to populate any form bean
> > associated with a forwarded-to action, should the target of the forward
> > happen to be a Struts action.
> >
> > * A forward need not target a Struts action. It may go to a JSP page,
> > another servlet in the web app, or something else. You may happen to
know
> > that, for your application, the target is another Struts action, but
> Struts
> > cannot assume that.
> >
> > * A forwarded-to action does not know that it was forwarded to from
> another
> > action. It could have been forwarded to from a JSP page, a non-Struts
> > servlet, or something else. Therefore, Struts cannot assume that the
form
> > bean has already been populated by some prior action.
> >
> > It seems that you have some very specific assumptions built into your
app.
> > In particular, your actions are very tightly coupled. For example, your
> > actions "know" that they are forwarding to another action, and further,
> they
> > "know" the type and instance of the form bean that the other action will
> > use. This type of coupling is one of the things that Struts really tries
> > hard to avoid.
> >
> > If you really need this kind of tight coupling between your actions,
then
> > you can have your actions "agree" on some other location from which they
> can
> > obtain their form bean, rather than using the one that Struts will pass
to
> > your execute() method.
> >
> > --
> > Martin Cooper
> >
> >
> > ----- Original Message -----
> > From: "Terrence Xavier" <[EMAIL PROTECTED]>
> > To: <[EMAIL PROTECTED]>
> > Sent: Thursday, April 18, 2002 11:21 AM
> > Subject: ActionServlet re-populates form upon Actoin => Action call
> >
> >
> > > Dear Struts Developers,
> > >
> > > We have noticed some unexpected behavior with Struts. Basically, if
> > > the HTTPRequest specifies attributes to modify in a struts form, they
> get
> > > modified on EVERY call to the ActionServlet. An example of this is as
> > > follows. Say that we have a JSP that sets a form attribute, and then
we
> > > submit to an Action class. From that Action, we modify the same form
> > > attributes, and then forward to another Action. The problem we are
> seeing
> > is
> > > that the form attributes get re-set upon entry into the second Action,
> > thus
> > > overwriting our changed values in the form from the first Action.
> > > The normal expected behaviour is that we can change the form
> > > attributes in an Action, and then forward to another action and read
> those
> > > changed values. However, due to how the ActionServlet processes
> > > HTTPRequests, those values will be replaced with the values specified
in
> > the
> > > HTTPRequest. Since the parameters in the HTTPRequest are read-only, we
> > > cannot override this functionality.
> > > We have done extensive testing of this "bug" over the past few days.
> > > We have written a simple project to demonstrate the issue, and have
> tested
> > > it with Struts 0.5, 1.0.2, and 1.1b1. Each of those versions of Struts
> > > functions the same with regard to this issue.
> > >
> > > Here is what is happening in more detail:
> > >
> > > The ActionServlet processes the HTTPRequest and populates the form
> > > bean from the parameters in the HTTPRequest. This occurs before
> > > instantiating the Action class to "perform". Thus, if we forward from
> > Action
> > > to Action, when the same request is passed by the servlet engine, the
> form
> > > bean gets populated twice -- before and after the first Action. So
form
> > bean
> > > values set within the Action that are also present in the HTTPRequest
> get
> > > overridden with the values from the HTTPRequest.
> > > Our simple project (attached to this e-mail) demonstrates this.
> > > Here's the flow of that project:
> > >
> > >
> > >   JSP        =>    Action1      =>     Action2   =>   etc...
> > >    |         |        |         |         |
> > >    V         V        V         V         V
> > > set(x)=2   (x=2)   set(x)=4   (x=2)    get(x)=2
> > >
> > >
> > > In our project, whenever we enter and leave an action, we print out
> > > a string indicating that we are entering or leaving the action. We
also
> > have
> > > print statements inside every getter and setter in the form bean that
> will
> > > tell us whenever anything is retrieved or set in the form. This is the
> > > output we get from our application (with extra a couple comments to
help
> > > explain what is going on):
> > >
> > > *********** startActionOne **************START
> > > formAction : setFormAction() originalValue
> > > *********** startActionOne **************END
> > > +++++++++++ One.jsp +++++++++
> > > formAction : setFormAction() changedbyOneJSP        <-- Struts sets
the
> > form
> > > bean attribute from JSP.
> > > *********** ActionOne **************START
> > > formAction : getFormAction() changedbyOneJSP
> > > formAction : setFormAction() changedbyActionOne
> > > *********** ActionOne **************END
> > > formAction : setFormAction() changedbyOneJSP        <-- Unexpected
> > behavior
> > > occurs here
> > > *********** StartActionTwo **************START
> > > formAction : setFormAction() changedbystartActionTwo
> > > *********** StartActionTwo **************END
> > > +++++++++++ Two.jsp +++++++++ getFormAction() = changedbyOneJSP
> > >
> > >
> > > It is easy to see why this behaviour would be unexpected. After
> > > explicitly setting the "formAction" attribute of the form in
ActionOne,
> it
> > > is re-set by Struts before ActionTwo is "performed".
> > >
> > > Given that this is how Struts functions, our questions are these:
> > >
> > > 1) We have work-arounds by using session request attributes, but we
> > > would like to set form values in actions. How do we do this within the
> > > Struts framework and have them retain their values?
> > >
> > > 2) Since Struts seems to process the request twice, setting the form
> > > attributes over and over again for each action that is forwarded to,
> does
> > it
> > > make sense to change Struts so that it does not do the same work on
the
> > same
> > > HTTPRequest object more than once?
> > >
> > > 3) Is this well-known issue?
> > >
> > > We would appreciate any input you can offer.
> > >
> > > Sincerely,
> > >
> > > Daryl Beattie and Terrence Xavier
> > >
> > > P.S. The example code is configured to work with Struts 1.1b1 right
now.
> > We
> > > used the same project to test the other versions, but have since
changed
> > it
> > > to use 1.1b1. We did not include the jars in our zip file, so if you
> want
> > to
> > > try it you will have to copy the Struts jars (and its dependent jars)
in
> > the
> > > WEB-INF/lib folder.
> > >
> > >
> > >
> > >
> >
> >
> >
--------------------------------------------------------------------------
> --
> > ----
> >
> >
> > > --
> > > To unsubscribe, e-mail:
> > <mailto:[EMAIL PROTECTED]>
> > > For additional commands, e-mail:
> > <mailto:[EMAIL PROTECTED]>
> >
> >
> > --
> > To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
> >
> > --
> > To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> > For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
>
>
> --
> To unsubscribe, e-mail:
<mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail:
<mailto:[EMAIL PROTECTED]>
>
>


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to