cancel
Showing results for 
Search instead for 
Did you mean: 
resplin
Elite Collaborator
Elite Collaborator

Obsolete Pages{{Obsolete}}

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



Workflow

Back to Workflow.

This document describes the steps for creating your own custom 'advanced' workflow by taking you through the start-to-end definition of a complete workflow - the 'Ad-hoc Task' workflow.

The following workflow requirements and design guide is also of assistance.




Table of Contents


Workflow Definition


An Alfresco 'advanced' workflow is comprised of the following artifacts...

none|450px|Workflow Definition


Process Definition :

The Process Definition describes the states (steps) and transitions (choices) of a workflow.  A step may be human- or system-based.  Human steps create and assign tasks to users.  System steps perform some kind of operation against the Alfresco repository.  Both are described and implemented in the Process Definition.

Alfresco embeds the JBoss jBPM process engine which itself provides the jPDL Process Definition Language.  jPDL is provided in one of the following formats:


  1. JBoss jBPM process archive (.par file)
  2. JBoss jBPM jPDL xml document (.xml file)
Task Model :

The Task Model provides a description for each of the human tasks in the workflow.  Each task description consists of:


  • Name and Title
  • Properties and Associations (e.g. the information attached to the task)

The description is used to drive the user interface dialog for viewing and managing the Task.

Alfresco provides a 'Data Dictionary' for describing types of object to store, view and edit.  This mechanism is also used to describe Workflow Tasks.


Web Client Configuration

Web Client configuration specifies the presentation of Tasks to the user in the Alfresco Web Client.

The configuration allows:


  • Control over which Task properties are displayed
  • Control over which Task properties are read-only and required
  • Control over how each Task property is rendered in the dialog
  • A custom dialog to be presented for each kind of Task in the Workflow

The Alfresco Web Client provides a sophisticated configuration mechanism for controlling dialogs.  This mechanism extends to the dialogs for workflow tasks.


Resource Bundle (optional)

A workflow resource bundle provides all the human-readable messages displayed in the user interface for managing the workflow.  Messages include Task titles, task property names, task choices etc.

Alfresco supports full localisation of its Web Client, including workflow.  Therefore, the same web client resource bundle configuration extends to workflow too.


Example Workflow - Ad-hoc Task


The example workflow referred to throughout this document is a very simple three step process.


  1. User A submits an 'ad-hoc' task to User B
  2. User B performs the task and completes it
  3. User A is informed of completion

To make things slightly more interesting we'll allow User A to specify on submission:


  • Description of what needs to be done
  • Due Date (optional)
  • Priority
  • Notify or don't notify of completion by e-mail

Step 1: Create the Process Definition


There are two ways of building the process definition (as dictated by JBoss jBPM):


  1. By hand i.e. create a jPDL xml document
  2. By designer i.e. use a tool to generate the jPDL xml document (or process archive)

JBoss jBPM reference documentation can be located at:


Hand developed jPDL XML Definition


Using an editor of your choice develop the jPDL xml document.  We'll start with the basic workflow structure:



<process-definition xmlns='urn:jbpm.org:jpdl-3.1' name='wf:adhoc'>

   <swimlane name='initiator'/>

   <start-state name='start'>
      <task name='wf:submitAdhocTask' swimlane='initiator'/>
      <transition name='' to='adhoc'/>
   </start-state>

   <swimlane name='assignee'/>
  
   <task-node name='adhoc'>
      <task name='wf:adhocTask' swimlane='assignee'/>
      <transition name='' to='completed'/>
   </task-node>
  
   <task-node name='completed'>
      <task name='wf:completedAdhocTask' swimlane='initiator'/>
      <transition name='' to='end'/>
   </task-node>
     
   <end-state name='end'/>
  
</process-definition>

The above definition describes the three steps of the adhoc task workflow.  Points to note:


  • There's always a start and end
  • The process definition name and task names are important; they're referenced later in other workflow definition artifacts
  • Swimlanes are used to declare workflow 'roles'
  • Tasks are associated with a swimlane

Process Designer developed Process Archive


An alternative way to develop the above jPDL document is via the JBoss jBPM Process Designer.


Installing JBoss jBPM Process Designer


