| java.lang.Object com.ecyrd.jspwiki.workflow.Workflow
Workflow | public class Workflow (Code) | |
Sequence of
Step objects linked together. Workflows are always
initialized with a message key that denotes the name of the Workflow, and a
Principal that represents its owner.
Workflow lifecycle
A Workflow's state (obtained by
Workflow.getCurrentState() ) will be one of the
following:
-
Workflow.CREATED : after the Workflow has been
instantiated, but before it has been started using the
Workflow.start() method.
-
Workflow.RUNNING : after the Workflow has been started
using the
Workflow.start() method, but before it has finished processing all
Steps. Note that a Workflow can only be started once; attempting to start it
again results in an IllegalStateException. Callers can place the Workflow
into the WAITING state by calling
Workflow.waitstate() .
-
Workflow.WAITING : when the Workflow has temporarily
paused, for example because of a pending Decision. Once the responsible actor
decides what to do, the caller can change the Workflow back to the RUNNING
state by calling the
Workflow.restart() method (this is done automatically by
the Decision class, for instance, when the
Decision.decide(Outcome) method is invoked)
-
Workflow.COMPLETED : after the Workflow has finished
processing all Steps, without errors.
-
Workflow.ABORTED : if a Step has elected to abort the
Workflow.
Steps and processing algorithm
Workflow Step objects can be of type
Decision ,
Task or other
Step subclasses. Decisions require user input, while Tasks do not. See the
Step class for more details.
After instantiating a new Workflow (but before telling it to
Workflow.start() ),
calling classes should specify the first Step by executing the
Workflow.setFirstStep(Step) method. Additional Steps can be chained by
invoking the first step's
Step.addSuccessor(OutcomeStep) method.
When a Workflow's start method is invoked, the Workflow
retrieves the first Step and processes it. This Step, and subsequent ones,
are processed as follows:
- The Step's
Step.start method executes, which sets the start
time.
- The Step's
Step.execute method is called to begin processing,
which will return an Outcome to indicate completion, continuation or errors:
-
Outcome.STEP_COMPLETE indicates that the execution method ran
without errors, and that the Step should be considered "completed."
-
Outcome.STEP_CONTINUE indicates that the execution method ran
without errors, but that the Step is not "complete" and should be put into
the WAITING state.
-
Outcome.STEP_ABORT indicates that the execution method
encountered errors, and should abort the Step and the Workflow as
a whole. When this happens, the Workflow will set the current Step's Outcome
to
Outcome.STEP_ABORT and invoke the Workflow's
Workflow.abort() method. The Step's processing errors, if any, can be retrieved by
Step.getErrors .
- The Outcome of the
execute method also affects what
happens next. Depending on the result (and assuming the Step did not abort),
the Workflow will either move on to the next Step or put the Workflow into
the
Workflow.WAITING state:
- If the Outcome denoted "completion" (i.e., its
Step.isCompleted method returns
true ) then the Step
is considered complete; the Workflow looks up the next Step by calling the
current Step's
Step.getSuccessor(Outcome) method. If
successor() returns a non-null Step, the
return value is marked as the current Step and added to the Workflow's Step
history. If successor() returns null , then the
Workflow has no more Steps and it enters the
Workflow.COMPLETED state.
- If the Outcome did not denote "completion" (i.e., its
Step.isCompleted method returns
false ), then the
Step still has further work to do. The Workflow enters the
Workflow.WAITING state and stops further processing until a caller restarts it.
The currently executing Step can be obtained by
Workflow.getCurrentStep() . The
actor for the current Step is returned by
Workflow.getCurrentActor() .
To provide flexibility for specific implementations, the Workflow class
provides two additional features that enable Workflow participants (i.e.,
Workflow subclasses and Step/Task/Decision subclasses) to share context and
state information. These two features are named attributes and
message arguments:
Example
Workflow Steps can be very powerful when linked together. JSPWiki provides
two abstract subclasses classes that you can use to build your own Workflows:
Tasks and Decisions. As noted, Tasks are Steps that execute without user
intervention, while Decisions require actors (aka Principals) to
take action. Decisions and Tasks can be mixed freely to produce some highly
elaborate branching structures.
Here is a simple case. For example, suppose you would like to create a
Workflow that (a) executes a initialization Task, (b) pauses to obtain an
approval Decision from a user in the Admin group, and if approved, (c)
executes a "finish" Task. Here's sample code that illustrates how to do it:
// Create workflow; owner is current user
1 Workflow workflow = new Workflow("workflow.myworkflow", context.getCurrentUser());
// Create custom initialization task
2 Step initTask = new InitTask(this);
// Create finish task
3 Step finishTask = new FinishTask(this);
// Create an intermediate decision step
4 Principal actor = new GroupPrincipal("Admin");
5 Step decision = new SimpleDecision(this, "decision.AdminDecision", actor);
// Hook the steps together
6 initTask.addSuccessor(Outcome.STEP_COMPLETE, decision);
7 decision.addSuccessor(Outcome.DECISION_APPROVE, finishTask);
// Set workflow's first step
8 workflow.setFirstStep(initTask);
Some comments on the source code:
- Line 1 instantiates the workflow with a sample message key and
designated owner Principal, in this case the current wiki user
- Lines 2 and 3 instantiate the custom Task subclasses, which contain the
business logic
- Line 4 creates the relevant GroupPrincipal for the
Admin
group, who will be the actor in the Decision step
- Line 5 creates the Decision step, passing the Workflow, sample message
key, and actor in the constructor
- Line 6 specifies that if the InitTask's Outcome signifies "normal
completion" (STEP_COMPLETE), the SimpleDecision step should be invoked next
- Line 7 specifies that if the actor (anyone possessing the
Admin GroupPrincipal) selects DECISION_APPROVE, the FinishTask
step should be invoked
- Line 8 adds the InitTask (and all of its successor Steps, nicely wired
together) to the workflow
author: Andrew Jaquith |
Field Summary | |
final public static int | ABORTED State value: Workflow aborted before completion. | final public static int | COMPLETED State value: Workflow completed all Steps without errors. | final public static int | CREATED State value: Workflow instantiated, but not started. | final public static int | ID_NOT_SET ID value: the workflow ID has not been set. | final public static int | RUNNING State value: Workflow started, and is running. | final public static Date | TIME_NOT_SET Time value: the start or end time has not been set. | final public static int | WAITING |
Method Summary | |
final public synchronized void | abort() Aborts the Workflow by setting the current Step's Outcome to
Outcome.STEP_ABORT , and the Workflow's overall state to
Workflow.ABORTED . | final public void | addMessageArgument(Object obj) Appends a message argument object to the array returned by
Workflow.getMessageArguments() . | final public synchronized void | addWikiEventListener(WikiEventListener listener) Registers a WikiEventListener with this instance. | protected void | cleanup() Clears the attribute map and sets the current step field to
null . | final protected synchronized void | complete() Protected helper method that changes the Workflow's state to
Workflow.COMPLETED and sets the current Step to null . | final protected void | fireEvent(int type) Fires a WorkflowEvent of the provided type to all registered listeners. | final public synchronized Object | getAttribute(String attr) Retrieves a named Object associated with this Workflow. | final public synchronized Principal | getCurrentActor() Returns the actor Principal responsible for the current Step. | final public int | getCurrentState() Returns the workflow state:
Workflow.CREATED ,
Workflow.RUNNING ,
Workflow.WAITING ,
Workflow.COMPLETED or
Workflow.ABORTED . | final public Step | getCurrentStep() Returns the current Step, or null if the workflow has not
started or already completed. | final public Date | getEndTime() The end time for this Workflow, expressed as a system time number. | final public List | getHistory() Returns a Step history for this Workflow as a List, chronologically, from the
first Step to the currently executing one. | final public synchronized int | getId() Returns the unique identifier for this Workflow. | final public Object[] | getMessageArguments()
Returns an array of message arguments, used by
java.text.MessageFormat to create localized messages. | final public String | getMessageKey() Returns an i18n message key for the name of this workflow; for example,
workflow.saveWikiPage . | final public Principal | getOwner() The owner Principal on whose behalf this Workflow is being executed; that
is, the user who created the workflow. | final public Step | getPreviousStep() Convenience method that returns the predecessor of the current Step. | final public Date | getStartTime() The start time for this Workflow, expressed as a system time number. | final public synchronized WorkflowManager | getWorkflowManager() Returns the WorkflowManager that contains this Workflow. | final public boolean | isAborted() Returns true if the workflow had been previously aborted. | final public synchronized boolean | isCompleted() Determines whether this Workflow is completed; that is, if it has no
additional Steps to perform. | final public boolean | isStarted() Determines whether this Workflow has started; that is, its
Workflow.start() method has been executed. | final protected Step | previousStep(Step step) Protected method that returns the predecessor for a supplied Step. | final protected void | processCurrentStep() Protected method that processes the current Step by calling
Step.execute . | final public synchronized void | removeWikiEventListener(WikiEventListener listener) Un-registers a WikiEventListener with this instance. | final public synchronized void | restart() Restarts the Workflow from the
Workflow.WAITING state and puts it into
the
Workflow.RUNNING state again. | final public synchronized void | setAttribute(String attr, Object obj) Temporarily associates an Object with this Workflow, as a named attribute, for the
duration of workflow execution. | final public synchronized void | setFirstStep(Step step) Sets the first Step for this Workflow, which will be executed immediately
after the
Workflow.start() method executes. | final public synchronized void | setId(int id) Sets the unique identifier for this Workflow. | final public synchronized void | setWorkflowManager(WorkflowManager manager) Sets the WorkflowManager that contains this Workflow. | final public synchronized void | start() Starts the Workflow and sets the state to
Workflow.RUNNING . | final public synchronized void | waitstate() Sets the Workflow in the
Workflow.WAITING state. |
ABORTED | final public static int ABORTED(Code) | | State value: Workflow aborted before completion.
|
COMPLETED | final public static int COMPLETED(Code) | | State value: Workflow completed all Steps without errors.
|
CREATED | final public static int CREATED(Code) | | State value: Workflow instantiated, but not started.
|
ID_NOT_SET | final public static int ID_NOT_SET(Code) | | ID value: the workflow ID has not been set.
|
RUNNING | final public static int RUNNING(Code) | | State value: Workflow started, and is running.
|
TIME_NOT_SET | final public static Date TIME_NOT_SET(Code) | | Time value: the start or end time has not been set.
|
WAITING | final public static int WAITING(Code) | | State value: Workflow paused, typically because a Step returned an
Outcome that doesn't signify "completion."
|
Workflow | public Workflow(String messageKey, Principal owner)(Code) | | Constructs a new Workflow object with a supplied message key, owner
Principal, and undefined unique identifier
Workflow.ID_NOT_SET . Once
instantiated the Workflow is considered to be in the
Workflow.CREATED state; a caller must explicitly invoke the
Workflow.start() method to
begin processing.
Parameters: messageKey - the message key used to construct a localized workflow name,such as workflow.saveWikiPage Parameters: owner - the Principal who owns the Workflow. Typically, this is theuser who created and submitted it |
abort | final public synchronized void abort()(Code) | | Aborts the Workflow by setting the current Step's Outcome to
Outcome.STEP_ABORT , and the Workflow's overall state to
Workflow.ABORTED . It also appends the aborted Step into the workflow
history, and sets the current step to null . If the Step
is a Decision, it is removed from the DecisionQueue. This method
can be called at any point in the lifecycle prior to completion, but it
cannot be called twice. It finishes by calling the
Workflow.cleanup() method to flush retained objects. If the Workflow had been previously
aborted, this method throws an IllegalStateException.
|
addMessageArgument | final public void addMessageArgument(Object obj)(Code) | | Appends a message argument object to the array returned by
Workflow.getMessageArguments() . The object must be an type
used by the
java.text.MessageFormat : String, Date, or Number
(BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short).
If the object is not of type String, Number or Date, this method throws
an IllegalArgumentException.
Parameters: obj - the object to add |
addWikiEventListener | final public synchronized void addWikiEventListener(WikiEventListener listener)(Code) | | Registers a WikiEventListener with this instance. This is a convenience
method.
Parameters: listener - the event listener |
cleanup | protected void cleanup()(Code) | | Clears the attribute map and sets the current step field to
null .
|
complete | final protected synchronized void complete()(Code) | | Protected helper method that changes the Workflow's state to
Workflow.COMPLETED and sets the current Step to null . It
calls the
Workflow.cleanup() method to flush retained objects.
This method will no-op if it has previously been called.
|
fireEvent | final protected void fireEvent(int type)(Code) | | Fires a WorkflowEvent of the provided type to all registered listeners.
See Also: com.ecyrd.jspwiki.event.WorkflowEvent Parameters: type - the event type to be fired |
getAttribute | final public synchronized Object getAttribute(String attr)(Code) | | Retrieves a named Object associated with this Workflow. If the Workflow
has completed or aborted, this method always returns null .
Parameters: attr - the name of the attribute the value |
getCurrentActor | final public synchronized Principal getCurrentActor()(Code) | | Returns the actor Principal responsible for the current Step. If there is
no current Step, this method returns null .
the current actor |
getCurrentStep | final public Step getCurrentStep()(Code) | | Returns the current Step, or null if the workflow has not
started or already completed.
the current step |
getEndTime | final public Date getEndTime()(Code) | | The end time for this Workflow, expressed as a system time number. This
value is equal to the end-time value returned by the final Step's
Step.getEndTime method, if the workflow has completed.
Otherwise, this method returns
Workflow.TIME_NOT_SET .
the end time |
getHistory | final public List getHistory()(Code) | | Returns a Step history for this Workflow as a List, chronologically, from the
first Step to the currently executing one. The first step is the first
item in the array. If the Workflow has not started, this method returns a
zero-length array.
an array of Steps representing those that have executed, or arecurrently executing |
getId | final public synchronized int getId()(Code) | | Returns the unique identifier for this Workflow. If not set, this method
returns ID_NOT_SET (
).
the unique identifier |
getMessageArguments | final public Object[] getMessageArguments()(Code) | |
Returns an array of message arguments, used by
java.text.MessageFormat to create localized messages. The first
two array elements will always be these:
- String representing the name of the workflow owner (i.e.,
Workflow.getOwner() )
- String representing the name of the current actor (i.e.,
Workflow.getCurrentActor() ).
If the current step is
null because the workflow hasn't started or has already
finished, the value of this argument will be a dash character (- )
Workflow and Step subclasses are free to append items to this collection
with
Workflow.addMessageArgument(Object) .
the array of message arguments |
getMessageKey | final public String getMessageKey()(Code) | | Returns an i18n message key for the name of this workflow; for example,
workflow.saveWikiPage .
the name |
getOwner | final public Principal getOwner()(Code) | | The owner Principal on whose behalf this Workflow is being executed; that
is, the user who created the workflow.
the name of the Principal who owns this workflow |
getPreviousStep | final public Step getPreviousStep()(Code) | | Convenience method that returns the predecessor of the current Step. This
method simply examines the Workflow history and returns the
second-to-last Step.
the predecessor, or null if the first Step iscurrently executing |
getStartTime | final public Date getStartTime()(Code) | | The start time for this Workflow, expressed as a system time number. This
value is equal to the start-time value returned by the first Step's
Step.getStartTime method, if the workflow has started already.
Otherwise, this method returns
Workflow.TIME_NOT_SET .
the start time |
getWorkflowManager | final public synchronized WorkflowManager getWorkflowManager()(Code) | | Returns the WorkflowManager that contains this Workflow.
the workflow manager |
isAborted | final public boolean isAborted()(Code) | | Returns true if the workflow had been previously aborted.
the result |
isCompleted | final public synchronized boolean isCompleted()(Code) | | Determines whether this Workflow is completed; that is, if it has no
additional Steps to perform. If the last Step in the workflow is
finished, this method will return true .
true if the workflow has been started but has nomore steps to perform; false if not. |
isStarted | final public boolean isStarted()(Code) | | Determines whether this Workflow has started; that is, its
Workflow.start() method has been executed.
true if the workflow has been started;false if not. |
previousStep | final protected Step previousStep(Step step)(Code) | | Protected method that returns the predecessor for a supplied Step.
Parameters: step - the Step for which the predecessor is requested its predecessor, or null if the first Step wassupplied. |
processCurrentStep | final protected void processCurrentStep() throws WikiException(Code) | | Protected method that processes the current Step by calling
Step.execute . If the execute throws an
exception, this method will propagate the exception immediately
to callers without aborting.
throws: WikiException - if the current Step's Step.startmethod throws an exception of any kind |
removeWikiEventListener | final public synchronized void removeWikiEventListener(WikiEventListener listener)(Code) | | Un-registers a WikiEventListener with this instance. This is a
convenience method.
Parameters: listener - the event listener |
restart | final public synchronized void restart() throws WikiException(Code) | | Restarts the Workflow from the
Workflow.WAITING state and puts it into
the
Workflow.RUNNING state again. If the Workflow had not previously been
paused, this method throws an IllegalStateException. If any of the
Steps in this Workflow throw a WikiException, the Workflow will abort
and propagate the exception to callers.
throws: WikiException - if the current task's Task.execute methodthrows an exception |
setAttribute | final public synchronized void setAttribute(String attr, Object obj)(Code) | | Temporarily associates an Object with this Workflow, as a named attribute, for the
duration of workflow execution. The passed Object can be anything required by
an executing Step. Note that when the workflow completes or aborts, all
attributes will be cleared.
Parameters: attr - the attribute name Parameters: obj - the value |
setFirstStep | final public synchronized void setFirstStep(Step step)(Code) | | Sets the first Step for this Workflow, which will be executed immediately
after the
Workflow.start() method executes. Note than the Step is not
marked as the "current" step or added to the Workflow history until the
Workflow.start() method is called.
Parameters: step - the first step for the workflow |
setId | final public synchronized void setId(int id)(Code) | | Sets the unique identifier for this Workflow.
Parameters: id - the unique identifier |
setWorkflowManager | final public synchronized void setWorkflowManager(WorkflowManager manager)(Code) | | Sets the WorkflowManager that contains this Workflow.
Parameters: manager - the workflow manager |
start | final public synchronized void start() throws WikiException(Code) | | Starts the Workflow and sets the state to
Workflow.RUNNING . If the
Workflow has already been started (or previously aborted), this method
returns an
. If any of the
Steps in this Workflow throw a WikiException, the Workflow will abort
and propagate the exception to callers.
throws: WikiException - if the current Step's Step.startmethod throws an exception of any kind |
waitstate | final public synchronized void waitstate()(Code) | | Sets the Workflow in the
Workflow.WAITING state. If the Workflow is not
running or has already been paused, this method throws an
IllegalStateException. Once paused, the Workflow can be un-paused by
executing the
Workflow.restart() method.
|
|
|