You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by "paul.t.smith" <pa...@attbi.com> on 2003/01/05 06:02:23 UTC

Struts Version 2 Proposal - Workflow and extra

Dear Struts Commiters,

I know that the current focus is on finalizing Struts 1.1, but I would like
to propose a design for version 2.0. I have taken the commons-workflow
package and built on top of it a package which I have been calling PageFlow.
The modifications Ive made basically "webify" the workflow package and make
it more conceptually sound for building and maintaining large web
applications.
PageFlow provides a significant feature-set enhancement over the current
Struts application controller. Some of the improvement is based on the
features of the
commons-workflow and some of I have added. I have not really attempted
to improve the building of the pages themselves, just the controller piece.

Id like your input on getting the design and code out there
for evaluation. I am at the prototype level and having just come off a large
Struts application, I know this package would really push the Struts
forward. Unfortunately, the code is not built into the current contrib
structure so
putting it there would make the build difficult. There is still a
significant amount of
code documentation to complete etc. This is completely prototype
code so the edges are a little (read very) rough.

The most significant features are:

Contextual Pages and Actions:
Page flows are logically grouped sets of "pages" connected by "actions".
Actions
are declared "between" pages and are made up of one or more steps.
In other words they are little workflows. In fact the page flow is the
central metaphor for
the framework. For example, the developer declares a "page" in the
struts-config file (what is called a forward right now) and then uses
an "instance" of that page in a pageflow. The benefit to the developer is
that
a JSP may be re-used in different ways at different points in the
applicaiton. That means the inside a page-flow a developer may use a page
with a different form,
different actions, etc.
For example, in a recent Struts application, I had numerous
places from which could reach an edit screen. This screen had to have a
large
logic:if block for its submit button (since we needed different action
objects, parameters, etc depending on where we came from). In pageflow the
actions are based on the users location in the context, so all "pages" and
"actions" are contextual.

Workflow: The workflow features of PageFlow are much like those of the
commons-workflow. An action is composed of steps. These steps can be custom
written by the developer, though I have a significant number of re-usable
actions already defined. This concept is perfect for re-use. I have
steps to call other workflow systems (BEA BPM, Commons-Workflow, Tibco
BusinessWorks, etc), web services, print log statements, call session beans
and a
host of others can be written later. These re-usable steps will reduce the
actual
code on web apps dramatically.

Mult-Level Wizards and PageFlows: Page flows are able to be nested at any
level of depth and may be called from other actions with parameters. As all
of the activities in a web application are housed in a page flow this makes
generating a wizard or a re-usable application trivial. For example, a
developer could create an add/edit/delete pageflow and then pass in the
variable (entity bean, jdo, custom data object) to be added/edited/deleted
as well as custom tiles declarations so the appropriate pages would pop-up.
A wizard is even simpler. Any of these pageflow may also nest other
pageflow while still sharing data through the session and application scopes
or through parameters.

Events: All of the commons-workflow events are fired. I have also added web
applicaiton specific events like navigation events, form object events,
action events, scope modifier events, application load and destroyed events,
etc. This makes it easy to execute logic based on the users context or very
complex combinations of events (add an event listener so that anytime a user
goes to the "resume" it will check if they used the name "Tom" in the
session.username variable, etc.) The user may add an event listener by
adding a
step to the xml pageflow declaration.

Macro MVC: currently Struts supports page-level MVC. That is, the model
object is represented by the form, the view by the page, and the Struts
Request Processor is the controller. I have kept this intact in PageFlow,
but have added declarative memory management (via decalaring and using
"variables"
in the struts-config.xml and pageflow-config.xml files) and
allowed objects in these scopes to be assigned and converted to/from form
variables. This allows the developer to use and modify objects in memory
without writing any java code. I call it Macro MVC because the variables are
made higher level model objects which provide data to/from from objects
(which effectively become the view objects) and the controller handles
conversion to/from the form to the variables. I have even specd out a set of
special classes which function as dynamic value objects for EJB and can be
used as "variables" giving automatic value object passing into the business
tier (thus you
can write a significant web application using entity and session beans and
the only java you'd write is for the EJBs, custom tasks). These variables
are can be declared at 4
scopes; application, session, pageflow, action. All variables are
automatically
garbage collected upon exiting their scope (that is when the user exits an
action or
pageflow the variables are cleaned up) This saves a good deal of work in
large web apps)

