You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by "Felciano, Ramon" <fe...@ingenuity.com> on 2001/01/10 23:40:28 UTC

Any way to dynamically change flow-of-control?

Hi --

I'm evaluating Struts (+Turbine+Rocks) as a framework for our web apps 

We often want to insert certain UI actions based on exceptional user
behavior. A simple example is an authentication  screen that gets inserted
"just in time". For example, if the normal flow of control is from page A
--> page B, where page B requires authentication, then 98% of the time, the
user goes A --> B. However, the very first time this happens we want to
insert an authentication page: A --> Logon --> B. Other situations where
this type of intermittent insertion of additional UI and flow logic would be
helpful include:

- Confirm pages ("Are you sure that xxxx?" with "Continue" and "Cancel"
buttons)
- Pick lists ("We couldn't find the product ID you entered; please select
from the following list")
- Alert pages for (possibly unexpected) server-side events that occured
since the last client-server traffic passed through.

I realize that these can all be implemented on a case-by-case basis, with
each Action class deciding whether to insert a new flow element or not. A's
Action class could check the authentication state and decide whether to go
to Login or B accordingly. In the pick list example, this could be done by
returning the user to the original form and using JSP logic to notice the
error and display a list of options to choose from. However, if the page is
a complex one, displaying a specialized form for just this input value can
be useful.

I guess I'm wondering whether there is any generalized support for this that
might better separate the nature of these exception events? For example, in
the login example, it doesn't make sense to me that A's Action class make
the decision as to whether to show the login form, since the authentication
is bound to B. In particular, I'd like to be able to reroute to Logon when
needed, but otherwise continue with the "normal" flow of logic. Thus, if at
a later date the "normal" flow of logic dictates A --> C, I only want to
change this in one place (A's success forward property), and still benefit
from the just-in-time authentication. Same thing for confirm pages, etc...

Finally, and on a different topic, can someone please point me to the most
recent discussion (or docs) regarding how to do Form validation with struts?
The [outdated?] user guide first suggests not doing it in the ActionForm
class, then provides a ValidatingActionForm that seems to encourage the
practice...

Thanks in advance for your time.

Ramon

_________________________________

Ramon M. Felciano
INGENUITY Systems, Inc.



Re: Any way to dynamically change flow-of-control?

Posted by Ted Husted <ne...@husted.com>.
"Felciano, Ramon" wrote:
> - Confirm pages ("Are you sure that xxxx?" with "Continue" and
"Cancel"
> buttons)
> - Pick lists ("We couldn't find the product ID you entered; please
select
> from the following list")
> - Alert pages for (possibly unexpected) server-side events that
occured
> since the last client-server traffic passed through.

Just a wild idea here: 

An action is not required to forward to a path or action, but has
everything it needs to answer the request itself (and return a null
action forwarding).

So how about if the action wrote pages like this dynamically, the
old-fashioned servlet way, perhaps using a standard "message box" type
library? 

The responses in the dynamic page could then be set to forward to
whatever actions or paths were appropriate to the circumstances,
without having to write a physical JSP for every conceivable
combination.


-- Ted Husted, Husted dot Com, Fairport NY USA.
-- Custom Software ~ Technical Services.
-- Tel 716 425-0252; Fax 716 223-2506.
-- http://www.husted.com/



Re: Any way to dynamically change flow-of-control?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Hi Ramon,

See interspersed comments below.

"Felciano, Ramon" wrote:

> Hi --
>
> I'm evaluating Struts (+Turbine+Rocks) as a framework for our web apps
>
> We often want to insert certain UI actions based on exceptional user
> behavior. A simple example is an authentication  screen that gets inserted
> "just in time". For example, if the normal flow of control is from page A
> --> page B, where page B requires authentication, then 98% of the time, the
> user goes A --> B. However, the very first time this happens we want to
> insert an authentication page: A --> Logon --> B. Other situations where
> this type of intermittent insertion of additional UI and flow logic would be
> helpful include:
>
> - Confirm pages ("Are you sure that xxxx?" with "Continue" and "Cancel"
> buttons)
> - Pick lists ("We couldn't find the product ID you entered; please select
> from the following list")
> - Alert pages for (possibly unexpected) server-side events that occured
> since the last client-server traffic passed through.
>

That is an interesting approach.

>
> I realize that these can all be implemented on a case-by-case basis, with
> each Action class deciding whether to insert a new flow element or not. A's
> Action class could check the authentication state and decide whether to go
> to Login or B accordingly. In the pick list example, this could be done by
> returning the user to the original form and using JSP logic to notice the
> error and display a list of options to choose from. However, if the page is
> a complex one, displaying a specialized form for just this input value can
> be useful.
>
> I guess I'm wondering whether there is any generalized support for this that
> might better separate the nature of these exception events? For example, in
> the login example, it doesn't make sense to me that A's Action class make
> the decision as to whether to show the login form, since the authentication
> is bound to B. In particular, I'd like to be able to reroute to Logon when
> needed, but otherwise continue with the "normal" flow of logic. Thus, if at
> a later date the "normal" flow of logic dictates A --> C, I only want to
> change this in one place (A's success forward property), and still benefit
> from the just-in-time authentication. Same thing for confirm pages, etc...
>

Within Struts 1.0, an approach to handling these things generically would be to
subclass the ActionServlet controller servlet, and override a method like
processActionPerform (which actually calls the selected Action) or
processActionForward (which forwards control to the returned logical page
name).  You could then inspect the current state of the world, and inject
flow-of-control changes like this while still utilizing the superclass's basic
functionality.

To make the types of things you inject somewhat configurable, you might also
want to use your own custom ActionMapping subclass, with extra bean properties
that describe (to your override method) what exceptional things to do and when
to do them -- the selected ActionMapping instance is made available to most of
the processing calls, so this information would be easily accessible.

In future versions, one of the directions I really want to look is a more
"workflow" like organization of processing within Struts (both for the basic
processing that the controller servlet does for you, and for letting you glue
together finer grained tasks, in addition to (or instead of) the relatively
coarse grained Actions that are currently supported.  Doing the sorts of dynamic
flow-of-control changes you are talking about would seem to fit into that model
pretty well, especially if you could "script" them in the struts-config file.

>
> Finally, and on a different topic, can someone please point me to the most
> recent discussion (or docs) regarding how to do Form validation with struts?
> The [outdated?] user guide first suggests not doing it in the ActionForm
> class, then provides a ValidatingActionForm that seems to encourage the
> practice...
>

The user guide is under active development to bring it up to the 1.0 APIs -- I
would expect the version you get with tonight's nightly build to be pretty up to
date.

On the particular issue of validation, the ActionForm class (you don't need
ValidatingActionForm any more) has a method:

    public ActionErrors validate(ActionMapping mapping,
                HttpServletRequest request)

that is used for form beans that want to validate.  You return null if no errors
are encountered, or an ActionErrors object that is a collection of error message
keys (along with the field names the errors are assocaited with).

>
> Thanks in advance for your time.
>
> Ramon
>

Craig McClanahan



Re: Any way to dynamically change flow-of-control?

Posted by Elod Horvath <el...@itfais.com>.
see interspersed comments below...


"Laird J. Nelson" wrote:
> 
> ----- Original Message -----
> 
> I like to think of this as the "dialog box problem" that web UIs face.
> That is, each case above, in a "traditional" client-server program,
> would be implemented, usually, as a dialog box.  What's unique about a
> dialog box?  It pops up and gets in the way of where you (a) are or (b)
> were trying to go.  Only when you dismiss it are you "returned" to
> either (a) or (b).  On the web, of course, with our primitive HTML-based
> UIs, there are no such things as dialog boxes (unless you use
> javascript).  So "screen flow" becomes all important.
> 
> I bring this up because struts seems to have gone partway--better than
> any other framework I've seen--but not all the way in its support of
> this dialog box metaphor (it uses form beans).  What is now needed is a
> navigation stack of some kind--perhaps even something that is
> written/phrased in terms of "traditional" UI metaphors.  I'm thinking
> about some kind of stack--and believe me, I haven't thought this all the
> way through yet--that can be accessed by Actions, but any given Action
> would typically say something like "OK, go to the next screen that I'm
> being told to go to, or if I'm not being told to go anywhere, go to this
> default location".  Or the Action might be able to say "oops, conditions
> aren't right to advance; pop the stack and go back to where we were a
> moment ago but display the following message".  Things on the stack
> would be *roughly* equivalent to screens--though I hesitate to use
> "screen" as I think that's one of the major shortcomings of the Turbine
> framework, because a "screen" on the web often exists as a separate
> entity only because the marketing department said it has to.

Actually, I've implemented just such a construct at work for the struts
based prototype of a significant financial web-application shell. There 
 
was some discussion on this list some time ago about something called a 
StateManager, which is essentially what this is.  And yes, the concept
of 
"screen" is fuzzy -- in my situation, a "screen" is really a [at times] 
complicated and changing frameset.  

The app/shell's flow follows a (process/state update/redraw) pattern 
in a [con]federation of sub-applications (and thus, controllers).  
See my attached diagram with numbered steps as follows:

1)  Application Request
    Client-side user triggers a request to the server.

2)  Sub-application Controller Dispatch
    Dispatches the request to the appropriate action handler.

3)  Action Request Processing
    The actions process the request, invokes relevant business logic,
    sets up data and state beans.

4)  Redirect Response
    Initial request response is _always_ a redirect to a single URL
    to redraw the application window.

5)  Window Redraw Request
    There is one global window redraw request handled by the main
    controller servlet.  This request "repaints" the entire browser
    window based on the current state of the application.

6)  Main Controller Dispatch
    Dispatches the request to the appropriate action handler.

