Alfresco: Workflow managed by JavaScript
If you are a regular reader of this blog, you might have figured out that I am currently working on a project involving alfresco at the center and it's a content management system. Earlier I have worked with Content repository (Apache Jackrabbit) and that was a good experience. Alfresco is next step of a content repository which extends it into a full blown content management system and much more. I was working on a problem where we defined a custom (Advanced workflow) to be precise in Alfresco lingo. This workflow was needed to be monitored, managed and accessed only via a webscript as we have used webscripts to do almost everything in our project. I was very pleased to see this, but that is only available in 2.9 labs release (as of now). We are using alfresco 2.2.0 version for our development and that is production stable version, so I have very little choice but go with production version. Alfresco has very limited JavaScript API support for workflow manipulation and that was difficult job for manage. There was no other option than writing custom JavaScript API which allows to manage workflow in Alfresco. We did that and it was very powerful and easy!
I wanted following features for JavaScript API -
- Easy to extend
- Can handle any workflows
- Provides easy ways to retrieve tasks, definitions, paths etc.
- Provides as much functionality possible which is available in Alfresco Workflow Console.
Alfresco workflow console is command line interaction component which allows you to manipulate, get information about workflows using simple commands and I wanted to do all that using JavaScript. I started exploring the source code and found a class 'org.alfresco.service.cmr.workflow.WorkflowService'. This class has generic API which allows you to do all the operations possible through workflow console. This bean is used for workflow console operations. So all I needed was expose this bean in JavaScript as root object and start using it. That simple! I wrote a simple java class to expose the bean as follows:
package com.xxxx.yyyy.workflow; import java.util.List; import org.alfresco.repo.processor.BaseProcessorExtension; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.workflow.WorkflowService; public class WorkflowManager extends BaseProcessorExtension { private ServiceRegistry services; public void setServiceRegistry(ServiceRegistry serviceRegistry) { this.services = serviceRegistry; } public WorkflowService getWorkflowService(){ return services.getWorkflowService(); } }
The method getWorkflowService() exposes the workflow service to the JavaScript calls. To expose the Workflow Manager as root object in JavaScript create WEB-INF/classes/alfresco/extension/custom-script-context.xml and you will be good! (If you don't know how to do that, read this) Now, you can get the handle of workflow service in JavaScript code. Yet, we need to write a small component which will allow us to retrieve the active workflows, tasks etc. To do so, I wrote a small JavaScript object which provides those functionality to the user.
var workflowService = workflow.getWorkflowService(); var W = { transitions: function(noderef){ var task = W._currentTask(noderef); var trans = []; try{ var tasks = task && task.path.node.transitions; for(var index=0; index < tasks.length; index++){ trans[trans.length] = tasks[index].id; } }catch(error){ // Ignore error } return trans; }, move: function(noderef, command){ workflowService.endTask(W._currentTask(noderef).id , command); }, _workflowPath: function(noderef){ var workFlows = workflow.getWorkflows ("workspace://SpacesStore/" + noderef, true); if(workFlows.size()>0){ return workFlows.get(0).id + "-@"; } return ""; }, _currentTask: function(noderef){ var curTask; var tasks; try{ tasks = workflowService.getTasksForWorkflowPath (W._workflowPath(noderef)); if(tasks.size() > 0) curTask = tasks.get(0); } catch(Error){ // Ignore error } return curTask; } } function initWorkflow(noderef) { var wflow = actions.create("start-workflow"); wflow.parameters.workflowName = "jbpm$xxxxyyyy:abc"; // your workflow name wflow.parameters["bpm:assignee"] = person.properties.userName; wflow.parameters["bpm:workflowDescription"] = "Put your description"; wflow.execute(noderef_for_which_workflow_will_associate); }
Thats it! The initiate workflow method is used to apply a workflow to a node. Once that is done, the W object can be used to do operations like retrieving the active tasks, ending the workflow and making the workflow transition. Hope that helps. If you need more workflow related information and reading material you can visit following places:


nice to see growing adoption and use of alfresco and jbpm. We also are working on similar problems, developing custom solutions for our customers based on alfresco. Currently we faced a probloem how to provide customer with more user friendly workflow management UI. Workflow terminal is too geeky and asks for some more advance ui.
remis
11 Jun 08 at 1:21 pm
Alfresco rocks buddy. I should have been a computer sciences guy.
Devranjan
24 Jul 08 at 11:17 pm
did you go any further making a proper workflow UI for alfresco? i would be extremely interested in your progress….
the workflow console is just not user friendly at all!
Peglar
23 Mar 09 at 3:42 pm
Hi
I am also doing something similar.
I do not know hoe to create the custom-script-context.xml (If you don’t know how to do that, read this) does not help me.
Could you please send me a sample xml?
thanks
Johan
21 May 09 at 2:28 pm
Alfresco suuuucks. It is developed by people without knowledge how to code. Code is flawed.
To configure just simple things such as ftp, smtp or webdav access you should use global search on hundreds of spring configs and when change configuration in 2 or 3 files synchroniously.
Extension mechanism is very poor and unprofessional. Web ui looks ugly. HTML markup is horrible.
Permission model in Alfresco sucks too. There is no ACL support or just mechanism to setup permission on node in JCR. System folder ‘Data Dictionaly’ is visible to all user and there is no correct way to hide it. If you hide, some of the system functions will silently fail.
JCR is sloooooooooooooooooooooow.
If someone will recommend you your boss to use it on production you should convince boss not to do (or just shoot that man).
Dmitry Pekar
2 Jul 10 at 10:00 pm