Fine-Grained Filters: I very much like the servlet filters which have been
added recently, unfortunately, they only work at a very course-grained
level. PageFlow includes fine-grained filters which function in the same way
as servlet filters. They can be executed on the application, pageflow, page,
or action levels. This means for certain pages or specific actions the
developer can execute a filter object which will receive the request and
response objects prior to them being processed in any other way.

Scripted Actions: PageFlow has a javascript task which can execute any
server-side javascript declared in it's input parameter. This allows the
developer to execute extrememly complex functions without any java files.

EL compatible script: Currently scopes and variables are accessed via XPath
notation (I used the JXPath processor from commons). However, the final
version should
allow EL compatible notation in the configuration files, statements, step
parameters, etc.

JSF compatible: It should require very little work to make pageflow
compatible with JSF. PageFlow uses a Filter now.

Completely customizable Request Processor: The engine itself is written as a
workflow which is parsed from the struts-config and
struts-pageflow-config files. This allows the developer to completely
customize the way that the engine responds to a request, starts an action or
whatever. In the future this could allow for very fast processing.

Struts 1.1 compatible: PageFlow only recognizes requests with certain
request.parameters. It is built as a Filter and will pass through any
requests that it does not recognize to Struts or other frameworks. It will
recognize and use form objects, forwards and most Action objects (with some
caveats) inside of a pageflow. The only thing I havent been able to figure
out is how to make sub-apps compatible. It is a relatively large leap, so I
expect Ive missed a good deal of the incompatibilities. The things I havent
included
in the prototype are; latest tiles integration, validation (though the
placeholder
is there), modules,

Please let me know your thoughts,

Paul T. Smith






----- Original Message -----
From: "Craig R. McClanahan" <cr...@apache.org>
To: "Struts Developers List" <st...@jakarta.apache.org>
Sent: Wednesday, April 10, 2002 10:42 AM
Subject: Re: Servlet 2.3 filter


