top of page

A Beginner's Look at Alfresco Task Listeners


Recently, ClearCadence was hired to implement the Alfresco Digital Business Platform (a triple threat combo of Alfresco Process Services, Alfresco Content Services and Alfresco Governance Services) for one of our clients.  Within this project, one of their requirements was to capture the name of the user who took ownership of a workflow task. 


One of the great things about the Alfresco platform is that because it’s open source, you have a lot of people doing a lot of things with it and sharing those experiences online.  The problem is that often there are only partial or incomplete answers because the author assumes you know a lot more than you do about the platform OR it’s a very technical answer and unless you are deep in the trenches with Java code, AngularJS and REST service calls, you can get very lost.  The answer may even be right in front of you, but because you are not code savvy to what they are writing, you don’t recognize it. 


Finding answers like this can pose a challenge with a platform such as Alfresco Process Services because it provides a “low-code” approach to make it easier for customers to build their own BPM solutions.   Low-code is great and Alfresco provides plenty of documentation, but it can’t cover everything you may need to satisfy your business requirements. Additionally, for us, being a BPM consulting firm, it’s important to consider the customer when building such solutions.  It may be that providing a complex set of Java classes isn’t something they want to support long term.  Because of this, we at ClearCadence will be providing some simple, “medium-code” answers for specific use cases.


And thus “how do you capture a username in Alfresco Process Services?” is presented below.


The trick with the username (or the “assignee” as it is referred to in Alfresco) is that you can really only capture it in one of two ways:  the first is at the task level when someone takes ownership of the task and the second is by digging into the history of the task and working through each person who touched it.  For our client’s need, they wanted it captured at the moment the user acquired the task.  Having worked with several different BPM platforms in the past, my first thought to accomplish this was to get the username of the task owner through client-side JavaScript, stash it in a form field and then save the task, all during a form load event. 


This solution, while doable, felt a little kludgy and we were hoping for a sleeker and more streamlined solution.  Enter the Alfresco Task Listener.


The Alfresco Task Listener is an extension to the BPMN 2.0 specification that provides a hook inside a user task and that is triggered by events.  These events can then run custom code that can be server-side JavaScript, Groovy script, or make a call to a Java class.  Since we’re trying to keep this simple, we elected to take the JavaScript approach. 


However, before we get into that, let’s look more closely at the events within the Task Listener:


  • Assignment – Invoked when the task is assigned to someone;

  • Create – Invoked when the task is created (AND after the Assignment event);

  • Complete – Invoked when the task is completed and just before the task is deleted from runtime data;

  • Delete – Invoked just before the task is to be deleted and just after the task has finished its complete event;

A quick note on why the Assignment event is fired before the Create Event:  this is done so that when receiving the create event, an inspection of all properties can be done which would include the assignee of the task. 


As mentioned previously, we wanted to go with the semi low-code method and use JavaScript even though the Task Listener supports calling classes, using expressions, delegate expressions and, finally, script tasks.   Since Alfresco Process Services utilizes Activiti at its core, you can refer to the Activiti User Guide to find a code snippet like this:

<activiti:taskListener event="complete" class="org.activiti.engine.impl.bpmn.listener.ScriptTaskListener" >

<activiti:field name="script">

<activiti:string>

                          def bar = "BAR"; // local variable

                          foo = "FOO"; // pushes variable to execution context

                          task.setOwner("kermit"); // test access to task instance

                          bar // implicit return value

             </activiti:string>

        </activiti:field>

        <activiti:field name="language" stringValue="groovy" />

        <activiti:field name="resultVariable" stringValue="myVar" />

</activiti:taskListener>

This is great…for someone who understands deeper code but what about those low-to-medium code users who either don’t want to go this deep, don’t know how to go this deep, or doesn’t have access to the necessary files on the application server (i.e., a citizen developer working in a department trying to build a workflow and does not have access to change a jar or property file)?  Therefore, Alfresco has built the App Designer in the Alfresco Process Services platform that puts a cover of sorts over the Activiti BPM code.  


Looking at the properties of a User Task, we can find Task Listeners and then click to see the values for them:

User Task Properties

Task Listener Values

This interface provides the entry segments for building the code sample we saw previously.  Within this dialog, you can select your Event, Class, Expression, Delegate Expression and/or the Script Language you want to use and the script itself OR the expressions and/or strings to be used.  Let’s look at what the Alfresco App Designer Task Listener would look like if we used it instead of writing that code we looked at earlier:

Task Listener vs. raw code

Makes it a little bit easier for the non-developer to get something done, doesn’t it?  Yes, there is still code to be written but this is why we are saying “medium code” as opposed to “low or no code” and let’s face it, “no code” solutions will only get you so far.  To really flex the muscles on your BPM solutions, you must have some ability to customize. 


Before we move on, take a note of these controls:

Task Listener Controls

These allow you to move the order of your events and to add or remove events as needed.  Often, we will add hooks to the Create, Assignment, and Complete events in a single user task.  Speaking of the Assignment event, let’s look at our solution for getting that username of the task owner. 


As stated earlier, we went with JavaScript because our client primarily has people proficient in JavaScript rather than in Groovy Script and they mostly preferred not to have to drag out Eclipse or IntelliJ IDEA to work out a Java class.   Therefore, we have our language (JavaScript).  In order to execute the script, we need to reference the ScriptTaskListener class and, of course, we want to get this information during the Assignment event.  We could get the username at the Create Event since it occurs after the Assignment Event but it just makes it cleaner and easier to understand if we do it during Assignment (we want to know the person ASSIGNED to the task so why not get that during ASSIGNMENT, right?).


We then worked out the minor JavaScript code needed to get to the username and this required a couple different calls.  First, we needed an execution object to set our variables, then we had to get the internal ID for the person assigned to the task and we used that ID to get the full name of the user.  Finally, we set that value to a form field variable and, just for good measure, we set the STATUS form field variable to “In Progress” to further define the disposition of the task:

var execution = task.getExecution();

var userID = task.getAssignee();

var sUserName = userInfoBean.getFullName(userID);

execution.setVariable("CURRENT_USER", sUserName);

execution.setVariable("STATUS", "In progress");

The key in the above code is the Alfresco userInfoBean which provides the information regarding the user (for more info, click here).   The end-result is having that information available not only to the user but for our own internal uses, like passing the data to back-end systems via integration.  Here’s what the Task Listener mostly looked like when we were done (which was within just a few minutes once we knew what we were targeting and how to get it):

Task Listener Configuration Final

In the end, could we have coded this within a Java class and called that as needed?  Yes, but when ClearCadence provides professional services to our clients, we want to deliver a solution that is supportable by them, therefore, we take the time to make sure we understand not only the requirements of a project but also the people, capabilities, and the in-house skills available.  This way, when we ultimately deliver the solution, we know we’re not giving them something they won’t be able to adequately support. 


Luckily, with the blend of low, medium and high-code options that many of today’s BPM platforms support, like Alfresco Process Services, we can readily provide our customers with the best and most efficient solutions possible.  Be on the lookout for more “medium-code” discussions on our website and if you need any assistance with implementing and supporting your BPM solution, whatever the platform, please contact us

Kevin Beddingfield is the Managing Director at ClearCadence

Featured Posts
Recent Posts
Archive
Search By Tags
bottom of page