Hi Christoph ... thanks for the comments, and see embedded replies below.

Also, I'm about to post some concrete code (in commons-sandbox) that can
help us crystalize our thinking a little.

On Mon, 13 Aug 2001, Christoph Reck wrote:

> With the enclosed XML things become much clearer. I have some comments:
> * Some <app:forward ...> tags do not have a closing tag. I believe it 
>   should close after the <app:navigate> part (or after the core:if and 
>   core:goto parts).

Yah, of course, everything needs to be proper XML :-).

> * The <app:branch control="..." idref="..."> is also not clear where 
>   the control comes from. It should be enclosed by an <core:if> when
>   the branch is conditional.

The theory there is that you will provide some mechanism in your form
submits to identify where (within the workflow activity you are
running) control should go next.  Details need to be fleshed out, but the
motivation is that you need to support things like "Previous", "Next", and
"Finish" buttons in a wizard without involving the page designer in the
details of how the workflow is managed.

For a framework-independent implementation in the "web" layer, this might
be as simple as some conventions on names of submit fields to represent
the various navigation gestures.  For the Struts-specific layer (on top of
the generic "web" layer, in jakarta-struts rather than here) I plan to
provide a set of custom tags for this -- I could image Turbine providing
some standardized services to implement the same sort of feature.

> * IMO the $parameter should be adressed by a dot instead of a colon:
>     <ctx:set name="username" value="$parameter.username"/>
>   this is more java and bean like!
> 

The expression language to be used has *not* been determined yet!  The
examples are only to motivate discussion about what might be possible, not
as "done deal" illustrations of the selected syntax.  (Personally, I'm
kinda fond of XPath type syntax, but that's just me ...).

Also, given the extensibility of the framework, it's easy to provide
your own expression-evaluation Step implementations if you don't like
whatever ends up being the "standard" ones.

> Wouldn't the following structure better represent the workflow?
>   <flow:task>              instead of the <flow:workflow> 
>     <flow:step view="..."> instead of the <app:navigate> which is rendered
>                            by a specific view (instead of the <app:forward>).
>       <ctx:set ...>
>       <core:if ...>        replacing the <app:branch>. The enclosing 
>         <flow:branch>      <app:navigate> is not necessary. The branch may 
>       </core:if>           be enclosed within <core:if> and preceeded by 
>                            <ctx:set> cascades...      

Likewise, these are details that need to be fleshed out.

The initial implementation I'm about to check in doesn't support nested
steps yet (or even provide any built in steps to change the control flow),
although the underlying Context implementation will support it for
non-nested steps.

> 
> Will the workflow manager keep the task/step state to continue
> the navigation? Or will the application supply the parameters
> of the desired task/step IDs (e.g. within the URI)?
> 

Details depend on how you are using the workflow engine.  But the key
point, and I feature I haven't seen in other attempts at workflow
managers, is the ability to "suspend" a computation and come back later.  
In this scenario, the Context is used to maintain the current
computational state of a particular computation for a particular user --
so that, when control is returned to the workflow engine, it picks up
where it left off.

Now, in a batch program, you might not ever need this
"suspend" capability, because you could encode the entire computation as a
single activity.  But if you're writing a Swing app, or a web app, you
have to give control back to the surrounding environment at some
points.  Because web apps are familiar to lots of us, let's consider that
case in a little more detail.

I envison that you'd integrate the workflow engine into a web app by
storing a Context instance in the user's session (so that they'd always
come in to the most recent state of that computation).  The context
remembers where they were before, and starts computing again (using Scopes
as a way to make things like request attributes available to the steps in
your computation).  Now, when you're ready to display a page, you'll do a
RequestDispatcher.forward() to whatever technology you're using for the UI
(a JSP page, a velocity template, whatever).  Now, at this point, you need
to return control to the servlet container -- remember, you're executing
on the request processing thread -- so that the response can be sent back
to the user.  Hence, the need for the "suspend" feature.

This will make more sense when I check in some code into the sandbox later
this afternoon.

> In a previous project (early 2000) I faced a similar requirement
> and created a similar specification. I watched closely the cocoon2
> and turbine approaches of web applications, but found these not
> appropiate. JSP could have solved the view part, but would have been
> ugly. 
> 

:-)

> I finally created the application based on Velocity, where I 
> scripted exacly this workflow task handling per-request using VTL.
> This then loaded a corresponding step controller VTL script that
> did the <ctx:set>, <core:if> and <core:invoke> parts (using the VTL 
> conterparts) and then loaded the view template. My application
> then used a skin layout to format the final output (à la Turbine).
> 
> The used context tools used are already part of commons.ruppert in 
> the sandbox. The controller in my application can read external files 
> (directories, text and xml) and can run external scripts with these 
> tools. Velocity and a simple ApplicationServlet is all that's
> neccesary for this to run. This is working great and is *really* 
> simple! 
> 

Sounds pretty nice ... I will take a look at the rupert code.

> By mapping the VTL controller code to XML it might gain some 
> toolability (structure & syntax checks plus automatic generation 
> and information extraction).
> 

If it's not already done, can I assume that you can abstract out the
web-layer-specific stuff?  I've got use cases in mind for workflow
management that are not web apps, so this is one of the itches I need to
scratch.

> I have concrete examples for such an application approach. I can 
> supply sample XMLs for further discussions/clarifications.
> 
> Please contact me for any questions. 
> :) Christoph
> 

Craig