You will need to work with jBPM 3, as jBPM 4 does not seem to be supported by Alfresco yet.


  1. Download the latest jbpm-jpdl-3.x (somehow version 3.2.6.SP1 is newer and works better than 3.3.1.GA).
  2. If you don't have Eclipse already, download it and install it.
  3. Execute the downloaded jBPM installer jar: java -jar jbpm-installer-3.*.jar
    • During the installation, select only jBPM3 standalone.
    • If it asks for a JBoss location and you don't have JBoss, just enter /tmp or equivalent. Don't pay attention to the database question.
  4. To install JBoss jBPM Process Designer, open Eclipse and follow these instructions.
    • The archive is in the designer directory where you installed jBPM3.
  5. When you are done, open Eclipse's preferences and open the JBoss JBPM section. Create a new 'Runtime location' pointing to the directory where you installed jBPM.
    • Set server name and port to where your Alfresco is (for instance localhost and 8080)
    • Set 'Server deployer' to /alfresco/jbpm/deployprocess.
  6. Now find activation.jar in your Alfresco install (usually in tomcat/webapps/alfresco/WEB-INF/lib) and copy it to jBPM3's lib directory.
  7. You can now create a new 'JBoss jBPM Process Project' in Eclipse, and a new 'JBoss jBPM Process Definition' within it.
    • Never close the diagram tab that appeared, because a bug may prevent it from being opened again (closing Eclipse is OK).

Using JBoss jBPM Process Designer


JBoss jBPM Process Designer is a graphical editor for developing workflows.  It's possible to switch between Diagram and XML views allowing synchronized development of jPDL XML either by hand-crafting XML manually, or having it generated via the Diagram.

The XML generated by the Diagram view generates a NullPointerException in WorkflowUtil.prepareTaskParams() because the start step has no task, so just insert <task name='wf:someRandomText'/> in the start node using the XML view.

none|700px|Workflow Service API Data Model


Deploying via JBoss jBPM Process Designer


JBoss jBPM Process Designer allows a process definition to be saved to a process archive file or deployed directly to an existing server.  Alfresco has provided support to allow deployment directly to Alfresco.


  1. For releases V3.2 SP2, V3.3 SP2 and later, enable the JBPM Deploy Process Servlet by adding this to alfresco-global.properties. Note that this is not recommended in a production environment as it allows unauthenticated deployment of new workflows.
    system.workflow.deployservlet.enabled=true

  2. Start or restart the Alfresco server
  3. From the Deployment Tab enter:
    1. Server Name = machine name where Alfresco is installed
    2. Server Port = port number assigned to Alfresco (default: 8080)
    3. Server Deployer = /alfresco/jbpm/deployprocess
  4. Press Test Connection...
  5. If all OK, press Deploy Process Archive...

If deployed successfully, the process definition is now available for use by Alfresco.  Please note, there is no need to restart the Alfresco server in order to activate the new deployed process definition.  This allows quick turn-around testing whilst developing new process definitions via the JBoss jBPM Process Designer.


Manually deploying a jPDL XML file or Process Archive


Process definitions can be configured into Alfresco so they are deployed whenever Alfresco starts.

The Spring bean 'workflowDeployer' provides deployment of Process Definitions.  It may be used in conjunction with Alfresco's configuration extension mechanism to deploy custom made workflows.



<bean id='myworkflows.workflowBootstrap' parent='workflowDeployer'>
   <property name='workflowDefinitions'>
      <list>
         <props>
            <prop key='engineId'>jbpm</prop>
            <prop key='location'>alfresco/workflow/adhoc_processdefinition.xml</prop>
            <prop key='mimetype'>text/xml</prop>
         </props>
      </list>
   </property>
</bean>

The bean accepts a list of workflow descriptions to deploy.  Each workflow description consists of the following properties:


engineId :  The embedded process engine to deploy to.  Note: v1.4 onwards, this must be jbpm

location : The classpath location of the process definition file.  Note: JBoss jBPM process definitions may be deployed from a Process Archive or jPDL XML file.  If following the standard configuration extension mechanism, the location of the process definition is likely to be something like alfresco/extension/workflow/xxx_processdefinition.xml.

mimetype : The format of process definition file.  One of either text/xml for jPDL XML files, or application/zip for jBPM Process Archive files.  If not specified, the default is application/zip.

redeploy (true | false) : Force deployment of the process definition if it is already deployed.  This is useful when developing and testing a workflow.  Each time the Alfresco  server starts the process definition is redeployed and a new version made.  For production environments, it is recommended this value is set to false.  If not specified, the default is false.

Redeploying a Process Definition


The process definition is versioned and kept kept alive to allow the existing 'in-progress' tasks to continue executing with their version of the process definition until they are completed.   In fact, the workflow definition is parsed and put into the alfresco jbpm database tables.

You can redeploy a process definition to create a new version of the process definition which will be used for new instances of your workflow tasks.

There are various options to re-deploy an existing process definition:


  1. The Workflow Console
  2. You can set the redeploy flag in the process definition and reboot alfresco.
  3. JBoss jBPM Process Designer has options to allow redeployment.

Step 2: Create the Task Model


For each Task in the process definition (as defined by <task> elements in jPDL) it is possible to associate a Task description.  The description specifies the information that may be attached to a Task i.e. properties (name and datatype) and associations (name and type of associated object).  A user may view and edit this information in the Task dialog within the Alfresco Web Client.

