Workflow Reqs and Design

Document created by resplin Employee on Jun 6, 2015Last modified by alfresco-archivist on Aug 31, 2016
Version 5Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Design Document
Workflow

Back to Workflow.



This document describes requirements for advanced workflow within Alfresco and the approach taken during the v1.4 development cycle.

Focus is given to providing support for user-oriented processes that are managed within the context of a Repository e.g. review and approve, translation, publish.  It is envisioned that BPEL will still provide support for enterprise-wide process management where content management is a piece of the process i.e. CRM/Accounting/Contract process.  The former we can call Content Management Process, the latter Content Integration Process (note: any other terms that better describe - I'm not married to these).

Workflow User interface design is not included in this document.  Focus is given to use-cases and services required.




Table of Contents


Alfresco v1.3 'Simple' Workflow


Since its inception, Alfresco has supported 'simple' workflow, which is aimed at providing an end-user with the capability to define their own content-oriented workflows.  It's simple in that each workflow definition is restricted to a single state.  Multiple states are represented by loosely tying multiple workflow definitions.  Loose coupling is achieved by attaching a workflow definition to a folder and a workflow instance to a content item.  A Content item is moved or copied to a new folder at which point a new workflow instance is attached based on the workflow definition of the folder.  A workflow definition is unaware of other 'related' workflow definitions.

Limitations:


  • unable to create multi-state workflow definitions
  • restricted to one or two exit transitions (approve, reject)
  • reliance on folder structure for multi-stage workflow and action triggering
  • no notion of a task or assignment

To resolve these limitations, Alfresco will integrate a best-of-breed BPM engine into its core.  This will extend the Alfresco platform to include support for bespoke content-oriented processes.


BPM Requirements (Alfresco v1.4 onwards)


The difference between 'simple' and advanced workflow can be described as...


Types of Workflow


Any kind of workflow should be supported by advanced workflow, but to bring some focus, the following examples must be catered for:

1) Simple multi-step Review (requested by several customers)

For example, send this document to Fred for review and once approved notify me.

TODO: document this process

2) WCM Press Release Publishing Workflow

As described by Kevin Cochrane.

TODO: reference documented process

3) Alfresco Test 'Approval' Workflow

Example/Test demonstrating the commonly requested features of Workflow.

4) Alfresco 'simple' workflow

Must be able to express existing simple workflows in the language of the integrated BPM engine.


BPM Engine Requirements


Basically, the basis of any BPM engine is a state machine.  However, to support the above workflows, the following is specifically required:


  • Multiple workflow states
  • Any number of state transitions
  • Manual (user) or automatic (system) signalling of transitions
  • Process context (e.g. content item/s to process)
  • Execution of logic (content operations) on transitions, state entry / exit
  • Asynchronous execution of logic (i.e. execute transform in another thread/process)
  • Forks and Joins
  • Decisions
  • Timed signals (for reminders, or indication of issue)
  • Long running process (i.e. persistence of state and multi-transaction transitions)
  • Process composition (one process invokes another)
  • Tasks / Task List (bonus - this could be supported outside of WF engine)
  • Resource assignment (bonus - this could be supported outside of WF engine)
  • Permissions to protect state transitions (bonus)

Workflow User Interactions


A user of a Content Management application requires the following interactions with an advanced workflow.

