This document provides an overview of advanced workflow capabilities in Alfresco, including service tasks, listeners, and scripting. Service tasks allow Java code to be executed from a workflow using Java delegate classes, beans, or expressions. Listeners can react to workflow events using classes, beans or expressions. Scripting supports JavaScript execution using scope and execution variables. Timers can delay workflow start, intermediate, and boundary events using date, duration, or repeating formats.
4. Service Tasks!
• Service Tasks allow Java code to be executed as part of a
workflow!
• Allows easy unit testing and code re-use!
• Three ways to implement:!
• JavaDelegate Class!
• JavaDelegate Bean:!
• Arbitrary Expression!
5. Service Tasks: Java Delegate Class!
• The supplied class must implement JavaDelegate interface!
• Fields can be set on the class!
• Use the ʻactiviti:classʼ attribute to specify the delegate class
<serviceTask id=“getMimetypet" name=“Get Mimetype”
activiti:class="org.alfresco.examples.MimetypeGetter“ >
<extensionElements>
<activiti:field name=“document">
<activiti:expression>${dcwkflw_document}</activiti:expression>
</activiti:field>
</extensionElements>
</serviceTask>
6. Service Tasks: Java Delegate Bean!
• The supplied bean must implement JavaDelegate interface!
• The same bean instance is used for all executions!
• The bean must be defined in Spring and registered with the
activitiBeanRegistry!
• Use ʻactiviti:delegateExpressionʼ attribute to specify the
delegate bean in the process definition:!
<serviceTask id=“getMimetype" name=“Get Mimetype“
activiti:delegateExpression="${mimetypeGetter}" />
7. Service Tasks: Java Delegate Bean!
• Recommended to extend BaseJavaDelegate class!
• Recommend extending baseJavaDelegate bean!
• If the bean class extends BaseJavaDelegate and the Spring bean
definition extends baseJavaDelegate, then the bean will
automatically be registered with the activitiBeanRegistry and will
have access to the serviceRegistry!
<bean id=“mimetypeGetter" parent="baseJavaDelegate"
class="org.alfresco.example.MimetypeGetter" />
9. Service Tasks: Arbitrary Expression!
• Execute any arbitrary expression!
• The expression may reference any bean defined in Spring and
registered with the activitiBeanRegistry!
• A process variable can be specified for the return value using the
activiti:result attribute!
<serviceTask id=”getMimetype” name="Get Mimetype" activiti:resultVariable="dcwkflw_mimetype"
activiti:expression=“${mimetypeGetter.getMimetype(dcwkflow_document)}” />!
11. Listeners!
• Used to react to certain events during workflow execution!
• Two types: TaskLisener and ExecutionListener!
• Three ways to configure, as with ServiceTasks:!
• Listener Class:!
<activiti:executionListener class="org.alfresco.example.MyExecutionListener" event=“start” />!
• Listener Bean:!
<activiti:taskListener delegateExpression=“${myTaskListener}" event=“create" />!
• Arbitrary Expression
<activiti:executionListener expression=“myPojo.myMethod(myVar)" event="start" />
13. Listeners: Execution Listener Implementation!
Execution Listener class or delegate bean must implement
ExecutionListener interface:!
public class ExecutionEventLogger implements ExecutionListener
{
private static final Log LOGGER = LogFactory.getLog(ExecutionEventLogger.class);
@Override
public void notify(DelegateExecution execution) throws Exception
{
String eventName = execution.getEventName();
LOGGER.info("Received event: " + eventName);
}
}!
14. Listeners: Task Listener Events!
• All Task Listeners defined inside task elements:!
<userTask id=“theTask” name=“The Task” >
<extensionElements>
<activiti:taskListener ... [Listener Details] ... />
</extensionElements>
</userTask>!
• Event: assignment is called when a task is assigned to a user,
usually called before create:!
<activiti:taskListener event=“assignment” class=“org.alfresco.example.TaskEventLogger” />
• Event: create is called when the task is created, after assignment:!
<activiti:taskListener event=“create” delegateExpression=“${taskEventLogger}” />
• Event: completed is called when the task is completed:!
<activiti:taskListener event=“completed” expression=“${logger.info(task.eventName)}” />
15. Listeners: Task Listener Implementation!
Task Listener class or delegate bean must implement TaskListener
interface:!
public class ExecutionEventLogger implements TaskListener
{
private static final Log LOGGER = LogFactory.getLog(ExecutionEventLogger.class);
@Override
public void notify(DelegateTask task)
{
String eventName = task.getEventName();
LOGGER.info("Received event: " + eventName);
}
}
18. Scripting: Scope Variables!
• person ScriptNode, the current user!
• userhome ScriptNode, the home space of the current user!
• execution DelegateExecution, the current execution.!
• task DelegateTask, the current task (ScriptTaskListener only)!
• cancelled boolean, was the execution cancelled
(ScriptExecutionListener only)!
• deleted boolean, was the execution deleted
(ScriptExecutionListener)!
19. Scripting: Execution Variables!
• All execution variables added to scope!
• Variable names translated from “prefix:suffix” to “prefix_suffix”!
• Associations and noderef properties converted to ScriptNodes!
• Use execution.setVariable(name, value) to modify variables!
• Check if a variable exists using:!
if (typeof <variable name> != 'undefined')
20. Scripting: Examples!
• Copy a task variable to a process variable:
execution.setVariable('dcwkflw_reviewOutcome', task.getVariable('dcwkflw_reviewOutcome'));
• Set a task property from a pocess variable if it exists:
if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate;
• Apply an aspect ʻdcwkflw:publishedʼ to a document:
var presentation = bpm_package.children[0]; // Get the presentation
presentation.addAspect('dcwkflw:published'); // Apply published aspect
22. Timers!
• Timers are used to delay an event until a specified time/duration!
• Timers can be attached to three types of event:!
• startEvent: Starts the workflow!
• intermediateCatchEvent: Between nodes/events!
• boundaryEvent: Associated with a node (e.g. a userTask)!
• Three ways to set trigger time:!
• timeDate: Triggers at specified date/time!
• timeDuration: Triggers after specified delay duration!
• timeCycle: Triggers repeatedly with specified delay/interval!
• All dates/times/durations/intervals use ISO8601 format!
23. Timers: Start Event Date Example!
• Create a workflow which sends a Christmas Greeting
<!-- Start workflow at 12:05 on Christmas Day -->
<startEvent id="start" >
<timerEventDefinition>
<timeDate>2011-12-25T12:05:00</timeDate>
</timerEventDefinition>
</startEvent>
<sequenceFlow id='flow1' sourceRef='start' targetRef='sendGreeting' />
24. Timers: Intermediate Event Delay Example!
• Delay after some service task performs some asynchronous event
to wait for the job to complete:!
<sequenceFlow id='flow1' sourceRef='asyncJob' targetRef='waitForJobToFinish' />
<!-- Wait 1 hour 30 mins for the job to finish -->
<intermediateEvent id="waitForJobToFinish" >
<timerEventDefinition>
<timeDuration>PT1H30M</timeDate>
</timerEventDefinition>
</intermediateEvent>
<sequenceFlow id='flow2' sourceRef='waitForJobToFinish' targetRef='nextTask' />
25. Timers: Repeating Boundary Event Example!
• Send a reminder email if a task isnʼt completed after 1 week.
Repeat the email every day for 3 days:!
<userTask id="theTask" >
<!-- Wait 1 week, then repeat every 2 days a further 2 times -->
<boundaryEvent id="repeatingNotification" cancelActivity="false" attachedToRef="theTask" />
<timerEventDefinition>
<timeCycle>R3/P1W/P1D</timeDate>
</timerEventDefinition>
</boundaryEvent>
<sequenceFlow id='flow1' sourceRef='repeatingNotification' targetRef='sendEmail' />
<serviceTask id="sendEmail" activiti:delegateExpression="${sendEmailDelegate}" />