The Task Model is expressed as a Content Model as supported by the Data Dictionary.  To create a Task Model:


  1. Create a new Content Model for the Process Definition
  2. Create a Type for each Task
  3. Within each Type, describe the Properties and Associations (information) required for that Task

For the Adhoc Workflow Tasks, we can define the following Content Model:

<model name='wf:workflowmodel' xmlns='http://www.alfresco.org/model/dictionary/1.0'>

  <imports>
     <import uri='http://www.alfresco.org/model/dictionary/1.0' prefix='d'/>
     <import uri='http://www.alfresco.org/model/bpm/1.0' prefix='bpm'/>
  </imports>

  <namespaces>
     <namespace uri='http://www.alfresco.org/model/workflow/1.0' prefix='wf'/>
  </namespaces>
     
  <types>




     wf:submitAdhocTask'>
        <parent>bpm:startTask</parent>
        
        <properties>
           <property name='wf:notifyMe'>
              <type>d:boolean</type>
              <default>false</default>
           </property>

        </properties>

        <mandatory-aspects>
           <aspect>bpm:assignee</aspect>
        </mandatory-aspects>
     </type>

     wf:adhocTask'>
        <parent>bpm:workflowTask</parent>
     </type>

     wf:completedAdhocTask'>
        <parent>bpm:workflowTask</parent>
     </type>
     
  </types>
  
</model>

The full expressive power of the Content Model may be used to describe Tasks.  For example, property data types, constraints and default values may be assigned.  The associated Task Dialogs are driven by these definitions.

Also, if there's commonality across the tasks, sub-typing or aspects may be used to encapsulate the common information requirements.

The type name in the Content Model must correspond with the task name as defined in the process definition.

The above model defines:


  • A start task named 'wf:submitAdhocTask'.
    • This task defines the properties to be collected when the workflow is started.  In this case, the properties are workflow description, priority and due date (all from bpm:startTask) and 'wf:notifyMe'.
    • This task also includes the aspect 'bpm:assignee'.  This allows the collection of an assignee (a single person) in the start task dialog.
  • Workflow tasks 'wf:adhocTask' and 'wf:completedAdhocTask'.
    • These tasks do not define anything extra over the basic 'bpm:workflowTask'.

Common Task Model


Alfresco provides a pre-registered Content Model for describing the common attributes of all Tasks.  These include:


  1. Task Id
  2. Start Date
  3. Due Date
  4. Completion Date
  5. Priority
  6. Status
  7. Outcome (i.e. which choice was made on completion)
  8. Workflow Package (i.e. the content routed through the Workflow)
  9. Context (i.e. the Alfresco space within which the workflow was initiated)
  10. ...

The above information (and more) is defined in the 'bpm:businessprocessmodel' Model.  This model is located in the config file alfresco/model/bpmModel.xml.
Within this model, the two most important type definitions are called 'bpm:workflowTask' and 'bpm:startTask'.  Custom workflow task definitions must derive (explicitly or implicitly) from either one of these types.  Note: Start Tasks are explained below.

The base Task model may be referred to in your own Content Model as follows:



   <imports>
      <import uri='http://www.alfresco.org/model/bpm/1.0' prefix='bpm'/>
   </imports>

You may have noticed the Adhoc Workflow Task Model defined above only defines a single property called 'wf:notifyMe'.  What about due date, assignee?  They are all inherited from the basic task definitions.


The Start Task


There's a special task known as the Start Task which is assigned to the Initiator of the workflow.  It's used to collect the information (i.e. the workflow parameters) required for the workflow to proceed.  Within the Alfresco Web Client, the Start Task is presented as a single page within the Start Workflow Wizard upon selection of the workflow to start.  The page (as with all other Task dialogs) is driven by the Task Definition.

Within the Process Definition (i.e. jPDL), the Start Task is the one defined within the <start-state>.  The Start Task description in the Task Model must derive from 'bpm:startTask'.

Often a Start Task will collect the participants (people, groups) who are to play a role within the workflow.  To allow this, the following pre-defined aspects are provided which may be attached to the start task definition:


  • bpm:assignee collect a single person to play a role
  • bpm:assignees collect one or more people to play a role
  • bpm:groupAssignee collect a single group to play a role (v2.0 onwards)
  • bpm:groupAssignees collect a one or more groups to play a role (v2.0 onwards)

Custom aspects may be added to collect any arbitrary number of people / groups.


Workflow Package Actions


Alfresco Workflows generally work against Content held in the Alfresco Repository.  A Workflow Package is used to hold the content that's routed through the workflow.  Content within the package may be viewed, edited, or removed.  Content may also be added to the Workflow package.