Via the CM Client (i.e. Web Browser):


  1. Start workflow
    1. Select from list of pre-defined workflows
    2. Attach resources (documents, folders etc)
    3. Assign users to workflow
      1. determine which assignments (workflow roles) are required
      2. manual assignment of people to workflow roles
      3. automatic assignment of people to workflow roles via Space roles
      4. mixture of automatic and manual adjustment
  2. List my tasks (what have I got to do?)
  3. List tasks I could assign to myself (for task assigned to group/pool)
  4. Perform task
    1. View associated task resources (if any)
    2. Link to appropriate Client user interface for completing task (Could)
    3. Change task state
    4. Mark task done (or other outcome)
  5. Look back (trail of steps up to my task assigment)
  6. Look forward (why hasn't something happened yet?)
  7. Re-assign task to someone else
  8. Take ownership of task
  9. Cancel/abort workflow I've started ??

Via a notification medium (e.g. E-mail, IM):


  1. Receive notification of new task
  2. Navigate to Web Client UI for task
  3. View associated resources (Could)
  4. Mark task done (or other outcome) (Could)

Workflow Processes


Parameters


Each advanced (in-flight) workflow instance may require one or more of the following parameters:


  • Content attachment
    • Folder containing content items (non-versioned, or specific version)
    • Content Item (non-versioned, or specific version)
  • Arbitrary collection of Content attachments
  • Initiating User / System process
  • Task assignments (in terms of workflow roles/swimlanes)
    • Single user or group allowed
  • Context (e.g. Space, Folder, Project, Web Site)
  • plus any workflow specific parameters

It should be possible to ask a workflow definition for a description of its parameters, in particular, the task assignments required.

Parameter values are provided at process initiation time.  Some parameters may be discarded after initiation once they have been used to determine some dynamic aspect of the workflow.  However, the majority of them will be carried through the lifetime of the process instance.

In some scenarios, it is useful to encapsulate process parameter values so they can be re-used.  For example, a Space Template may be associated with a particular Workflow definiton with 'canned' parameter values (known as a Workflow Template?).  Users within that Space may initiate the Workflow without having to detour from the defaults i.e. the best practice is encapsulated.


Context


Each process instance will carry variables which can be read or set during the lifetime of the instance, in particular, when evaluating Decisions and Managing Content.  Most BPM engines offer this facility, but not all support scoped process variables for parallel execution paths.

It is important to distinguish between process context and content state.  The Repository already does an excellent job of maintaining content state and will continue to do so in an in-flight process.  The process instance is solely responsible for maintaining process context i.e. the variables it's carrying and the position(s) within the process.  During the execution of a process instance, content state may be modified or read as actions are performed against content, or process decisions are driven by content.

At some point in the future, the notion of Content Lifecycle may be formalised in the Content Repository.  Even without formalised Content Lifecycle, a poor man's version can be implemented using aspects, property setting and categorisation.


Content-driven Decisions


A process flow (or execution) may be driven by the context (e.g. content, folder, space, user) attached to the process.  Most workflow engines provide a fork or decision node where the condition is written using a native expression language.  However, as Alfresco utilises JavaScript for managing logic, it would be ideal to allow JavaScript to determine decisions points within the process and for that JavaScript to have access to the following:


  • Process parameters & context
  • Current task

as simple objects for easy navigation and examination.


Managing Content


During an in-flight process, it may be necessary to perform operations against content in the repository.  There shouldn't be a restriction on what operations may be performed.

Alfresco already provides the notion of an Action which encapsulates a re-usable repository operation.  Configuration of Actions into a process should be made very easy, whereas, configuration of arbitrary logic should be possible.  Actions already support parameters, so a mechanism to map process state to action parameters is required.

Operating against the Repository requires prior authentication.  Operations are performed on state entry & exit or on transition, which happen when starting a workflow and signalling continuation of a workflow.  The authenticated identity for an operation may come from:


  • current authentication (whoever issued the signal)
  • an explicit user (including system user) for the Action as defined in the process
  • current user for the path in the process

The transaction of the operation is either:


  • the transaction that triggered the workflow signal: in this case the operation and transition from workflow state to another is atomic
  • a new transaction if the operation itself is asynchronous, or the workflow state entry is asynchronous

A process must be sensitive to errors which may occur during an operation.  It should be possible to handle an error by triggering an explicit error transition which moves the process to a state for recovery or even end.  When an error occurs, the content operation must exhibit ACID behaviour in that it will be rolled-back, but the process will still move to the next state, allowing for the issue to be (system or user) resolved.


Workflow Association


Not all Workflows are applicable to all situations.

Within an Alfresco Space it may be necessary to specify which Workflows are applicable.  This could simply be a list, or more specifically, a list of Content Type to Workflow mappings.

In particular, it is often required to implicitly start a workflow when:


  1. Content of a given type is created or updated
  2. Content within a given folder is created or updated

In WCM, during Web Space setup, it is necessary to support the linking of Form, Presentation Template and Workflow.  In this case, it's not just the selection of the Workflow, but also the configuration of it i.e. the setting of its parameter values.  The saving of Workflow parameter values is required so each subsequent use of a Form kicks off the same associated & configured Workflow.


Tasks


Advanced workflows, in particular, the ones we're focusing on above, require user intervention in the form of tasks.


Task Definition


  • Task type e.g. review / translate
  • Task message i.e. description of what to do - template based.
  • Task parameter definitions (e.g. content to review)
  • Task outcomes (exit transitions)
  • Task custom property definitions
  • Task notification e-mail template

Task Instance


  • Parameter values (e.g. content attachment)
  • Due date
  • Status (started, completed)
  • Outcome (exit transition)
  • Exit date
  • Priority
  • Reminder
  • Assignee/Owner
  • Context (e.g. Space, Folder, Project, Web Site) (optional)
  • Workflow instance (optional)

Viewing and acting upon a task will require a user interface that is sensitive to the task in hand.  In particular the viewing / setting of task specific state, parameters and for selecting a task outcome.  It should be possible for a task to describe itself.


Task Assignment


Outside-in approach:

The workflow definition specifies the task assignment slots to be filled.  On start of the workflow, users or groups are assigned to the slots.  The mapping takes place outside of the workflow and may be driven by any means whether manual or automatic e.g. map users & groups via their assigned role in the initiating Alfresco space.

Inside-out approach:

Within a workflow definition, logic is provided to 'dynamically' assign users and groups to task assignment slots.  The logic may rely on context provided to the process (e.g. query roles on space provided to process) or any other external mechanism.


Group Support (v2.0)


  • Assign Group(s) to task

For each distinct person in group(s), allocate task to person (i.e. one task instance per person).

NOTE: Make use of ForEachFork to iterate over group members


  • Assign Group(s) to pooled task

Group(s) as a whole are assigned to task.  Someone in group takes ownership of task.


  • Supporting requirements
  1. Pooled task dashlet (list tasks that you may take ownership of i.e. assigned to a group you belong to)
    1. Take ownership action
    2. Pooled task dialog: Return to Pool action
  2. Support for modelling (single/multiple) group associations in workflow model
  3. Select Group(s) in Task Dialog UI
  4. Javascript API
    1. retrieval of groups
    2. retrieval of members/people in group (direct, recursive)
    3. TODO: check - is it possible to build collections in javascript?

User Notification


A User may be notified when:


  • A task is assigned to them (on creation, or re-assigned from someone else)
  • A reminder is triggered
  • Ad-hoc points in the Workflow process

Task Context


Tasks are created within a context, where the context is typically:


  • Project, Team, Web
  • Personal

Task Lists


Need to perform the following queries:


  • List tasks assigned to me
    • Filtered by context
    • Filtered by task type
  • List pooled tasks associated to me

Ad-hoc Tasks


Q: Do we need to support the notion of tasks outside workflow?

There's no reason why tasks cannot be managed outside of workflow.  For example, a user may wish to manage their day-to-day activities.  This could be supported by wrapping each task in a single workflow, but I think we want to provide task management as an independent service of the Alfresco platform.  We could support integration with an external task system (e.g. Outlook) behind this service.

The following additional user actions may be supported for task management:


  • Create Task
  • Delete Task

Agree?

Kevin Cochrane: More I think about your task proposal, the more I warm up to it. Another reason:  outside of the context of WCM (which can tend to be very process-centric because you are distributing information so broadly for public consumption), the notion of simple tasks a user can create in the context of their workspace as a TO DO list for a given project is an absolute must.  For WCM, it's a nice to have convenience that becomes a particularly acute need in the context of a simple intranet publishing op, but for collab activities I imagine it's a hard requirement.


Content Lifecycle


TODO: Expand on formalising the notion of Content Lifecycle...


  • A state machine for lifecycle
  • Promote/Demote
  • Actions on transitions?
  • Relationship to Workflow

Permissions


TODO: Expand on this...


  1. Who can start the workflow?
  2. Who can move the process forward?
  3. Who executes operations as a side effect of moving the process forward?

Administration


Processes require care and attention.  To simplify management of processes, the following features are required:


  • process definition (role: developer familiar with xml and repository concepts)
    • via a graphical designer
    • or xml
  • process definition registration
    • support for simultaneous multiple versions of a process definition
  • auditing i.e. logging of workflow instances
    • also useful for looking back / forward in process
    • hook into standard Alfresco auditing capability
  • export & import
    • of process definitions
    • of process instances
    • of tasks
  • installation deployment options
    • BPM engine located in Repository server process
    • BPM engine located in independent BPM server

BPEL


TODO: Expand this...

BPEL4WS Business Process Execution Language (for Web Services)

WSIF Web Services Invocation Framework


BPM Design


Choice of BPM Engine


Starting from Alfresco Community 3.4.e, Alfresco provides both  the Activiti BPMN 2.0 BPM engine and the original JBoss jBPM engine . You can discover more on the Activiti  implementation in Workflow_with_Activiti.
The rest of this page discusses Workflow using the original jBPM engine:-

Provides:


  • all workflow concepts needed
  • pluggable integration points (e.g. transaction, db connnection)
  • hibernate persistence by default
  • comes with 'good enough' graphical process designer (eclipse plug-in)
  • lgpl license

High-level Components


500px


  • Allow plug-in of BPM Engine via SPIs for Workflow Component & Task Component
  • BPM Engine Registry keeps track of registered BPM Engines
  • A Workflow Component & Task Component Adaptor for jBPM is provided
  • Extend jBPM process definition language to include:
    • invocation of Alfresco Action
    • invocation of Alfresco JavaScript
    • simple access to Alfresco objects in process / task context
  • Workflow Service provides API for client
    • interacts with the registered BPM engines for implementation
    • remote versions of this service may be rendered (via RMI, SOAP)
  • Alfresco Command Servlet extension allows URL signalling of workflow transitions

Design Decision Update


Originally, the thought was to manage Tasks within Alfresco where we provide a loose coupling between workflow transitions (managed by the BPM engine) and the creation/assignments of tasks in Alfresco.

However, after much deliberation, a change of mind has been made.  Workflow Tasks will now be managed by the BPM engine.  The reasoning is that all process information is encapsulated in one place allowing complete reporting, tracking and load balancing.  Also, Alfresco can concentrate on content management focusing on the touch points between content management and process management.

Benefits of this route:


  1. 1 + 1 = 3 i.e. Alfresco + jBPM communities = great content-oriented processes
  2. Allows for Alfresco to participate in cross-application business processes (future)
  3. Full Workflow administration and reporting

Workflow Definition


An Alfresco Workflow definition is made up of four parts:


  • Process Definition which defines the steps and behaviour of the Workflow
  • Task Model which defines the data collected & presented during the Workflow
  • Workflow User Interface Configuration which defines the Task dialogs of the Workflow
  • Workflow Resource Bundle which defines localised user interface messages

none|500px|Workflow Definition

Splitting the workflow definition this way allows for an external & pluggable BPM engine to provide the Process Definition (the first of which is jPDL of jBPM).  Each BPM engine will provide its own set of features and process definition language.

Fronting the Process Definition is a Task Model which is understood by clients of the Workflow i.e. those who wish to initiate a workflow, move a workflow forward, or interact with workflow tasks.  It provides the public contract and is independent of BPM engine.  As a public contract, an attempt to maintain compatibility between Alfresco versions will be made.


Task Model


The Workflow contract is described as an Alfresco Dictionary Model.  Each task within a workflow is represented as a Dictionary Type where task properties and associations are modelled as Type properties and associations.  An Alfresco client may use the Type definition to drive the collection of data required for the task.  In fact, the Alfresco Web Client infrastructure (e.g. dialog and wizard framework) already provides Type-driven UI allowing for easy construction and configuration of Task dialogs.

Workflow parameters required to start a workflow are also modelled as a Task.  Each workflow may have the notion of a special 'Start' Task which is created upon launch of the workflow. The properties and associations of the 'Start' Task represent the workflow parameters to collect.  Again, the same UI configuration may be used for initiating a workflow.  Another benefit of having a 'Start' task is it appears in the initiators completed task list providing a point for determining the status of the workflow or cancelling it.

Examples workflow models follow:


With these models, Web Client configuration can include:


  • Configuring the properties to collect within the 'Start' Task Dialog
  • Completely override the 'Start' Task Dialog for each Workflow
  • Configuring the properties to view / edit within a Task Dialog
  • Completely override the View / Edit Task Dialog for each Task

Workflow (Start Task) Templates


Given that each Workflow maps to a Dictionary Model, it is possible to create Workflow Task nodes within the Alfresco Repository.  For example, with the ReviewApproveWorkflow.xml model registered, a node of type 'wf:submitReviewTask' can be persisted and for each of its properties a value may be stored.  Essentially, this provides a Workflow Start Task Template node.  Enough information is stored to know which Workflow to start and the values to use for its parameters.  This is particularly useful when used in conjunction with Space Templates and also useful for WCM Web Space setups.


Workflow Localisation


The approach used for Dictionary Model localisation will also be used for Workflow & Task Models.  Task localisation uses the same message keys as Type.

However, the following workflow specific keys are also supported:


  • <workflow_prefix>_<workflow_name>.workflow.[title|description]
  • <workflow_prefix>_<workflow_name>.node.<node_name>.[title|description]
  • <workflow_prefix>_<workflow_name>.node.<node_name>.transition.<transition_name>.[title|description]
  • <workflow_prefix>_<workflow_name>.task.<task_prefix>_<task_name>.[title|description]

where:


  • <workflow_prefix> is the workflow model namespace prefix
  • <workflow_name> is the workflow name
  • <node_name> is the name of a node within the workflow
  • <transition_name> is the name of a node transition within the workflow
  • <task_prefix> is the task namespace prefix
  • <task_name> is the task name
  • <transition_name> is the workflow transition name

For example:



wf_review.workflow.title=Review & Approve
wf_review.workflow.description=Send documents for approval
wf_review.node.start.title=Start
wf_review.node.start.transition.review.title=Review
wf_review.node.review.title=Review

# for tasks, either rely on Type definition for task
wf_workflowmodel.type.wf_submitReviewTask.title=Review
# or, provide explicit title and description
wf_review.task.wf_submitReviewTask.title=Review

jBPM Process Designer


jBPM provides a (Eclipse hosted) GUI for defining workflow processes.  One feature of the designer is the ability to deploy a definition to a server.  Alfresco will provide the necessary support to allow the jBPM Process Designer to deploy directly to Alfresco.


Alfresco Management & Deployment of Process Definitions


The following type will be added to the Content Model to support the storage of process definitions within the Alfresco Repository.  Process definitions are then under content management.

Process Definition - Content Type for storing a Process Definition.

<type name='bpm:processdefinition'>
  <title>Process Definition</title>
  <parent>cm:content</parent>
  <properties>
     <property name='bpm:engineId'>
        <type>d:text</text>
     </property>
  </properties>
</type>

Against this type, an Alfresco 'Deploy/Publish' action could be registered allowing for the deployment of Process Definitions within the Alfresco Web Client.

Process Definitions may live in the Data Dictionary Folder, but are only of use to 'Process Designers' who design and edit them, so the visibility will be restricted.


Workflow Package


Content-oriented workflows operate against Content!

The content routed through an Alfresco workflow is stored in the Alfresco Repository.  To represent the package of content (where zero, one or more pieces of content may be in play at any point) during the workflow, a new concept of a Workflow Package is introduced.

A Workflow Package is simply a container of content items which itself is stored in the Repository.  Initially, Alfresco will support a single Workflow Package per workflow instance meaning that all active tasks within a workflow instance have access to the same package.  For example, in a review process many people (i.e. many tasks) may be involved in the approval of the same content.  Other tasks may involve the collection of new content, in which case, it's added to the package.

The container may be one of folder, versioned folder or layered folder to which a workflow package aspect is applied.  The aspect keeps track of the association back to the workflow plus any other important workflow information that may want to be searched against in the repository.  A running list of comments about the package may also be persisted in the Repository as an attached Discussion Thread.

Within each Task, the set of Workflow Package actions may be defined:


  • Add item
  • Remove item
  • View item
  • Checkout item
  • ...

The definition is simply an Alfresco Web Client named 'Action Group'.  Each workflow task instance supports an Action Group property which may be set at process definition time, or at process instance run-time.


Workflow APIs


Workflow Model


none|500px|Workflow Service API Data Model


WorkflowDefinition



/** Workflow Definition unique id */
public String id;

/** Workflow Definition name */
public String name;

/** Workflow Definition version */
public String version;

/** Workflow Definition Title (Localised) */
public String title;

/** Workflow Definition Description (Localised) */
public String description;

/** Task Definition for Workflow Start Task (Optional) */
public WorkflowTaskDefinition startTaskDefinition;

WorkflowInstance



/** Workflow Instance unique id */
public String id;

/** Workflow Instance description */
public String description;

/** Is this Workflow instance still 'in-flight' or has it completed? */
public boolean active;

/** Initiator (cm:person) - null if System initiated */
public NodeRef initiator;

/** Workflow Start Date */
public Date startDate;

/** Workflow End Date */
public Date endDate;

/** Workflow Package */
public NodeRef workflowPackage;

/** Workflow Context */
public NodeRef context;

/** Workflow Definition */
public WorkflowDefinition definition;

WorkflowNode



/** Workflow Node Name */
public String name;

/** Workflow Node Title (Localised) */
public String title;

/** Workflow Node Description (Localised) */
public String description;

/** Type of the Workflow Node (typically this is BPM engine specific - informational only */
public String type;

/** Does this Workflow Node represent human interaction? */
public boolean isTaskNode;

/** The transitions leaving this node (or null, if none) */
public WorkflowTransition[] transitions;

WorkflowTransition



/** Transition Id */
public String id;

/** Transition Title (Localised) */
public String title;

/** Transition Description (Localised) */
public String description;

/** Is this the default transition */
public boolean isDefault;

WorkflowPath




/** Unique id of Workflow Path */
public String id;

/** Workflow Instance this path is part of */
public WorkflowInstance instance;

/** The Workflow Node the path is at */
public WorkflowNode node;

/** Is the path still active? */
public boolean active;


WorkflowTask



/** Unique id of Task */
public String id;

/** Task Name */
public String name;

/** Task Title (Localised) */
public String title;

/** Task Description (Localised) */
public String description;

/** Task State */
public WorkflowTaskState state;

/** Workflow path this Task is associated with */
public WorkflowPath path;

/** Task Definition */
public WorkflowTaskDefinition definition;

/** Task Properties as described by Task Definition */
public Map<QName, Serializable> properties;

WorkflowTaskDefinition




/** Unique id of Workflow Task Definition */
public String id;

/** Workflow Node this task created from */
public WorkflowNode node;

/** Task Metadata */
public TypeDefinition metadata;


WorkflowTimer




/** Timer Id */
public String id;

/** Transition Name */
public String name;

/** Associated Workflow Path */
public WorkflowPath path;

/** Associated Workflow Task (if any) */
public WorkflowTask task;

/** Due Date */
public Date dueDate;


Identifiers


workflowName


Identifies a workflow definition.  The format is as follows:

bpmengine$definitionId

bpmengine = identifier of BPM engine (specified in registration of engine)

definitionId = BPM engine specific identifier for a given workflow definition

e.g. jbpm$wf:review


workflowInstance


Identifies an 'in-flight' workflow (i.e. an instance of a workflow definition). This identifier is tied to the BPM engine supporting the workflow.  The format is as follows:

bpmengine$instanceId

where:

bpmengine = identifier of BPM engine (specified in registration of engine)

instance = BPM engine specific identifer for a given workflow instance

e.g. jbpm$1234


workflowPath


Identifies a position within an 'in-flight' workflow (i.e. a workflow path within a workflow instance). This identifier is tied to the BPM engine supporting the workflow.

bpmengine$position

where:

bpmengine = identifier of BPM engine (specified in registration of engine)

position = BPM engine specific identifer for a given workflow instance

e.g. jbpm$1234-@ represents the root path of jBPM workflow instance 1234


Workflow Service


Client facing API for interacting with Alfresco Workflows and Tasks




//
// Workflow Definition Management
//

/**
* Deploy a Workflow Definition to the Alfresco Repository
*
* @param  engineId  the bpm engine id
* @param  workflowDefinition  the workflow definition
* @param  mimetype  the mimetype of the workflow definition
* @return  workflow deployment descriptor
*/
@Auditable(parameters = {'engineId', 'workflowDefinition', 'mimetype'})
public WorkflowDeployment deployDefinition(String engineId, InputStream workflowDefinition, String mimetype);

/**
* Deploy a Workflow Definition to the Alfresco Repository
*
* Note: The specified content object must be of type bpm:workflowdefinition.
*       This type describes for which BPM engine the definition is appropriate.
*
* @param workflowDefinition  the content object containing the definition
* @return  workflow deployment descriptor
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {'workflowDefinition'})
public WorkflowDeployment deployDefinition(NodeRef workflowDefinition);

/**
* Is the specified Workflow Definition already deployed?
*
* Note: the notion of 'already deployed' may differ between bpm engines. For example,
*       different versions of the same process may be considered equal.
*      
* @param  engineId  the bpm engine id
* @param  workflowDefinition  the definition to check
* @param  mimetype  the mimetype of the definition
* @return  true => already deployed
*/
@Auditable(parameters = {'engineId', 'workflowDefinition', 'mimetype'})
public boolean isDefinitionDeployed(String engineId, InputStream workflowDefinition, String mimetype);

/**
* Undeploy an exisiting Workflow Definition
*
* @param workflowDefinitionId  the id of the definition to undeploy
*/
@Auditable(parameters = {'workflowDefinitionId'})
public void undeployDefinition(String workflowDefinitionId);

/**
* Gets latest deployed Workflow Definitions
*
* @return  the latest deployed workflow definitions
*/
@Auditable
public List<WorkflowDefinition> getDefinitions();

/**
* Gets all deployed Workflow Definitions (with all previous versions)
*
* @return  the deployed (and previous) workflow definitions
*/
@Auditable
public List<WorkflowDefinition> getAllDefinitions();
   
/**
* Gets a Workflow Definition by unique Id
*
* @param workflowDefinitionId  the workflow definition id
* @return  the deployed workflow definition (or null if not found)
*/
@Auditable(parameters = {'workflowDefinitionId'})
public WorkflowDefinition getDefinitionById(String workflowDefinitionId);

/**
* Gets the latest Workflow Definition by unique name
*
* @param workflowName  workflow name e.g. jbpm$wf:review
* @return  the deployed workflow definition (or null if not found)
*/
@Auditable(parameters = {'workflowName'})
public WorkflowDefinition getDefinitionByName(String workflowName);

/**
* Gets all (including previous) Workflow Definitions for the given unique name
*
* @param workflowName  workflow name e.g. jbpm$wf:review
* @return  the deployed workflow definition (or null if not found)
*/
@Auditable(parameters = {'workflowName'})
public List<WorkflowDefinition> getAllDefinitionsByName(String workflowName);

/**
* Gets a graphical view of the Workflow Definition
*
* @param workflowDefinitionId  the workflow definition id
* @return  image view of the workflow definition
*/
@Auditable(parameters = {'workflowDefinitionId'})
public byte[] getDefinitionImage(String workflowDefinitionId);


//
// Workflow Instance Management
//


/**
* Start a Workflow Instance
*
* @param workflowDefinitionId  the workflow definition id
* @param parameters  the initial set of parameters used to populate the 'Start Task' properties
* @return  the initial workflow path
*/
@Auditable(parameters = {'workflowDefinitionId', 'parameters'})
public WorkflowPath startWorkflow(String workflowDefinitionId, Map<QName, Serializable> parameters);

/**
* Start a Workflow Instance from an existing 'Start Task' template node held in the
* Repository.  The node must be of the Type as described in the Workflow Definition.
*
* @param templateDefinition  the node representing the Start Task properties
* @return  the initial workflow path
*/
@Auditable(parameters = {'templateDefinition'})
public WorkflowPath startWorkflowFromTemplate(NodeRef templateDefinition);

/**
* Gets all 'in-flight' workflow instances of the specified Workflow Definition
*
* @param workflowDefinitionId  the workflow definition id
* @return  the list of 'in-flight' workflow instances
*/
@Auditable(parameters = {'workflowDefinitionId'})
public List<WorkflowInstance> getActiveWorkflows(String workflowDefinitionId);

/**
* Gets a specific workflow instances
*
* @param workflowId  the id of the workflow to retrieve
* @return  the workflow instance (or null if not found)
*/
@Auditable(parameters = {'workflowId'})
public WorkflowInstance getWorkflowById(String workflowId);

/**
* Gets all Paths for the specified Workflow instance
*
* @param workflowId  workflow instance id
* @return  the list of workflow paths
*/
@Auditable(parameters = {'workflowId'})
public List<WorkflowPath> getWorkflowPaths(String workflowId);

/**
* Gets the properties associated with the specified path (and parent paths)
*
* @param pathId  workflow path id
* @return  map of path properties
*/
@Auditable(parameters = {'pathId'})
public Map<QName, Serializable> getPathProperties(String pathId);

/**
* Cancel an 'in-flight' Workflow instance
*
* @param workflowId  the workflow instance to cancel
* @return  an updated representation of the workflow instance
*/
@Auditable(parameters = {'workflowId'})
public WorkflowInstance cancelWorkflow(String workflowId);

/**
* Delete an 'in-flight' Workflow instance
*
* NOTE: This will force a delete, meaning that the workflow instance may not
*       go through all the appropriate cancel events.
*
* @param workflowId  the workflow instance to cancel
* @return  an updated representation of the workflow instance
*/
@Auditable(parameters = {'workflowId'})
public WorkflowInstance deleteWorkflow(String workflowId);

/**
* Signal the transition from one Workflow Node to another
*
* @param pathId  the workflow path to signal on
* @param transition  the transition to follow (or null, for the default transition)
* @return  the updated workflow path
*/
@Auditable(parameters = {'pathId', 'transitionId'})
public WorkflowPath signal(String pathId, String transitionId);

/**
* Fire custom event against specified path
*
* @param pathId  the workflow path to fire event on
* @param event  name of event
* @return  workflow path (it may have been updated as a result of firing the event
*/
@Auditable(parameters = {'pathId', 'event'})
public WorkflowPath fireEvent(String pathId, String event);

/**
* Gets all Tasks associated with the specified path
*
* @param pathId  the path id
* @return  the list of associated tasks
*/
@Auditable(parameters = {'pathId'})
public List<WorkflowTask> getTasksForWorkflowPath(String pathId);


//
// Workflow Timer Management
//

/**
* Gets all active timers for the specified workflow
*
* @return  the list of active timers
*/
@Auditable(parameters = {'workflowId'})
public List<WorkflowTimer> getTimers(String workflowId);


//
// Task Management
//

/**
* Gets a Task by unique Id
*
* @param taskId  the task id
* @return  the task (or null, if not found)
*/
@Auditable(parameters = {'taskId'})
public WorkflowTask getTaskById(String taskId);

/**
* Gets all tasks assigned to the specified authority
*
* @param authority  the authority
* @param state  filter by specified workflow task state
* @return  the list of assigned tasks
*/
@Auditable(parameters = {'authority', 'state'})
public List<WorkflowTask> getAssignedTasks(String authority, WorkflowTaskState state);

/**
* Gets the pooled tasks available to the specified authority
*
* @param authority   the authority
* @return  the list of pooled tasks
*/
@Auditable(parameters = {'authority'})
public List<WorkflowTask> getPooledTasks(String authority);

/**
* Query for tasks
*
* @param query  the filter by which tasks are queried
* @return  the list of tasks matching the specified query
*/
@Auditable(parameters = {'query'})
public List<WorkflowTask> queryTasks(WorkflowTaskQuery query);

/**
* Update the Properties and Associations of a Task
*
* @param taskId  the task id to update
* @param properties  the map of properties to set on the task (or null, if none to set)
* @param add  the map of items to associate with the task (or null, if none to add)
* @param remove  the map of items to dis-associate with the task (or null, if none to remove)
* @return  the update task
*/
@Auditable(parameters = {'taskId', 'properties', 'add', 'remove'})
public WorkflowTask updateTask(String taskId, Map<QName, Serializable> properties, Map<NodeRef>> add, Map<NodeRef>> remove);

/**
* End the Task (i.e. complete the task)
*
* @param taskId  the task id to end
* @param transition  the task transition to take on completion (or null, for the default transition)
* @return  the updated task
*/
@Auditable(parameters = {'taskId', 'transitionId'})
public WorkflowTask endTask(String taskId, String transitionId);


//
// Package Management
//

/**
* Create a Workflow Package (a container of content to route through the Workflow).
*
* If an existing container is supplied, it's supplemented with the workflow package aspect.
*
* @param container  (optional) a pre-created container (e.g. folder, versioned folder or layered folder)
* @return  the workflow package
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {'container'})
public NodeRef createPackage(NodeRef container);

/**
* Gets the Workflows that act upon the specified Repository content.

* @param packageItem  the repository content item to get workflows for
* @param active  true => active workflows only, false => completed workflows only
* @return  list of workflows which act upon the specified content
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {'packageItem', 'active'})
public List<WorkflowInstance> getWorkflowsForContent(NodeRef packageItem, boolean active);

Workflow Component SPI


SPI to be implemented by a BPM Engine that provides Workflow management.



//
// Workflow Definition Support
//


/**
* Deploy a Workflow Definition
*
* @param workflowDefinition  the content object containing the definition
* @param mimetype (optional)  the mime type of the workflow definition
* @return workflow deployment descriptor
*/
public WorkflowDeployment deployDefinition(InputStream workflowDefinition, String mimetype);

/**
* Is the specified Workflow Definition already deployed?
*
* Note: the notion of 'already deployed' may differ between bpm engines. For example,
*       different versions of the same process may be considered equal.
*      
* @param workflowDefinition  the definition to check
* @param mimetype  the mimetype of the definition
* @return  true => already deployed
*/
public boolean isDefinitionDeployed(InputStream workflowDefinition, String mimetype);

/**
* Undeploy an exisiting Workflow Definition
*
* TODO: Determine behaviour when 'in-flight' workflow instances exist

* @param workflowDefinitionId  the id of the definition to undeploy
*/
public void undeployDefinition(String workflowDefinitionId);

/**
* Gets all deployed Workflow Definitions
*
* @return  the deployed workflow definitions
*/
public List<WorkflowDefinition> getDefinitions();

/**
* Gets a Workflow Definition by unique Id
*
* @param workflowDefinitionId  the workflow definition id
* @return  the deployed workflow definition
*/
public WorkflowDefinition getDefinitionById(String workflowDefinitionId);

/**
* Gets a Workflow Definition by unique name
*
* @param workflowName  workflow name e.g. jbpm$wf:review
* @return  the deployed workflow definition
*/
public WorkflowDefinition getDefinitionByName(String workflowName);


//
// Workflow Instance Support
//


/**
* Start a Workflow Instance
*
* @param workflowDefinitionId  the workflow definition id
* @param parameters  the initial set of parameters used to populate the 'Start Task' properties
* @return  the initial workflow path
*/
public WorkflowPath startWorkflow(String workflowDefinitionId, Map<QName, Serializable> parameters);

/**
* Gets all 'in-flight' workflow instances of the specified Workflow Definition
*
* @param workflowDefinitionId  the workflow definition id
* @return  the list of 'in-flight' workflow instances
*/
public List<WorkflowInstance> getActiveWorkflows(String workflowDefinitionId);

/**
* Gets a specific workflow instances
*
* @param workflowId  the id of the workflow to retrieve
* @return  the workflow instance
*/
public WorkflowInstance getWorkflowById(String workflowId);

/**
* Gets all Paths for the specified Workflow instance
*
* @param workflowId  workflow instance id
* @return  the list of workflow paths
*/
public List<WorkflowPath> getWorkflowPaths(String workflowId);

/**
* Cancel an 'in-flight' Workflow instance
*
* @param workflowId  the workflow instance to cancel
* @return  an updated representation of the workflow instance
*/
public WorkflowInstance cancelWorkflow(String workflowId);

/**
* Signal the transition from one Workflow Node to another within an 'in-flight'
* process.
*
* @param pathId  the workflow path to signal on
* @param transition  the transition to follow (or null, for the default transition)
* @return  the updated workflow path
*/
public WorkflowPath signal(String pathId, String transitionId);

/**
* Gets all Tasks associated with the specified path
*
* @param pathId  the path id
* @return  the list of associated tasks
*/   
public List<WorkflowTask> getTasksForWorkflowPath(String pathId);

Task Component SPI


SPI to be implemented by a BPM Engine that provides Task management.



/**
* Gets a Task by unique Id
*
* @param taskId  the task id
* @return  the task
*/
public WorkflowTask getTaskById(String taskId);

/**
* Gets all tasks assigned to the specified authority
*
* @param authority  the authority
* @param state  filter by specified workflow task state
* @return  the list of assigned tasks
*/
public List<WorkflowTask> getAssignedTasks(String authority, WorkflowTaskState state);

/**
* Gets the pooled tasks available to the specified authority
*
* @param authority   the authority
* @return  the list of pooled tasks
*/
public List<WorkflowTask> getPooledTasks(List<String> authorities);

/**
* Update the Properties and Associations of a Task
*
* @param taskId  the task id to update
* @param properties  the map of properties to set on the task (or null, if none to set)
* @param add  the map of items to associate with the task (or null, if none to add)
* @param remove  the map of items to dis-associate with the task (or null, if none to remove)
* @return  the update task
*/
public WorkflowTask updateTask(String taskId, Map<QName, Serializable> properties, Map<NodeRef>> add, Map<NodeRef>> remove);

/**
* Start the specified Task
*
* Note: this is an optional task operation.  It may be used to track
*       when work started on a task as well as resume a suspended task.
*
* @param taskId  the task to start
* @return  the updated task
*/
public WorkflowTask startTask(String taskId);

/**
* Suspend the specified Task
*
* @param taskId
* @return  the update task
*/
public WorkflowTask suspendTask(String taskId);

/**
* End the Task (i.e. complete the task)
*
* @param taskId  the task id to end
* @param transition  the task transition to take on completion (or null, for the default transition)
* @return  the updated task
*/   
public WorkflowTask endTask(String taskId, String transitionId);




Usage examples


You can find an example of how to deal with those API by looking at the source code of class WorkflowInterpretor.


jBPM Extensions


jBPM has several hook points for integrating custom behaviour into a Workflow.  To start with, extensions will take the form a jBPM ActionHandler.

It seems it's also possible to plug-in new node types (with their own xml declaration) into jBPM, so alternative xml representations may also be available.  TODO: Document...


Alfresco Script


An ActionHandler that invokes an Alfresco Script.




<action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
  <script>
     <expression>
        // some alfresco javascript
     </expression>
     <variable name='passedInValue' access='read'/>
     <variable name='passedOutValue' access='write'/>
  </script>
</action>

Or

<action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
  <script>
     // some alfresco javascript
  </script>
</action>

The script is passed all process variables and executed, unless the <variables> element is provided, in which case, specific variables may be passed in and out.  Node References will be converted to Node objects for simple Alfresco Node navigation and operation.  The standard jBPM objects accessible in BeanShell are also accessible in Alfresco JavaScript e.g. executionContext, taskInstace...

jBPM already provides scripting support in the form of BeanShell.  It provides access to workflow context in the form of some pre-defined variables (Java Objects).  The Alfresco script will also have access to the same variables.  In return, BeanShell scripts will have access to Alfresco Node objects.


Alfresco Actions


Alfresco actions are now invocable via Alfresco JavaScript.  Please see JavaScript_API#Actions_API.


Start Workflow Action


The action named 'start-workflow' is used to automate the start of advanced workflows e.g. from rules.  It supports the following parameters:


workflowName : name of the workflow in the form of <engineId>$<workflowName> e.g. jbpm$wf:review

endStartTask (optional) - true (default) | false : specifies whether the start task is automatically ended

startTaskTransition (optional) : specifies the start task transition to take.  If one is not specified, the default transition is taken.

All other parameters are passed to the start task of the workflow.  Namespaced parameters such as bpm:workflowDueDate are allowed.

The 'actioned' upon Repository node is placed into the workflow package of the started workflow.

e.g.

The following Rule script may be used to initiate the 'Review & Approve' workflow for content that is acted upon by the rule.  The script assigns the workflow to the person who kicked off the rule, and sets a due date to 7 days in the future.

var workflow = actions.create('start-workflow');
workflow.parameters.workflowName = 'jbpm$wf:review';
workflow.parameters['bpm:assignee'] = person;
var futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 7);
workflow.parameters['bpm:workflowDueDate'] = futureDate;
workflow.execute(document);

Task URL Command Processor


Refer to Task Command Processor.


Plan (Tasks & Estimates)


Workflow Plan - for historical reasons only.


Questions


russ:
What does it take to describe a task (task prototype)?


  • Description
  • Core states, part of task interface
  • Task Domain states
  • Transitions/Outcomes
  • Parameters
  • Required resources
  • Published events

If it possible for a task / or even the runtime to publish certain event like task started, suspended, continued, stopped, failed, completed; it be comes natural to support operations such as sending email notifications or much richer functionalities.  Other processes may subscribe for events allowing them to be separately described and loosely coupled via asynchronous messaging paradigm.  In terms of implementation it is consistant with almost any BPM because evented process is just like any other process the only differnce is how it was started.

Challanges can be auditing the results of a process which published an event which may or may not initiate another process: it can be difficult to say let me see the history of this process and all of the effects it created.

What are tasks described in? Is this tied to the implementation?  JDML is a job description markup targeted at Grid but incorporates some of the concepts discussed by this document.

Outcomes