> Ted Husted wrote:
> > 
> > Craig R. McClanahan wrote:
> > 
> > > It should be feasible to subdivide the "Struts integration"
> > > into generic integration with the web layer (mapping to
> > > servlet API concepts) and the features that are truly
> > > Struts-specific (such as mapping a logical ActionForward
> > > to a particular resource path)."
> > 
> > Maybe we should do that sooner than later, and start out talking about
> > "framework integration" instead.
> > 
> > The pseudo-code for the original proposal contemplates three tiers:
> > core, web, and "struts". The elements labeled "struts" are not actually
> > part of the current framework. Perhaps it would be helpful to label
> > these "app" instead, with the understanding that this is the tier that
> > each framework would implement for its own application.
> > 
> > While Struts does use terms like "forward" and "action", these are
> > common terms that stem from HTTP and HTML. If a framework did not
> > support named, or logical forwards, it might have to use a URI instead.
> > 
> > Meanwhile, the "web" tier might also be generalized as the context tier,
> > and there may be implementations of this for Web, J2EE/EJB, et cetera.
> > The workflow script might not need to know which implementation was
> > being used, and so we could just refer to the context instead.
> > 
> > To wit,
> > 
> > <flow:workflow name="Application Logon">
> > 
> > <-- Display the logon form (Struts maps to a real JSP page) -->
> > <app:forward id="display" name="Logon Page"/>
> > 
> > <-- Authenticate the username and password, returning a Principal
> >                 if accepted, or null if not -->
> > <ctx:set name="username" value="$parameter:username"/>
> > <ctx:set name="password" value="$parameter:password"/>
> > <core:invoke bean="authenticator" method="authenticate">
> >         <core:param type="java.lang.String" value="$username"/>
> >         <core:param type="java.lang.String" value="$password"/>
> >         <core:return name="principal"/>
> > <core:invoke/>
> > 
> > <-- If no Principal was returned, branch back to the logon form -->
> > <core:if expr="$principal == null">
> >         <ctx:set name="error" value="$messages.lookup('invalid.logon')"/>
> >         <core:branch idref="display"/>
> > </core:if>
> > 
> > <-- Exit to the "Main Menu" workflow -->
> > <core:goto name="Main Menu"/>
> > 
> > </flow:workflow>
> > 
> > <flow:workflow name="Simple Wizard Application">
> > 
> > <!-- Display the first page of the interation -->
> > <app:forward id="page1" name="Simple Wizard Page 1">
> > 
> > <!-- Process navigation input from the first page -->
> > <app:navigate>
> >         <app:branch control="CANCEL" idref="cancel"/>
> >         <app:branch control="FINISH" idref="finish"/>
> >         <app:branch control="NEXT"   idref="page2"/>
> > </app:navigate>
> > 
> > <!-- Display the second page of the interation -->
> > <app:forward id="page2" name="Simple Wizard Page 2">
> > 
> > <!-- Process navigation input from the second page -->
> > <app:navigate>
> >         <app:branch control="CANCEL" idref="cancel"/>
> >         <app:branch control="FINISH" idref="finish"/>
> >         <app:branch control="NEXT"   idref="page3"/>
> >         <app:branch control="PREV"   idref="page1"/>
> > </app:navigate>
> > 
> > <!-- Display the third page of the interation -->
> > <app:forward id="page3" name="Simple Wizard Page 3">
> > 
> > <!-- Process navigation input from the third page -->
> > <app:navigate>
> >         <app:branch control="CANCEL" idref="cancel"/>
> >         <app:branch control="FINISH" idref="finish"/>
> >         <app:branch control="PREV"   idref="page2"/>
> > </app:navigate>
> > 
> > <!-- Process the FINISH navigation control as appropriate -->
> > <xxx:yyy id="finish" .../>
> > <core:goto name="Main Menu"/>
> > 
> > <!-- Process the CANCEL navigation control as appropriate -->
> > <xxx:yyy id="cancel" .../>
> > <core:goto name="Main Menu"/>
> > 
> > </flow:workflow>
> > 
> > So there would be "app" and "ctx" APIs, or interfaces, in the Commons,
> > and there could be default implementations of a Web, J2EE, and whatever
> > context. But no working implementation of the "app" API. It would be up
> > to developers working with Turbine, Struts, Barracuda, or whatever to
> > implement the "app" API for a given framework. But the code implementing
> > the "ctx" and "core" elements would be shared. We might even want to
> > make "core" a general API too, and then offer a Java implementation of
> > that, just to keep our options open.
> > 
> > Properly done, it could mean that the workflow scripts for some
> > frameworks could be shared. Though, I imagine there may eventually be
> > framework-specific elements too.
> > 
> > I'd also suggest that the custom tags, which would apparently be part of
> > the "app" layer, be part of the Commons distribution, so that another
> > JSP framework does not have to reimplement these.  Whatever resources
> > that are needed can be exposed in the ServletContext under known names.
> > 
> > Since there does seem to be interest in doing this as a Commons project
> > (it has my +1 and I even may still be a Committer here and everything
> > ;-), we might keep the initial discussion in the Commons, and refactor
> > the Struts proposal as a Commons proposal, using neutral language.
> > 
> > (I could help with that part of it today ...)
> > 
> > -- Ted Husted, Husted dot Com, Fairport NY USA.
> > -- Custom Software ~ Technical Services.
> > -- Tel +1 716 737-3463
> > -- http://www.husted.com/about/struts/
> 

Reply via email to