However, not all Workflow Package operations are applicable to all Tasks.  For example, a review task may only allow view and edit.

The Alfresco Web Client supports the notion of 'Action Groups' i.e. a named group of UI Actions.  Each task is allocated Action Groups allowing control over which UI Actions are available on the Workflow Package whilst in the Web Client dialog of that Task.  This is achieved by specifying a default value for the following Task properties in the Task Model:

bpm:packageActionGroup'>
  <type>d:text</type>
  <default>add_package_item_actions</default>
</property>

bpm:packageItemActionGroup'>
  <type>d:text</type>
  <default>edit_package_item_actions</default>
</property>

Out-of-box, the following Action Groups are available for Workflow Packages:


read_package_item_actions : allow viewing of package items
edit_package_item_actions : above + allow modification (edit, checkout, ...) of package items
edit_and_remove_package_item_actions : above + allow removal of package items
remove_package_item_actions : allow removal (but not modification) of package items
add_package_item_actions : allow addition of new package items

They are all defined in the config file alfresco/web-client-config-workflow-actions.xml which provides the definitive list of actions for each Action Group.  Support for custom Action Groups is provided if the out-of-the-box definitions do not suit.


Deploying the Task Model


A workflow task model may be deployed using the 'Workflow Deployer' bean (as described in
Deploying a Process Definition).

<bean id='myworkflows.workflowBootstrap' parent='workflowDeployer'>
  <property name='workflowDefinitions'>
     ...
  </property>
  models'>
    <list>
      <value>alfresco/workflow/adhocModel.xml</value>
    </list>
  </property>
</bean>

Alternatively, the Task Model is just a Content Model, so may be deployed like any other Content Model.  Refer to Deploying Content Models.

An example configuration snippet follows:

<bean id='adhocWorkflow.dictionaryBootstrap' parent='dictionaryModelBootstrap' depends-on='dictionaryBootstrap'>
  <property name='models'>
     <list>
        <value>alfresco/model/adhocTaskModel.xml</value>
     </list>
  </property>
</bean>

NOTE: I've experienced a problem when using the dictionaryBootstrap for my custom workflow model as shown above. The problem was that I could not extend types in the wcmwf namespace. When I switched to the workflowBootstrap bean, it worked fine.


Out-of-the-box Workflow Definitions


The 'Review & Approve' and 'Ad-hoc Task' workflow definitions provided by default may be found in the Alfresco config directory alfresco/workflow.


  • review_processdefinition.xml - Process Definition for 'Review & Approve'
  • adhoc_processdefinition.xml - Process Definition for 'Adhoc Task'
  • workflow-messages.properties - Resource Bundle for both
  • workflowModel.xml - Task Model for both

Both of these workflows are configured in the bootstrap file alfresco/bootstrap-context.xml by the bean called workflowBootstrap.


Step 3: Add Behaviour to the Process Definition


With the data requirements specified, it's possible to re-visit the Process Definition and augment it with behaviour e.g. describe the data flow, task assignments and repository actions to perform.

All jPDL features are supported within Alfresco.  Please refer to the JBoss jBPM User Guide for the complete reference documentation of these features.

Back to the example, the augmented Adhoc Task Workflow...

<process-definition xmlns='urn:jbpm.org:jpdl-3.1' name='wf:adhoc'>

  <swimlane name='initiator'/>

  <start-state name='start'>
    <task name='wf:submitAdhocTask' swimlane='initiator'/>
    <transition name='' to='adhoc'/>
  </start-state>

  <swimlane name='assignee'>
    <assignment actor-id='#{bpm_assignee.properties['cm:userName']}'/>
  </swimlane>
  
  <task-node name='adhoc'>
    <task name='wf:adhocTask' swimlane='assignee'>
      <event type='task-create'>
        <script>
          if (bpm_workflowDueDate != void) taskInstance.dueDate = bpm_workflowDueDate;
          if (bpm_workflowPriority != void) taskInstance.priority = bpm_workflowPriority;
        </script>

      </event>
    </task>
    <transition name='' to='completed'>
      <action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
        <script>
          if (wf_notifyMe)
          {
            var mail = actions.create('mail');
            mail.parameters.to = initiator.properties['cm:email'];
            mail.parameters.subject = 'Adhoc Task ' + bpm_workflowDescription;
            mail.parameters.from = bpm_assignee.properties['cm:email'];
            mail.parameters.text = 'It's done';
            mail.execute(bpm_package);
          }
        </script>
      </action>

    </transition>
  </task-node>
  
  <task-node name='completed'>
    <task name='wf:completedAdhocTask' swimlane='initiator'/>
    <transition name='' to='end'/>
  </task-node>
     
  <end-state name='end'/>

  <event type='process-end'>
     <action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
        <script>
           if (logger.isLoggingEnabled())
              logger.log('End of process.  Cancelled: ' + cancelled);
        </script>
     </action>

  </event>
  
