cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniela Gehle <d.ge...@levigo.de>
Subject [RT] Flowmaps revisited
Date Tue, 09 Oct 2001 14:47:53 GMT
Dear Cocooners,

I've been following your discussions concerning the Flowmap topic with
high interest, as our company is working on a web application showing
exactly the same problems that could be solved by some kind of Flowmap
or Transition Map (as I prefer to call it to avoid confusion with the
ongoing Flowmap proposals).  We've been reading and discussing your
proposed approaches carefully and found valuable inspiration in it.
(Although some parts of your proposals are still covered with mist, for
example the usage of filters in Berin's proposal. Maybe someone else can
enlighten us. :-)

Resulting from these considerations we envision a slightly different and
"lighter", but not less powerful way to implement flow control in Cocoon
2, which I would like to present you herein.

This approach is "lighter" in the sense that it can easily be integrated
into the current Cocoon 2 framework using the actors concept. Once the
Cocoon Sitemap implementation will change from compiled to interpreted,
this approach can easily be adapted and integrated into the new Sitemap
concept. But for now all we want is a generalized implementation without
any changes affecting the Cocoon framework itself.

Of course we would like to contribute the implementation of this
Transition Map approach to the Cocoon project, so please let me know
what you think about it, if we misunderstood some of your points or if
we are missing any important details. The proposal itself is not
entirely fixed yet (and of course not yet coded as well :-), so you
still have the opportunity to influence the design we propose, to make
it perfectly fit into the Cocoon framework.

Ok, fastened your seat belts? - So let's start with the explanation:

---------------------------------------------------
Reminder: Pages, navigation and flow.
---------------------------------------------------
One of our web applications requires the user to step through a number
of pages in a controlled sequence (or "flow"). Each of these pages is
accompanied by background "actions" performed by Java classes. These
actions concern data generation as well as data processing. From each of
these pages just a very small, context-dependant subset of other pages
is accessible, and only these transitions should be displayed to the
user.  What makes these transitions even more complicated, is that some
of them require not just the target URL but additional data that will be
processed by the underlying program logic.

This is very much in contrast to most of the common web applications
where you have some kind of   general navigation menu accessible from
each of the pages and provide the same navigational links for all of the
pages.

Therefore we can distinguish two different types of navigation:

