Tuesday, April 7, 2009

Working with jBPM workflows in Alfresco - Part 1: jBPM

The following set of blog articles will track my usage of jBPM in Alfresco to help orchestrate external content processing for publishing, and integrate with Review and Approval Advanced workflows.

Step 1 - Design
In order to collaborate with external publishing processes, we have chosen to use JMS topics. This approach offers robustness and flexibility in communication. The workflow described here will be an 'orchestration' workflow. Its responsibility is to call out external processes and monitor progress. This workflow will be associated to content, however, the content will be in the form of a 'work order' that is created when a user requests to publish a set of content. The user may view the workflow on this work order to see the progress of the external processes orchestrated by the workflow. Later on, we will integrate with the publish review and approve workflow where user tasks will be created to coordinate user activity.

Alfresco will be the container for the orchestration workflows. Actions in the workflow will be responsible for creating and sending messages to JMS topics to choreograph external publishing processes. A simulator will be used to act as the publisher processes for testing purposes. ActiveMQ is used as the JMS provider in these examples. There will also be a message handler created with the responsibi8lity of subscribing to topics that the publisher processes use to provide feedback and communicate status to the workflow. The following diagram represents this intended configuration.

Component descriptions:
  • Alfresco - contains jbpm implementation and content being workflowed
  • jBPM - library for jBPM accessed via the workflowService
  • process definition - jBPM process defining the process steps to orchestrate the publishing process
  • content event producer action - BPM action invoked from process to publish a content event message to the content topic
  • content event message - jms message indicating which content to publish and where to publish too
  • content event topic - jms topic storing the content event messages to be processed by the publisher
  • content event consumer - consumes content event messages and calls publishing services to invoke the publishing processes
  • publish process - implements the publishing functionality and calls publisher event producer to
  • publish event producer - creates and publishes publish event messages to the publish event topic indicating status of publishing
  • publish event consumer handler - consumes publish event messages and signals corresponding transitions on the publish process definition via the jbpm library

Step 2 - Environment Setup
  1. Install Alfresco SDK: follow instructions on the alfresco wiki
  2. Install ActiveMQ: follow the instructions on the ActiveMQ site
  3. Install jBPM (3.2.x): follow the instructions on the JBoss jBPM site: I installed jbpm-3.2.2 for best compatibility with Alfresco
  4. Install jBPM Process Designer
Note: compatibility problems. As of Alfresco 3.1, the jBPM 3.2.2 is supported. The only issue I had with this version is that there are no hibernate tasks for the Mail Node.

Step 3 - Create the Eclipse Project
For this project, I created a project called 'orchestration -example' using the jboss - jbpm process project' wizard.

Step 4 - Create the process
The following image shows the workflow configuration created to orchestrate and monitor the publishing process.
Workflow states:
  • Start - initial state when workflow is created
  • Requested - state indicating that a request was made to the publisher (the content event msg was sent to the content topic)
  • Processing - state indicating that the publisher has received the request and is processing
  • Succeeded - the publish process completed normally
  • Failed - the publish process failed
  • End - workflow has ended
Using this workflow, the state can be queried to indicate the status of the publishing process.
Here is the first version of this process definition:
<?xml version="1.0" encoding="UTF-8"?>

<process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="publishContentBasic">
<start-state name="start">
<transition name="to_requested" to="requested">
<action name="action" class="com.sample.action.MessageActionHandler">
<message>Going to the first state - requested!</message>

<state name="requested">
<transition to="processing" name="to_processing"></transition>

<state name="processing">
<transition to="succeeded" name="to_succeeded"></transition>
<transition to="failed" name="to_failed"></transition>

<state name="succeeded">
<transition to="end" name="to_end">
<action name="action" class="com.sample.action.MessageActionHandler">
<message>About to finish - succeeded!</message>

<state name="failed">
<transition to="end" name="to_end">
<action name="action" class="com.sample.action.MessageActionHandler">
<message>About to finish - failed!</message>

<end-state name="end"></end-state>
This first configuration of the process is basic and simple. It will be embellished later with processing and business logic. This example uses the com.sample.action.MessageActionHandler class that is created by default using the 'create jbpm project' option in Eclipse.

Step 5 - The first test
In this first pass, we are using jBPM out of the box, without Alfresco. This mode allows us to configure and test our process in as much isolation as possible. Later we will use the Alfresco SDK to run as an Embedded Alfresco when we need Alfresco workflow services.

package com.sample;

import junit.framework.TestCase;

import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;

public class PublishContentBasicProcessTest extends TestCase {

public void testSimpleProcess() throws Exception {

// Extract a process definition from the processdefinition.xml file.
ProcessDefinition processDefinition = ProcessDefinition.parseXmlResource("publishContentBasic/processdefinition.xml");
assertNotNull("Definition should not be null", processDefinition);

// Create an instance of the process definition.
ProcessInstance instance = new ProcessInstance(processDefinition);
"Instance is in start state",
"Message variable should not exist yet",

// Move the process instance from its start state to the first state.
// The configured action should execute and the appropriate message
// should appear in the message process variable.
"Instance is in reqested state",
"Message variable contains message",
"Going to the first state - requested!",

//move to processing state
"Instance is in processing state",

//move to succeeded state
"Instance is in processing state",

// Move the process instance to the end state. The configured action
// should execute again. The message variable contains a new value.
"Instance is in end state",
assertTrue("Instance has ended", instance.hasEnded());
"Message variable contains message",
"About to finish!",
Next Part, on to running workflows in Alfresco Embedded mode and running alfresco scripts in the workflow.



John said...

This is a great series of articles...can you elaborate on this comment?
"As of Alfresco 3.1, the jBPM 3.2 GA is supported with some patches"

What patches are needed, and what do they provide? Are they available online or do they need to be acquired through Alfresco support?

edlovesjava said...

Thanks John for pointing this line out. Upon further review, Alfresco Enterprise 3.1 is now shipping with jbpm 3.2.2, without patches. Previous versions were JBPM 3.2 GA with a patched jar.

Ganesh Kolhe said...

Thanks john for such nice article. But I would like to know the role of Active MQ here, why we need that?