org.apache.wiki.workflow
Class Workflow

java.lang.Object
  extended by org.apache.wiki.workflow.Workflow
All Implemented Interfaces:
Serializable

public class Workflow
extends Object
implements Serializable

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 getCurrentState()) will be one of the following:

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 start()), calling classes should specify the first Step by executing the setFirstStep(Step) method. Additional Steps can be chained by invoking the first step's Step.addSuccessor(Outcome, Step) 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 currently executing Step can be obtained by getCurrentStep(). The actor for the current Step is returned by 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:

See Also:
Serialized Form

Field Summary
static int ABORTED
          State value: Workflow aborted before completion.
static int COMPLETED
          State value: Workflow completed all Steps without errors.
static int CREATED
          State value: Workflow instantiated, but not started.
static int ID_NOT_SET
          ID value: the workflow ID has not been set.
static int RUNNING
          State value: Workflow started, and is running.
static Date TIME_NOT_SET
          Time value: the start or end time has not been set.
static int WAITING
          State value: Workflow paused, typically because a Step returned an Outcome that doesn't signify "completion."
 
Constructor Summary
Workflow(String messageKey, Principal owner)
          Constructs a new Workflow object with a supplied message key, owner Principal, and undefined unique identifier ID_NOT_SET.
 
Method Summary
 void abort()
          Aborts the Workflow by setting the current Step's Outcome to Outcome.STEP_ABORT, and the Workflow's overall state to ABORTED.
 void addMessageArgument(Serializable obj)
          Appends a message argument object to the array returned by getMessageArguments().
 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.
protected  void complete()
          Protected helper method that changes the Workflow's state to COMPLETED and sets the current Step to null.
protected  void fireEvent(int type)
          Fires a WorkflowEvent of the provided type to all registered listeners.
 Object getAttribute(String attr)
          Retrieves a named Object associated with this Workflow.
 Principal getCurrentActor()
          Returns the actor Principal responsible for the current Step.
 int getCurrentState()
          Returns the workflow state: CREATED, RUNNING, WAITING, COMPLETED or ABORTED.
 Step getCurrentStep()
          Returns the current Step, or null if the workflow has not started or already completed.
 Date getEndTime()
          The end time for this Workflow, expressed as a system time number.
 List getHistory()
          Returns a Step history for this Workflow as a List, chronologically, from the first Step to the currently executing one.
 int getId()
          Returns the unique identifier for this Workflow.
 Serializable[] getMessageArguments()
           Returns an array of message arguments, used by MessageFormat to create localized messages.
 String getMessageKey()
          Returns an i18n message key for the name of this workflow; for example, workflow.saveWikiPage.
 Principal getOwner()
          The owner Principal on whose behalf this Workflow is being executed; that is, the user who created the workflow.
 Step getPreviousStep()
          Convenience method that returns the predecessor of the current Step.
 Date getStartTime()
          The start time for this Workflow, expressed as a system time number.
 WorkflowManager getWorkflowManager()
          Returns the WorkflowManager that contains this Workflow.
 boolean isAborted()
          Returns true if the workflow had been previously aborted.
 boolean isCompleted()
          Determines whether this Workflow is completed; that is, if it has no additional Steps to perform.
 boolean isStarted()
          Determines whether this Workflow has started; that is, its start() method has been executed.
protected  Step previousStep(Step step)
          Protected method that returns the predecessor for a supplied Step.
protected  void processCurrentStep()
          Protected method that processes the current Step by calling Step.execute().
 void removeWikiEventListener(WikiEventListener listener)
          Un-registers a WikiEventListener with this instance.
 void restart()
          Restarts the Workflow from the WAITING state and puts it into the RUNNING state again.
 void setAttribute(String attr, Object obj)
          Temporarily associates an object with this Workflow, as a named attribute, for the duration of workflow execution.
 void setFirstStep(Step step)
          Sets the first Step for this Workflow, which will be executed immediately after the start() method executes.
 void setId(int id)
          Sets the unique identifier for this Workflow.
 void setWorkflowManager(WorkflowManager manager)
          Sets the WorkflowManager that contains this Workflow.
 void start()
          Starts the Workflow and sets the state to RUNNING.
 void waitstate()
          Sets the Workflow in the WAITING state.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

TIME_NOT_SET

public static final Date TIME_NOT_SET
Time value: the start or end time has not been set.


ID_NOT_SET

public static final int ID_NOT_SET
ID value: the workflow ID has not been set.

See Also:
Constant Field Values

COMPLETED

public static final int COMPLETED
State value: Workflow completed all Steps without errors.

See Also:
Constant Field Values

ABORTED

public static final int ABORTED
State value: Workflow aborted before completion.

See Also:
Constant Field Values

WAITING

public static final int WAITING
State value: Workflow paused, typically because a Step returned an Outcome that doesn't signify "completion."

See Also:
Constant Field Values

RUNNING

public static final int RUNNING
State value: Workflow started, and is running.

See Also:
Constant Field Values

CREATED

public static final int CREATED
State value: Workflow instantiated, but not started.

See Also:
Constant Field Values
Constructor Detail

Workflow

public Workflow(String messageKey,
                Principal owner)
Constructs a new Workflow object with a supplied message key, owner Principal, and undefined unique identifier ID_NOT_SET. Once instantiated the Workflow is considered to be in the CREATED state; a caller must explicitly invoke the start() method to begin processing.