>
>
> On Wed, 10 Apr 2002, Steven D. Monday wrote:
>
> > Date: Wed, 10 Apr 2002 08:30:33 -0500
> > From: Steven D. Monday <MO...@cat.com>
> > Reply-To: Struts Developers List <st...@jakarta.apache.org>
> > To: Struts Developers List <st...@jakarta.apache.org>
> > Subject: Re: Servlet 2.3 filter
> >
> >
> >                     "Craig R.
> >                     McClanahan"
> >                     <craigmcc@apa
> >                     che.org>
> >
> >                     04/09/2002    To: Struts Developers List
<st...@jakarta.apache.org>
> >                     10:27 AM      cc:
> >                     Please
> >                     respond to
> >                     "Struts
> >                     Developers           Subject:     Re: Servlet 2.3
filter
> >                     List"
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > Caterpillar: Confidential Green          Retain Until: 05/09/2002
> >                                          Retention Category:  G90 -
> >                                          Information and Reports
> >
> >
> >
> > I do appreciate your response and have a couple follow up questions.
> >
> > > How do you set up the data the *first* time you want to
> > > access a particular page (the way you'd use a setup action
> > > in a Struts based app)?
> >
> > Not sure I can comment on this issue since we're very new to the Struts
> > world but I would like to hear a scenario in which "setup actions" would
be
> > applied.
> >
>
> Using a filter for the controller would not change the basic application
> paradigm for Struts-based apps - you would still use a setup action first.
>
> The canonical example for this is you want to do a typical "master file
> maintenance" type application in a webapp (for example, to maintain
> customer records).  The form for a new customer and an old customer are
> very similar, so you'd like to use the same page for both transactions.
> A typical way to set this up in Struts:
>
> * To set up a new customer, call the action
>   "/setupCustomer.do?action=create"
>
> * To set up an old customer, call the action
>   "/setupCustomer.do?action=Edit&customer_id=123456"
>
> * In SetupCustomerAction, you set up a new CustomerForm
>   bean.  Then, if the "action" parameter is "create" you
>   configure it with all the default values for a new
>   customer.  If the "action" parameter is "edit" you go
>   grab the data out of the database, and prepopulate the
>   form.  I usually add the "action" parameter as a property
>   of my form bean (and use a hidden field on the form) so
>   that the save action called later knows what kind it was.
>   Finally, SetupCustomerAction forwards to the appropriate
>   "edit customer" page via an ActionForward.
>
> * In the edit customer page, the customer form bean will
>   already exist, and you just display the entry form.  If
>   you are editing, the previous values will be there automatically.
>   You can make decisions to display things differently (for example,
>   you might let a new customer set their own id but disable the
>   ability to change it on an existing customer) with <logic:present>
>   and <logic:equals> type tags.
>
> * The edit customer page includes the "action" property as a hidden
>   field, and submits to a "/saveCustomer.do" action which ultimately
>   calls SaveCustomerAction.
>
> * When the form submit happens, the validate() method of the customer
>   form bean is called in the usual way, so the user might be returned
>   to the input form again.
>
> * If the input data is ok, SaveCustomerAction must perform the database
>   updates needed to reflect the required changes.  If you are talking
>   to the database directly from an Action, you would construct an
>   appropriate INSERT or UPDATE statement, depending on what the "action"
>   property was.  Alternatively, you can just package up the required
>   data in a value object and send it off to the appropriate EJB or
>   whatever, calling a "create" or "update" method depending on the
>   "action" property.
>
> The /struts-example webapp included with Struts illustrates this design
> pattern on a very small scale.  For a larger scale example, we're building
> an administrative webapp for Tomcat 4 based on Struts (1.0.2 at the
> moment) that follows this pattern all over the place.  To take a look,
> grab a recent nightly build of Tomcat 4 from
> <http://jakarta.apache.org/builds/jakarta-tomcat-4.0/nightly>
> (source code drops are in the "src" subdirectory underneath.  An
> interesting aspect of this app is that the "database" is really a set of
> JMX MBeans that correspond to the internal components of Tomcat 4.
>
> > > What happens when a particular form submit should be handled
> > > differently (and trigger different output) depending on the
> > > contents of the included fields?
> >
> > I believe that filters can exercise the option to handle the
> > request/response themselves or to forward the request/response to the
next
> > filter in the chain.  I would think that should it be the case that if a
> > filter chose to evaluate request parameters and handle the response in a
> > different fashion (e.g. dispatch to a different jsp) dependent upon
> > parameter values it would have that perogative.
>
> This scenario can be handled just like it is today -- the action to which
> the form is submitted is perfectly free to send the request wherever it
> needs to, based on the received input fields.
>
> >
> > > What happens when you successfully complete a transaction and
> > > want to go on to the next one  (you can't just forward to the
> > > "new" page because filters won't get invoked again)?
> >
> > Could you give me some further insight into this comment, particularly
with
> > regard to the phrase "complete a transaction"?  I'm no doubt looking at
> > this filter concept from too simplistic a perspective.  Could you
describe
> > a transaction scenario?  I suppose I was looking at a filter chain that
> > might include a security filter, followed by a business logic filter,
> > followed finally by a view dispatching filter.  In other words a
> > "transaction" would include authentication/authorization, action and
> > response generation.  I don't think in this simple example I would
> > want/need filters to be invoked again before the jsp is dispatched to.
I
> > suppose if I did I would include filters in the above mentioned chain
that
> > would to additional view related manipulation of my business logic
filter's
> > output before the jsp filter.
> >
>
> For "complete a transaction", look at what SaveCustomerAction does in my
> example scenario above.
>
> However, the point being made in this sentence is an important one -- in
> Servlet 2.3, filters are only invoked on the *initial* request, not on the
> results of doing a RequestDispatcher.forward() call (which is what Struts
> does to forward to an appropriate response page).  That actually makes it
> easier to write a controller as a filter, but harder to use filters for
> some of the ways you might want to (like doing an XSLT transformation on
> the generated output, depending on what user-agent submitted this
> request).
>
> The processing of the controller itself can be decomposed into separate
> filters -- but I think the above comment was referring to application
> level transactions, not internal controller processing.
>
>
> >                          Thanks
> >
>
> Craig
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>
>
>



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>