</process-definition>

Notes:


  • The swimlane 'assignee' is mapped to the process variable bpm_assignee
  • A task-create event is used to initialise the due date and priority of the ad-hoc task
  • The adhoc task completed transition event is used to call Alfresco javascript that sends an e-mail
  • A process-end event is used to log the end of the workflow
  • in Alfresco version 3.4.0 the script to set priorities given above is causing a syntax error which can be fixed by changing it to: if (bpm_workflowPriority) { taskInstance.priority = bpm_workflowPriority; }

Process Data


All process data - including what is specified by the task model - is stored and exposed to actions scripts by jBPM. To manipulate the task model in scripts, we must therefore first understand how it is represented on the jBPM side.

The standard task properties are mapped as follows:


bpm:taskId <namespace_prefix>:<local_name> e.g. bpm:assignee, wf:notifyMe

  1. Task Variable - <namespace_prefix>_<local_name> e.g. bpm_assignee, wf_notifyMe

If the variable does not exist yet, the property has the default value specified in the task model (or null if no default exists).

By default, when a task variable is pushed to a process variable and vice-versa, the same name is used.  For example, the Start Adhoc Task description specifies the property wf:notifyMe.  When the Start Adhoc Task is completed, the respective task variable wf_notifyMe is pushed into the process as a process variable also called wf_notifyMe.

JBoss jBPM provides a mechanism for manually controlling the mapping between task and process variables.  This mechanism is called the task controller which allows specific variables to be mapped and specific names to be used, e.g. to map the task variable wf_notifyMe to the process variable notify_via_email...



   <task>
     <controller>
       <variable name='notify_via_email' access='write' mapped-name='wf_notifyMe'/>
     </controller>
   </task>

The type of each task variable is defined by the Task description i.e. the data type of the respective property, or in the case of associations, a collection.  Many Alfresco data types map conveniently to jBPM data types e.g. d:text to string, d:boolean to boolean.  However, there is special support for d:noderef and associations that require further attention.

Alfresco Repository node references and associations are represented as Alfresco Node objects in JBoss jBPM.  An Alfresco Node object is an object-oriented view of an item in the Alfresco Repository.  It provides convenient accessors for retrieving and setting properties and traversing associations as well as methods for performing checkout/in, transform etc.  This is really powerful when combined with the scripting capabilities of Beanshell and Alfresco Javascript available within process definitions.  With this it's possible to control flow based on repository meta-data as well as perform common repository automations using script as part of the workflow.

The following Process variables are available in all Workflows:


initiator : A Repository Node (type cmSmiley Tongueerson) representing the person who initiated the workflow
initiatorhome : A Repository Node (type cm:space) representing the home folder of the person who initiated the workflow
companyhome : A Repository Node (type cm:space) representing the company home folder
cancelled : A flag indicating whether the workflow has been cancelled



And the following Process variables are also available once the Start Task has been completed:


bpm_workflowDescription: The description for this particular in-flight workflow (as defined on the base start task)
bpm_workflowDueDate: The due date for the workflow as a whole (as defined on the base start task)
bpm_workflowPriority: The priority for the workflow as a whole (as defined on the base start task)
bpm_package: A Repository Node (container with aspect bpm:workflowPackage - a system workflow package will also be of type bpmSmiley Tongueackage) representing the Workflow Package containing the content being routed through the workflow
bpm_context: A Repository Node (type cm:folder) representing the Alfresco Space within which the workflow was started

Task assignment


The JBoss jBPM Identity Component is not yet plugged into Alfresco User management and thus cannot be used for swimlane and task assignments.

However, assignment may be achieved using the actor-id attribute of swimlanes and tasks.

For example, in the Adhoc Task Workflow, the Submit Adhoc Task defines an association (to cmSmiley Tongueerson) that represents the Assignee.  The initiator selects a person in the Submit Adhoc Task Dialog which is then stored as a variable on the Task (named bpm_assignee).  When the task is completed, the assignee variable is pushed into the process.

The process variable named 'bpm_assignee' is now accessible in jPDL script and assignment expressions.  Remember that references to Alfresco People are represented as Node objects and thus may be examined to obtain any property of the Person including their name or e-mail address.  The following swimlane assignment demonstrates this.



<swimlane name='assignee'>
  <assignment actor-id='#{bpm_assignee.properties['cm:userName']}'/>
</swimlane>

AssignmentHandler


V2.0 Onwards

From Alfresco V2.0, a jBPM AssignmentHandler is provided for mapping Alfresco people to jBPM actors.

<assignment class='org.alfresco.repo.workflow.jbpm.AlfrescoAssignment'>
  <actor>actor</actor>