Parameters:
messageKey - the message key used to construct a localized workflow name, such as workflow.saveWikiPage
owner - the Principal who owns the Workflow. Typically, this is the user who created and submitted it
Method Detail

abort

public final void abort()
Aborts the Workflow by setting the current Step's Outcome to Outcome.STEP_ABORT, and the Workflow's overall state to 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 cleanup() method to flush retained objects. If the Workflow had been previously aborted, this method throws an IllegalStateException.


addMessageArgument

public final void addMessageArgument(Serializable obj)
Appends a message argument object to the array returned by getMessageArguments(). The object must be an type used by the 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

getCurrentActor

public final Principal getCurrentActor()
Returns the actor Principal responsible for the current Step. If there is no current Step, this method returns null.

Returns:
the current actor

getCurrentState

public final int getCurrentState()
Returns the workflow state: CREATED, RUNNING, WAITING, COMPLETED or ABORTED.

Returns:
the workflow state

getCurrentStep

public final Step getCurrentStep()
Returns the current Step, or null if the workflow has not started or already completed.

Returns:
the current step

getAttribute

public final Object getAttribute(String attr)
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
Returns:
the value

getEndTime

public final Date getEndTime()
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 TIME_NOT_SET.

Returns:
the end time

getId

public final int getId()
Returns the unique identifier for this Workflow. If not set, this method returns ID_NOT_SET (0).

Returns:
the unique identifier

getMessageArguments

public final Serializable[] getMessageArguments()

Returns an array of message arguments, used by MessageFormat to create localized messages. The first two array elements will always be these:

Workflow and Step subclasses are free to append items to this collection with addMessageArgument(Serializable).

Returns:
the array of message arguments

getMessageKey

public final String getMessageKey()
Returns an i18n message key for the name of this workflow; for example, workflow.saveWikiPage.

Returns:
the name

getOwner

public final Principal getOwner()
The owner Principal on whose behalf this Workflow is being executed; that is, the user who created the workflow.

Returns:
the name of the Principal who owns this workflow

getStartTime

public final Date getStartTime()
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 TIME_NOT_SET.

Returns:
the start time

getWorkflowManager

public final WorkflowManager getWorkflowManager()
Returns the WorkflowManager that contains this Workflow.

Returns:
the workflow manager

getHistory

public final List getHistory()
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.

Returns:
an array of Steps representing those that have executed, or are currently executing

isAborted

public final boolean isAborted()
Returns true if the workflow had been previously aborted.

Returns:
the result

isCompleted

public final boolean isCompleted()
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.

Returns:
true if the workflow has been started but has no more steps to perform; false if not.

isStarted

public final boolean isStarted()
Determines whether this Workflow has started; that is, its start() method has been executed.

Returns:
true if the workflow has been started; false if not.

getPreviousStep

public final Step getPreviousStep()
Convenience method that returns the predecessor of the current Step. This method simply examines the Workflow history and returns the second-to-last Step.

Returns:
the predecessor, or null if the first Step is currently executing

restart

public final void restart()
                   throws WikiException
Restarts the Workflow from the WAITING state and puts it into the 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 AbstractStep.execute() method throws an exception

setAttribute

public final void setAttribute(String attr,
                               Object obj)
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, although it should be serializable. Note that when the workflow completes or aborts, all attributes will be cleared.

Parameters:
attr - the attribute name
obj - the value

setFirstStep

public final void setFirstStep(Step step)
Sets the first Step for this Workflow, which will be executed immediately after the start() method executes. Note than the Step is not marked as the "current" step or added to the Workflow history until the start() method is called.

Parameters:
step - the first step for the workflow

setId

public final void setId(int id)
Sets the unique identifier for this Workflow.

Parameters:
id - the unique identifier

setWorkflowManager

public final void setWorkflowManager(WorkflowManager manager)
Sets the WorkflowManager that contains this Workflow.

Parameters:
manager - the workflow manager

start

public final void start()
                 throws WikiException
Starts the Workflow and sets the state to RUNNING. If the Workflow has already been started (or previously aborted), this method returns 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 Step's Step.start() method throws an exception of any kind

waitstate

public final void waitstate()
Sets the Workflow in the 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 restart() method.


cleanup

protected void cleanup()
Clears the attribute map and sets the current step field to null.


complete

protected final void complete()
Protected helper method that changes the Workflow's state to COMPLETED and sets the current Step to null. It calls the cleanup() method to flush retained objects. This method will no-op if it has previously been called.


previousStep

protected final Step previousStep(Step step)
Protected method that returns the predecessor for a supplied Step.

Parameters:
step - the Step for which the predecessor is requested
Returns:
its predecessor, or null if the first Step was supplied.

processCurrentStep

protected final void processCurrentStep()
                                 throws WikiException
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.start() method throws an exception of any kind

addWikiEventListener

public final void addWikiEventListener(WikiEventListener listener)
Registers a WikiEventListener with this instance. This is a convenience method.

Parameters:
listener - the event listener

removeWikiEventListener

public final void removeWikiEventListener(WikiEventListener listener)
Un-registers a WikiEventListener with this instance. This is a convenience method.

Parameters:
listener - the event listener

fireEvent

protected final void fireEvent(int type)
Fires a WorkflowEvent of the provided type to all registered listeners.

Parameters:
type - the event type to be fired
See Also:
WorkflowEvent


Copyright © {inceptionYear}-2014 The Apache Software Foundation. All rights reserved.