7)  Action Request Processing
    This sets up the request object and determines the correct views to
    "forwards" to based on what's on top of the page stack.

8)  Request Forwarded (dispatched) to Views
   
9)  JSP Views Render Response

10) Final Result Response
    Response to the redraw request.

(apologies for the detail level in these steps -- I lifted this diagram
 and description from the system overview documentation I'm working on
 at work (geared towards newbie developers in my group))

one side benefit of this indirected approach is that the application
has _total_ control over what the user sees...because all requests 
_always_ result in a redirect to the same _global_ repaint action,
the browser's navigation buttons are effectively disabled; the user always
gets presented what is currently at the top of the pagestack -- be it
error page, form, interjected "dialog" window, etc.  The framework
effectively hides the implementing JSP views from the browser's URL
location making it more difficult for the user to bookmark intermediate 
pages or the browser to track page history (something which is usually 
not desirable, especially with sensitive apps/sites).

I hope this was helpful...

e

-- 
_______________________________________________________________________
Elod Horvath ('e')       /      ITFAIS Records (http://www.itfais.com/)

Re: Any way to dynamically change flow-of-control?

Posted by "Laird J. Nelson" <lj...@unix.amherst.edu>.
----- Original Message -----
From: "Ted Husted" <ne...@husted.com>
> On 1/10/2001 at 11:27 PM Laird J. Nelson wrote:
> > What is now needed is a navigation stack of some kind--perhaps even
> something that is written/phrased in terms of "traditional" UI
> metaphors.
> The other place this idea comes up is the problem with users
> bookmarking pages that require a form-based login.

Although in a J2EE context, that problem is solved for you by the
servlet container (something the vast majority of websites I've seen
don't seem to be aware of--i.e. that a lot of authentication-related
behavior is provided to you for free).

> One solution, that I admittedly have not tried, might be to set an
> attribute in the session context that your Actions would monitor, if
> they might need to return to some arbitrary place in your application.

What I'd love to have happen (warning; more thinking out loud) is to
make it so that Actions don't have to have *any* if/then logic in them
at all for these kinds of cases (if possible).  Every time you have to
say to one of your developers, "Please remember to put in the
check-for-the-logged-in-user's-name check at the top of each
page/servlet", you run the risk of having one of them forget to do this.
Or, to put it another way, this navigation stuff should probably go in
the controller servlet somehow.

> >Now think that somewhere in that flow a *logical* dialog box is
> supposed to present itself .. If the answer is Yes, then the next
> "screen" should be, well, the next screen.  If the answer is no, then
> the next "screen" should be the very same page that triggered this
> "dialog box" to appear, since after all when you dismiss a dialog box
> it goes away, leaving you right where you were before.
>
> I think here the "logical dialog box" would be the action, and the yes
> and no answers are mappings for that action from the
struts-config.xml.
> So your config might actually say, for "yes" forward to this path or
> action, or for "no" forward to that path or action.

But that information is not static.  "No" might return me to different
paths depending on where I was coming from (i.e. depending on where the
"dialog box" was invoked from).  Because, remember, "returning to a
page" is webspeak for "dismissing the dialog box" in regular UIspeak.
So even in the struts-config.xml, with all of its mapping semantics, you
can't always know where the user should be taken.

> If we needed "no"
> to go so some arbitrary page, then that might be something we can save
> and restore from the session context. It's also possible that the
> referer header could be used for automatic returns to a "grandparent"
> page.

Right; lots of frameworks and such handle cases back to the grandparent
level.  I'm suggesting that this should be generalized to handle any
ancestor as well.

> It's possible that we already have that functionality in the Action
> mappings. Each action can have it's own set of logical forwardings, or
> refer to a set of global forwardings. A nice feature here is that you
> can change and reload the mappings, without recompiling source!

Right, but you don't always have the information to build those mappings
in the first place.

Cheers,
Laird

--
ljnelson@unix.amherst.edu
http://www.amherst.edu/~ljnelson/
Good, cheap, fast: pick two.


Re: Any way to dynamically change flow-of-control?

Posted by Ted Husted <ne...@husted.com>.
On 1/10/2001 at 11:27 PM Laird J. Nelson wrote:
> What is now needed is a navigation stack of some kind--perhaps even
something that is written/phrased in terms of "traditional" UI
metaphors.  

The other place this idea comes up is the problem with users
bookmarking pages that require a form-based login. 

One solution, that I admittedly have not tried, might be to set an
attribute in the session context that your Actions would monitor, if
they might need to return to some arbitrary place in your application. 

You're right that it would be helpful to describe more of the Struts
framework in conventional IU metaphors. For example, in the case of

> "OK, go to the next screen that I'm being told to go to, or if I'm
not being told to go anywhere, go to this
default location".  

The action would get the "being told to" out of the request parameters
or form bean(s), and then get the "next screen" from it's
ActionMappings. 

>Or the Action might be able to say "oops, conditions aren't right to
advance; pop the stack and go back to where we were a
moment ago but display the following message".

Here, the form's validation action says "oops", sets the mesages as
needed in the ActionError collection, and returns to the input form
specified by the action mappings (from struts-config.xml). 

>Now think that somewhere in that flow a *logical* dialog box is
supposed to present itself .. If the answer is Yes, then the next
"screen" should be, well, the next screen.  If the answer is no, then
the next "screen" should be the very same page that triggered this
"dialog box" to appear, since after all when you dismiss a dialog box
it goes away, leaving you right where you were before.

I think here the "logical dialog box" would be the action, and the yes
and no answers are mappings for that action from the struts-config.xml.
So your config might actually say, for "yes" forward to this path or
action, or for "no" forward to that path or action. If we needed "no"
to go so some arbitrary page, then that might be something we can save
and restore from the session context. It's also possible that the
referer header could be used for automatic returns to a "grandparent"
page.

> It would be great if there were some kind of stack built into struts
to let this happen in one place.  You'd have your
EnterBillingInfoAction that would step through its *own* screen flow,
using perhaps its own stack, and then at the end of *its* stack would
know to "pop" back to the main navigation stack.

It's possible that we already have that functionality in the Action
mappings. Each action can have it's own set of logical forwardings, or
refer to a set of global forwardings. A nice feature here is that you
can change and reload the mappings, without recompiling source!


-- Ted Husted, Husted dot Com, Fairport NY USA.
-- Custom Software ~ Technical Services.
-- Tel 716 425-0252; Fax 716 223-2506.
-- http://www.husted.com/



Re: Any way to dynamically change flow-of-control?

Posted by "Laird J. Nelson" <lj...@unix.amherst.edu>.
----- Original Message -----
From: "Felciano, Ramon" <fe...@ingenuity.com>
> We often want to insert certain UI actions based on exceptional user
> behavior. A simple example is an authentication  screen that gets
inserted
> "just in time". For example, if the normal flow of control is from
page A
> --> page B, where page B requires authentication, then 98% of the
time, the
> user goes A --> B. However, the very first time this happens we want
to
> insert an authentication page: A --> Logon --> B.

(Incidentally, this can be handled for you by your J2EE-compliant
servlet engine; read section 9 and following of the servlet 2.2
specification and look at form-based login.)

> Other situations where
> this type of intermittent insertion of additional UI and flow logic
would be
> helpful include:
> - Confirm pages ("Are you sure that xxxx?" with "Continue" and
"Cancel"
> buttons)
> - Pick lists ("We couldn't find the product ID you entered; please
select
> from the following list")
> - Alert pages for (possibly unexpected) server-side events that
occured
> since the last client-server traffic passed through.

I like to think of this as the "dialog box problem" that web UIs face.
That is, each case above, in a "traditional" client-server program,
would be implemented, usually, as a dialog box.  What's unique about a
dialog box?  It pops up and gets in the way of where you (a) are or (b)
were trying to go.  Only when you dismiss it are you "returned" to
either (a) or (b).  On the web, of course, with our primitive HTML-based
UIs, there are no such things as dialog boxes (unless you use
javascript).  So "screen flow" becomes all important.

I bring this up because struts seems to have gone partway--better than
any other framework I've seen--but not all the way in its support of
this dialog box metaphor (it uses form beans).  What is now needed is a
navigation stack of some kind--perhaps even something that is
written/phrased in terms of "traditional" UI metaphors.  I'm thinking
about some kind of stack--and believe me, I haven't thought this all the
way through yet--that can be accessed by Actions, but any given Action
would typically say something like "OK, go to the next screen that I'm
being told to go to, or if I'm not being told to go anywhere, go to this
default location".  Or the Action might be able to say "oops, conditions
aren't right to advance; pop the stack and go back to where we were a
moment ago but display the following message".  Things on the stack
would be *roughly* equivalent to screens--though I hesitate to use
"screen" as I think that's one of the major shortcomings of the Turbine
framework, because a "screen" on the web often exists as a separate
entity only because the marketing department said it has to.

Where am I going with all this...think of registration for a typical
corporate website.  Often you'll be asked to enter a lot of personal
information.  All of that personal information may span many screens,
but logically speaking is itself one...one..."data unit"--one form bean,
to use struts' terminology.

Now think that somewhere in that flow a *logical* dialog box is supposed
to present itself ("Are you sure you have entered your credit card
information properly?").  If the answer is Yes, then the next "screen"
should be, well, the next screen.  If the answer is no, then the next
"screen" should be the very same page that triggered this "dialog box"
to appear, since after all when you dismiss a dialog box it goes away,
leaving you right where you were before.

Or think of an enter billing information screen that can be accessed
either (a) at registration time or (b) at
unregistered-user-creating-a-new-order time.  You want to reuse the same
"dialog box" ("Please enter your billing information") in both cases,
but you want to remember where to "go back to" when (a) registration
"pops up" this dialog box and when (b)
unregistered-user-creating-a-new-order "pops up" this dialog box.  It
would be great if there were some kind of stack built into struts to let
this happen in one place.  You'd have your EnterBillingInfoAction that
would step through its *own* screen flow, using perhaps its own stack,
and then at the end of *its* stack would know to "pop" back to the main
navigation stack.

OK, it's late, I've rambled, and I apologize.  I hope this makes some
sense.  If I have some free time later, I'll see if I can code this up.

Cheers,
Laird

--
ljnelson@unix.amherst.edu
http://www.amherst.edu/~ljnelson/
Good, cheap, fast: pick two.