</assignment>

actor : a user name literal or Javascript expression in the form of #{expression} which resolves to a user name literal or Alfresco person node



It is recommended that AssignmentHandlers replace assignments of the style...

<assignment actor-id='#{bpm_assignee.properties['cm:userName']}'/>

Pooled Tasks & Groups


V2.0 Onwards

A Pooled Task is one which is allocated to a collection of people, but only one person actually takes ownership.  Whilst owned, the person performs the task, eventually completing it, or in some cases, putting the task back into the pool for someone else to take ownership.

The AlfrescoAssignment handler supports allocation of a pooled task as follows...

<assignment class='org.alfresco.repo.workflow.jbpm.AlfrescoAssignment'>
  <pooledactors>pooledactors</pooledactors>
</assignment>

pooledactors : a group name literal or Javascript expression in the form of #{expression} which resolves to a collection of Alfresco people nodes or an Alfresco group node



A 'Pooled Task' Dashlet is available for listing all pooled tasks relevant to a user.  The list of pooled tasks includes those that are directly assigned to the user or indirectly assigned via a group the user belongs to. (In CE 2.1 & CE 3.2, it only contains the pool tasks. Is this a bug or a feature ? Norgan)  The list of pooled tasks is dynamic in that changes to group membership will have an effect on pooled tasks, even if they have already been allocated to a group.

The Alfresco Javascript API has enhanced people support in v2.0 (for retrieving groups & their members) which are useful for workflow group management.


Actions & Scripting


jPDL Actions and Scripts allow invocation of business logic during a workflow. 
Business logic may be expressed in Java, jPDL Beanshell or Alfresco JavaScript.  All three languages have access to Task and Process variables.

The syntax for including Alfresco JavaScript in a workflow definition is:

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

Or

<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>

Alfresco JavaScript has access to all process variables and (if applicable) task variables, unless the <variables> element is provided, in which case, specific variables may be passed in and out of the script.



For example, in the Adhoc Task Workflow, an e-mail is sent using Alfresco JavaScript (where bold items are references to process variables):

<transition name='' to='completed'>
  <action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
     <script>
        if (wf_notifyMe)
        {
           var mail = actions.create('mail');
           mail.parameters.to = initiator.properties['cm:email'];
           mail.parameters.subject = 'Adhoc Task ' + bpm_workflowDescription;
           mail.parameters.from = bpm_assignee.properties['cm:email'];
           mail.parameters.text = 'It's done';
           mail.execute(bpm_package);
        }
     </script>
  </action>
</transition>

Variables that represent Repository Nodes may be navigated and operated against using the Node API.  This API is available to both Alfresco JavaScript and jPDL Beanshell.

Also, within Alfresco Workflow JavaScript, the following 'root' objects are available:

1.4 Enterprise / 2.0 Onwards:


person : Node (type cmSmiley Tongueerson) representing the person who is executing the script.

userhome : Node (type cm:folder) representing the home folder of the person who is executing the script.

1.4 Community & Enterprise:


search :A host object providing access to Lucene and Saved Search results. See the Search API section.

actions :A host object providing invocation of registered Alfresco Actions.  See the Actions API section.

logger :A host object providing access to console logging facilities for debugging of scripts. See the Logging API section.

session Smiley Frustratedession related information such as the current authentication ticket. See the Session API section.

classification :Access to the root elements of the classification API. See the Classification API section.

utils :Access to a library of useful helper functions not provided as part of generic JavaScript. See the Utility Functions section.

Run As


2.9 Onwards:

Alfresco Javascript may be run as a specific user.

<action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
  <runas>admin</runas>
  <script>
    logger.log('Person ' + person.properties['firstName']);
  </script>
</action>

An exception is raised if the person does not exist at time of script execution.


For Each Fork


V2.0 Onwards

In some workflow scenarios, it is necessary to support a Fork where the number of paths is only known at run-time.  For example, in a parallel review process where the review task is allocated to 'N' people for review.

To support this scenario, a 'ForEachFork' action is provided.

<node name='startreview'>
   <action class='org.alfresco.repo.workflow.jbpm.ForEachFork'>
      <foreach>collection</foreach>
      <var>variable</var>
   </action>
</node>

collection : a Javascript expression in the form of #{expression} which resolves to a collection (of any type).  A path is forked for each entry of the collection.
variable : the name of the variable to create in each fork that holds the collection entry



As with a simple jPDL Fork, a ForEachFork must be balanced with a Join.  A simple parallel review could be described as follows:

<node name='startreview'>
   <action class='org.alfresco.repo.workflow.jbpm.ForEachFork'>
      <foreach>#{people.getMembers(wf_reviewGroup)}</foreach>
      <var>reviewer</var>
   </action>
   <transition name='review' to='review' />
</node>