- navigation as a way to consistently structure and group resources
(mostly in a hierarchical manner) and make them accessible for the user
in a fashionable way (we could call this type of navigation "static
navigation"), and

- navigation that refers to states in a flow and grants access to a
subset of pages that are part of a flow. We call this type of navigation
"flow navigation" from now on.

Static navigation is a pretty simple issue, so we will concentrate on
flow navigation in this article. As a special aspect of the flow control
presented here, the approach provides a mechanism to generate these
"flow navigation" elements automatically from the state description in
the Transition Map. As far as I know, this is a topic that has never
been addressed on the Cocoon list before. 

I don't want to confuse you - so I will touch this mechanism only
marginally within this presentation, but in fact it is an important
requirement that had fundamental influence on the presented design. If
you are interested, let me know, and I will feed you with additional
details.

---------------------------------------------------
What issues do we cover?
---------------------------------------------------
Now that we know the rough picture it is time to look a little bit
closer at what requirements have to be met exactly. This flow handling
approach covers not only flow control itself but some additional aspects
as well:

(1) Controlling the flow (i.e. state transitions) of the application.
(2) Separation of data processing ("control" aspect of the MVC pattern)
and data generation ("view" aspect of the MVC pattern).
(3) User authentication and authorization.
(4) Jumping to any visible state in the middle of the flow in one hop. 
(5) Automatic generation of "flow navigation" elements for each page.
(6) Handle form submits.
(7) Support generation of forms.

We will see how all this works together later. 

--------------------------------------------------------
Sample application
--------------------------------------------------------
The problem description is borrowed from the concept of finite state
machines and relies on a formal description of states and transitions.
Please note that this is the main difference to the previous
propositions on this list - we do not just concentrate on the states,
but on transitions as well. Each transition requires a particular set of
parameters tied to the transition. These parameters are used to generate
flow navigation elements and forms.

Let me explain this with an example. Assume a flow representing an
archive searching application requiring user authentication. For
example, think of a newspaper article archive containing articles to
several topics where autorized journalists are allowed to drop queries.
The page sequence that is crossed  performing a query might look like
this:

login -> topic-selection -> search-form -> result-list ->
article-display

The main processing direction is forward, but a backward navigation to
any of the previous pages has to be supported as well. If you are
currently looking at a newspaper article (article-display page), you
might want to jump to the page where you can change the selection of the
topic (topic-selection page). Or you might want to change your password
from any of the pages - this means that access to a "change-password"
page must be possible from every page.

This shows us that the flow is NOT just a simple sequence of pages
processed in a row, but of a much more complex structure (which is not
really easy to draw in ASCII graphics and therefore be omitted here :-). 

Moreover, we have been cheating a little bit so far. The flow consists
not only of pages - representing visible states of the system
(accessible via an URL) - but also of hidden states where system
operations are performed (like data verification or query processing).
These hidden states can lead to visible states or to other hidden
states.

Therefore, the login sequence of the above mentioned page flow should
better be written like this:

login --(AUTH)--> [check-login] --(AUTH-OK)--> topic-selection ->..
login <--(AUTH-NOT-OK)--|   

Please note that in this notation the transitions themselves have unique
names like (AUTH) or (AUTH-OK), and the hidden state [check-login] is
marked with square brackets to illustrate the difference to   visible
states. As its name proposes, the [check-login] state verifies and
processes the data entered in the login form on the login page.

Another important point is that the transitions are transporting data
from one state to another. The (AUTH) transition, for example, carries
fields like username="paul" and password="foo". These fields will be
evaluated by the subsequent state.

Now we can put together a description of all states and all transitions
in a Transition Map:

--------------------------------------------------------
The Transition Map
--------------------------------------------------------
<flow start="login" name="search-archive">
<transitions>
  <transition name="AUTH" target-state="check-login">
    <parameters>
      <parameter name="username" xpath="/environment/user"/>
      <parameter name="password" xpath="/environment/pass"/>
    </parameters>
  </transition>
  <transition name="AUTH-OK" target-state="topic-selection"/>
  <transition name="AUTH-NOT-OK"  target-state="login"/>
  <transition name="SELECTTOPIC" target-state="find-topic">
    <parameters>
      <parameter name="topic" xpath="/topics/topic"/>
    </parameters>
  </transition>
  <transition name="LOGOUT" target-state="perform-logout"/>
   ...
</transitions>
<states>
  <state name="login" resource="*/login">
    <if event="AUTH" transition="AUTH"/>
    <if event="CHANGEPASS" transition="CHANGEPASS"/>
  </state>
  <state name="check-login">
    <act type="LoginAction"/>
    <if event="OK" transition="AUTH-OK"/>
    <if event="ERROR" transition="AUTH-NOT-OK"/>
  </state>
  <state name="topic-selection" resource="*/topic-selection">
    <if event="LOGOUT" transition="LOGOUT"/>
    <if event="SELECT" transition="SELECTTOPIC"/>
  </state>
  <state name="perform-logout">
    <act type="LoginAction"/>
    <if event="OK" transition="LOGOUT-OK"/>
    <if event="ERROR" transition="LOGOUT-NOT-OK"/>
  </state>
   ...
</states>
</flow>

A Transition Map can contain several flow definitions, each of them
carrying a unique name and being responsible for a different functional
unit (<flow start="..." name="...">).

The first part of each flow definition consists of the definition of all
transitions (<transitions> ... </transitions>). Each transition is
described by a unique name, a target state and the parameters that are
required for this transition. These parameters are NOT necessary for the
flow control itself, but they are for form handling and automatic
generation of flow navigation elements. They result either from filling
form fields or represent environmental data provided by the data
generation classes. The latter can be evaluated automatically by using a
specialized "FlowNavigation" transformer, but I don't want to mix up
things here, so I'm concealing the details of this transformer for now.

To describe the flow as a whole we do not just need the transitions but
also information about the states and by which transitions they are
connected. The state descriptions (<state>...</state>) distinguish
between visible and hidden states. Visible states can be reached by
requesting a specific URL - hidden states cannot.  Visible states carry
the URL resource they are mapped to in the resource parameter of the
<state> element; hidden states carry information about the handler that
is executed when entering the state. These handlers can be implemented
as actors. It might be possible for a visible state to contain a handler
as well, but this is not recommended, because then the clean separation
of visible and hidden states would be broken. 

The decision which of the possible transitions to follow at a specific
point is done by evaluating the transition event parameters. These
parameters are either URL parameters (in the case of a visible state) or
result parameters of an action (in the case of a hidden state). Event
parameters are written in Capitals in order easily distinguish them from
ordinary parameters. 

--------------------------------------------------------
Sitemap configuration: the FlowHandlerAction
--------------------------------------------------------
In order to control the flow and the state transitions there is a
FlowHandlerAction hooked up in the Sitemap. More precisely, the
FlowHandlerAction will be performed for each URL that is representing a
(visible) state in the flow.  The FlowHandlerAction has to be fed with
the name of the flow for each pattern match within a flow. 

The Sitemap contains something like

<map:match pattern="in-the-flow/*">
  <map:act type="FlowHandler">
    <map:parameter name="search-archive"/>
  </map:act>
  <map:act type="AuthenticationAction">
    <map:redirect-to uri="in-the-flow/login"/>
  </map:act>
  <map:generate type="saxlet" src="templates/{1}.xml"/>
  <map:transform src="styles/{1}.xsl"/>
  <map:serialize/>
</map:match>

The Transition Map file itself will be specified within the definition
section of the FlowHandlerAction:

<map:actions>
  <map:action name="FlowHandler" src="org.bar.foo.FlowHandlerAction">
    <map-file>transitionmap.xmap</map-file>
  </map:action>
</map:actions>

--------------------------------------------------------
Are all the promised features there? 
--------------------------------------------------------
(1) Controlling the flow (i.e. state transitions) of the application? -
Yes. 

(2) Separation of data processing ("control" aspect of the MVC pattern)
and data generation ("view" aspect of the MVC pattern)? 

Yes. Control is performed by the handlers of the hidden states, data
generation is performed by the specific Generator (ServerPagesGenerator,
SAXLet Generator,...) for each page representing a visible state.

(3) User authentication and authorization? 

Yes. Except for the login process itself which is performed by the
LoginAction Handler of the "check-login" state, user authentication and
authorization are located in the AuthenticationAction used in the
Sitemap. Please note that this is one of the main differences to Berin's
proposal, were an authorization mechanism was part of the flowmap
itself. We decided to put the authentication and authorization aspects
apart, because not all applications rely on the same consistent
authentication/authorization mechanism. Therefore, in order to be open
to any authentication/authorization requirements, it seemed to make more
sense to  place them in actors called from within the Sitemap or the
Transition Map. Of course, a combination of both approaches is perfectly
possible.

(4) Jumping to any visible state in the middle of the flow in one hop? 

Yes. This is possible, provided that the necessary ordinary and event
parameters for the march along the transitions leading to the desired
target state are passed along with the HTTP request. As long as the
required parameters for the transitions between the states are contained
in the URL, the state machine will jump from state to state without
bothering the user with displaying pages belonging to intermediate
states. 
For example: If you want to jump to the state "search-form" without
crossing the "login" page, you can enter the URL:
http://foo.bar/in-the-flow/login?username=Paul&password=foo&AUTH=true&topic=squirrels&SELECT=true.
Starting from the "login" state the subsequent states "check-login",
"topic-selection" and "find-topic" are automatically crossed, leading to
the target state "search-form" (and displaying the "search-form" page to
the user). 

(5) Automatic generation of "flow navigation" elements for each page? 

Yes. This task will be performed by a specialized FlowNavigation
transformer using the xpath attributes of the transition descriptions in
the  Transition Map, matching them against XML elements of the generated
data and inserting generic "flow navigation" controls in the XML data
that is being processed.

(6) Handle form submits? 

Yes. Default target of a form submit is always the current page (=state)
itself. The FlowHandlerAction checks if there's an event parameter
triggering a transition leading to another state (according to the state
and transition description in the Transition Map) or if there is no
matching event parameter and the page itself has to be generated.

(7) Support generation of forms? 

Yes, this is possible in combination with flows, but not implemented
yet. Using a form descriptor similar to the <parameters> element of the
transition description in the Transition Map, forms can be generated in
a unified way, with the default form submit target being the current
page.

-------------------------------------------------------------
How does this proposal fit into the future plans for Cocoon?
-------------------------------------------------------------
That's a point pretty hard to answer for me, because I cannot sneak in
the heads of the Cocoon front row developers. All I could do is point
out the aspects we've been considering. Now it's your turn, please throw
your stones. ;-)

Thanks,
Dani

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


Mime
View raw message