Guido Casper wrote:
Johan Stuyts wrote:
A summary of my interpretation of the workflow thread is available on the wiki (http://wiki.cocoondev.org/Wiki.jsp?page=Workflow). Please verify my findings and I'm sorry if I misinterpreted something.
Thanks a lot for your effort, Johan.
I don't want this workflow thing being stalled and somehow feel like being my turn.
So my suggestion is to settle on the interface I proposed earlier: -setState(doc, requestedState, user, optionalObject) -getState(doc) -getAllowedActions(docURI, user)
Perhaps some more research how this matches with existing workflow APIs might be good to allow a better integration of (standardized) workflow management systems.
One API (though relatively complex but well supported by many vendors) is: http://www.wfmc.org/standards/docs/if2v20.pdf
I think this leaves enough space for different implementations (and is not carved in stone anyway).
"doc" might be an implementation of WorkflowObject with (at least)
get/setState(), getType() and getURI() methods and "user" might be an
implementation of WorkflowUser with getUsername() and getRole()
(allowing the details of getting this information being abstracted away
from the workflow engine (if desired)). Note that in most cases (like
myself's :-) this might require not much more than having the objects you might already have implement WorkflowUser/WorkflowObject.
I can offer to rework my approach a little (making it more generic) and put it into scratchpad. Be aware that it will however require at least 3 (to make up a meaningful sample) non-reusable (although tiny) Java components.
Although being simple (which might be ideal for discussing and settling
on an interface anyway) I believe the state pattern provides various extension points (like for nested states, XML descriptions or user-defined workflows), which might provoke further ideas where my mind left.
Just a few examples. Looking at my earlier config like this:
<workflow-manager> <state name="edited" class="EditedState"> <entering-action class="EditedAction"/> <leaving-action class="LeaveEditedAction"/> </state> <state name="reviewed" class="ReviewedState"> <entering-action class="ReviewedAction"/> </state> <state name="published" class="PublishedState"> <entering-action class="PublishedAction"/> </state> </workflow-manager>
If you need multiple workflows that simply might become
<workflow-manager> <workflow id="wf1"> <state name="edited" class="EditedState"> <entering-action class="EditedAction"/> <leaving-action class="LeaveEditedAction"/> </state> <state name="reviewed" class="ReviewedState"> <entering-action class="ReviewedAction"/> </state> <state name="published" class="PublishedState"> <entering-action class="PublishedAction"/> </state> </workflow> <workflow id="wf2"> ... </workflow> </workflow-manager>
easily allowing the config being externalized in separate files and allowing objects to dynamically change the workflow.
Interesting. This really looks a bit like XPDL (although much simplified). Just do the following substitutions: * <workflow-manager> -> <WorkflowProcesses> * <workflow> -> <WorkflowProcess> * <state> -> <Activity> * @class -> <Implementation> * userRole -> <ParticipantType> (from your example below)
Here's an XPDL example from the WfMC: http://www.wfmc.org/standards/docs/xpdl_sample/sample%20workflow%20process.xpdl http://www.wfmc.org/standards/XPDL.htm
One difference is, that your approach specifies classes for the implementation of states and transitions which might be more flexible but tied to java implementations.
Wouldn't it be better to start with a suitable subset of existing workflow definition standards (see http://wiki.cocoondev.org/Wiki.jsp?page=Workflow for examples) instead of defining just another proprietary one?
If you prefer more reusable Java code and your custom logic being interpreted rather than compiled that might be made into something like:
<workflow-manager> <state name="edited" class="GroovableState"> <groovy-code> switch (requestedState) { case "reviewed": allow = true; break; case "published": if (userRole == "editor") { allow = true; break; } default: allow = false; } </groovy-code> <entering-action class="EditedAction"/> <leaving-action class="LeaveEditedAction"/> </state> <!-- or even more terse --> <state name="reviewed" class="GroovableState"> <allow-enter state="published"> <groovy-code> if (userRole == "editor") { allow = true;} else {allow = false} </groovy-code> </allow-enter> <!-- DefaultAction just setting new state --> <entering-action class="DefaultAction"/> </state> <state name="published" class="PublishedState"> <entering-action class="PublishedAction"/> </state> </workflow-manager>
How much easier can it get?
Perhaps, reuse existing definition languages (see above)?
Note that I don't want to throw another technology into the mix (and
there are certainly people on this list being able to integrate Rhino
equally easily), just want to show how flexible the state pattern is.
And basically that's a major point, it gives you a very flexible approach while allowing you to continue working with what you are already familiar with.
WDYT?
I think we're slowly going into the right direction.
The hard thing is possible to find a good compromise for simple workflows (with simple implementation/definition) and complex workflows (with enough expressivenes/extensibility of the definition language).
Guido
Andreas