<task-node name='review'>
   <task name='wf:reviewTask'>
      <assignment class='org.alfresco.repo.workflow.jbpm.AlfrescoAssignment'>
        <actor>#{reviewer}</actor>
      </assignment>
   </task>
   <transition name='reject' to='endreview' />
   <transition name='approve' to='endreview'>
</task-node>

<join name='endreview'>
   <transition to='isapproved' />
</join>

Timers


A workflow timer provides the ability to trigger an action or transition within a workflow at a specified future time (absolute or relative to the entry of a node in the workflow).  Timers are useful for implementing escalation procedures (e.g. user A has not completed task B, therefore notify user C) and delayed processing (e.g. submit content to Web Site in a weeks time).

A timer may be attached to any node within the workflow definition (see jBoss jBPM documentation on timers), however, they are particularly useful against Task nodes.

Here's an example of attaching a timer to a task (which initiates the launch transition on the absolute date specified in the workflow):

<task-node name='submitpending'>
  <task name='wcmwf:submitpendingTask' swimlane='initiator'>
    <timer duedate='#{wcmwf_launchDate}' transition='launch' >
       <action class='org.alfresco.repo.workflow.jbpm.AlfrescoJavaScript'>
          <script>
             logger.log('WCM Submission submitted at ' + wcmwf_launchDate);
          </script>
       </action>
    </timer>
  </task>
  <transition name='cancel' to='submitcancelled' />
  <transition name='launch' to='submitted' />
</task-node>

The important points of interest are:


  • duedate may be jPDL relative time (e.g. '3 days') or an absolute date object
  • duedate may be set from a workflow variable e.g. #wcmwf_launchDate
  • the timer can have an associated action which is executed when the timer is triggered
  • the timer can have an associated transition which is followed when the timer is triggered
  • if the task is explicitly exited before the timer is triggered, the timer is destroyed

Step 4: Create Workflow Resource Bundles


For localised workflow interaction it is necessary to provide Resource Bundles containing UI labels for each piece of text that is exposed to the User.  With the appropriate resource bundles, a single Workflow instance may spawn Tasks where the user interface for each Task is rendered in a different language based on the locale of the user.

The Dictionary Model localisation approach is used for Workflow & Task Models to provide labels for Task names & properties.



Other workflow labels are supported with the following keys:


  • <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 our example Adhoc Task Workflow, the following Resource Bundle is defined:



#
# Adhoc Task Workflow
#

wf_adhoc.workflow.title=Adhoc Task
wf_adhoc.workflow.description=Assign task to colleague

# Adhoc Task Definitions

wf_workflowmodel.type.wf_submitAdhocTask.title=Submit Adhoc Task
wf_workflowmodel.type.wf_submitAdhocTask.description=Allocate task to colleague
wf_workflowmodel.property.wf_adhocDescription.title=Task Description
wf_workflowmodel.property.wf_adhocDescription.description=Description of what needs to be achieved
wf_workflowmodel.property.wf_adhocDueDate.description=Task Due Date
wf_workflowmodel.property.wf_adhocPriority.title=Task Priority
wf_workflowmodel.property.wf_notifyMe.title=Notify Me
wf_workflowmodel.property.wf_notifyMe.description=Notify me when task is complete
wf_workflowmodel.association.wf_assignee.title=Assignee
wf_workflowmodel.association.wf_assignee.description=Who's doing the task
wf_workflowmodel.type.wf_adhocTask.title=Adhoc Task
wf_workflowmodel.type.wf_adhocTask.description=Adhoc Task allocated by colleague
wf_workflowmodel.type.wf_completedAdhocTask.title=Adhoc Task Completed
wf_workflowmodel.type.wf_completedAdhocTask.description=Adhoc Task Completed

Localised resource bundles are registered using the Workflow Deployer bean.  This bean allows for the deployment of a Process Definition, but it can also deploy associated Tasks Models and Resource Models.

<bean id='myworkflows.workflowBootstrap' parent='workflowDeployer'>
  <property name='workflowDefinitions'>
    <list>
      ...
    </list>
  </property>
  <property name='models'>
    <list>
      ...
    </list>
  </property>
  labels'>
    <list>
      <value>alfresco/workflow/adhoc-messages</value>
    </list>
  </property>
</bean>

Alternatively, the resource bundle may be registered along with the Task Model using the usual:

<bean id='adhocWorkflow.dictionaryBootstrap' parent='dictionaryModelBootstrap' depends-on='dictionaryBootstrap'>
  <property name='models'>
     <list>
        ...
     </list>
  </property>
  labels'>
     <list>
        <value>alfresco/messages/adhoc-messages</value>
     </list>
  </property>
</bean>

Step 5: Configure the Web Client Task Dialogs


Workflow Task Dialogs are configured using the exisiting Alfresco Web Client configuration mechanism and in particular, the steps shown in Displaying Custom Metadata.

As the tasks are defined using the Data Dictionary the same property sheet configuration techniques apply here too. Therefore, to collect the required data for the wf:submitAdhocTask defined in the Create the task description section above, the following configuration is used:



<config evaluator='node-type' condition='wf:submitAdhocTask' replace='true'>
   <property-sheet>
      <separator name='sep1' display-label-id='general' component-generator='HeaderSeparatorGenerator' />
      <show-property name='bpm:workflowDescription' component-generator='TextAreaGenerator' />
      <show-property name='bpm:workflowPriority' />
      <show-property name='bpm:workflowDueDate' />
      <show-property name='wf:notifyMe' />
      <separator name='sep2' display-label-id='users_and_roles' component-generator='HeaderSeparatorGenerator' />
      <show-association name='bpm:assignee' />
   </property-sheet>
</config>

The Start Workflow Wizard uses the configuration above to display the relevant controls to collect the data from the user. The Manage Task Dialog uses the same approach to display the data it needs to collect. For the wf:adhocTask defined in the Create the task description section the following configuration is used:



<config evaluator='node-type' condition='wf:adhocTask' replace='true'>
   <property-sheet>
      <separator name='sep1' display-label-id='general' component-generator='HeaderSeparatorGenerator' />
      <show-property name='bpm:taskId' />
      <show-property name='bpm:workflowDescription' component-generator='TextAreaGenerator' />
      <show-property name='bpm:status' />
      <show-property name='bpm:dueDate' />
      <show-property name='bpm:priority' />
   </property-sheet>
</config>

If the standard Manage Task Dialog is not sufficient it can be overridden based on the type of task.

Simply provide an override for the default manageTask dialog in your configuration:



<config evaluator='node-type' condition='wf:adhocTask' replace='true'>
   <property-sheet>
      ...
   </property-sheet>
   <dialogs>
      <dialog name='manageTask'
              page='/custom/jsp/workflow/special-manage-task-dialog.jsp'
              managed-bean='ManageTaskDialog'
              icon='/images/icons/manage_workflow_task_large.gif' 
              description-id='manage_task_desc' />
      <dialog name='viewCompletedTask'
              page='/jsp/workflow/view-completed-task-dialog.jsp'
              managed-bean='ViewCompletedTaskDialog'
              icon='/images/icons/completed_workflow_task_large.gif'
              description-id='view_completed_task_desc'
              show-ok-button='false' />
   </dialogs>
</config>



You might want to take the existing /jsp/workflow/manage-task-dialog.jsp as starting point for your custom dialog. Possibly you also would use a different backing bean. Please also note that you should provide a new configuration for the viewCompletedTask dialog. The example above just duplicates the standard definition from web-client-config-dialogs.xml, but you get the idea on how to provide your own JSP and backing bean.


Step 6: Test the Workflow


Custom workflow definitions may be tested using one of the following methods:


  1. Start the Alfresco Server and test via the Alfresco Web Client
  2. Use the Workflow Console to interactively step through workflows
  3. Write a JUnit Test Harness that employs the Alfresco Workflow Service API to programmatically Start Workflows and Manage Tasks. You can find an example of programmatic usage of those API in source code of class WorkflowInterpretor.

Step 7: Integration with Rules (Optional)


An advanced workflow may be initiated via a Rule defined within the Alfresco Web Client.  This allows automated initiation of a workflow rather than relying on a user to manually start.

To support this, a new Action has been introduced named 'start-workflow'.  Unfortunately, for now, there is no Web Client UI for configuring the 'start-workflow' action.  Instead, the Web Client 'Execute Script' Action can be used to programmatically initiate the 'start-workflow Action.

The 'start-workflow' Action 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 script may be executed by a Rule 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:workflowDescription'] = document.name;
workflow.parameters['bpm:assignee'] = person;
var futureDate = new Date();
futureDate.setDate(futureDate.getDate() + 7);
workflow.parameters['bpm:workflowDueDate'] = futureDate;
workflow.execute(document);

Appendix A: Unsupported Features


The following features may be switched on, but are unsupported.


Display of Workflow Definition Diagrams


When developing a workflow definition with the Alfresco Workflow Designer it is possible to create a graphical view (diagram) of the workflow.  Deploying the workflow definition directly from the Designer into Alfresco will also deploy its diagram.

The diagram may be shown in the Start Workflow and Manage Task dialogs.  This is achieved by changing:

false' id='workflow-outline' ...

to:

true' id='workflow-outline' ...

in:

/jsp/workflow/start-workflow-wizard/workflow-options.jsp
/jsp/workflow/manage-task-dialog.jsp

The result is as follows:

none|thumbnail