Activiti is an open-source BPMN platform distributed under the Apache license. It's written in Java and thus can run in any Java application, on a server, on a cluster or in the cloud. Activiti integrates perfectly with Spring, it is extremely lightweight and based on simple concepts.  Here's a first tutorial which shows you a first taste of this very interesting workflow and Business Process Management (BPM) Platform.

Activiti does not require an installation as it's made up of a set of JAR files. We will just install the Activiti Eclipse plugin so that we can design our process from a Development IDE.

From the Eclipse upper menu, select Help | Install New Software. Choose to add the following Repository: http://activiti.org/designer/update

activiti tutorial

Next, check Activiti BPMN Designer as displayed by the following picture:

activiti tutorial

Click on Next and Finish the installation. You will need restarting Eclipse at the end of it.

Create a simple Standalone Project

Ok. Now let's create a standalone application which uses Activiti API to start process instances and generates a Task list. To include the Activiti JAR and its dependent libraries, we advise using Maven as it simplifies dependency management on both our and your side a lot. Hence create a new Maven project at first:

$ mvn archetype:generate -DgroupId=com.mastertheboss.activiti -DartifactId=activitiDemo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

Now we will need to include Activiti core libraries and some dependencies in the pom.xml file. Here is the list of dependencies we will add:

 <properties>
   <activiti-version>5.18.0</activiti-version>
</properties>

<dependencies>
   <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-engine</artifactId>
      <version>${activiti-version}</version>
   </dependency>
   <dependency>
      <groupId>org.activiti</groupId>
      <artifactId>activiti-spring</artifactId>
      <version>${activiti-version}</version>
   </dependency>
   <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.3.168</version>
   </dependency>
   <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.6</version>
   </dependency>
   <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-jdk14</artifactId>
      <version>1.7.6</version>
   </dependency>
</dependencies>

Done with the setup, we will now create a simple Process using the BPMN Designer.


Create a Process Diagram

Now Add an Activiti Diagram to your process from the menu File | New | Other | Activiti | Activiti Diagram.

activiti tutorial8


Create a sample process in the resources folder of your Project. In our case, we will name the process MyProcess and we will save it in resources/DemoProcess.bpmn.
By clicking on it, the visual editor of Eclipse will appear. We will create a simple process definition which contains a ServiceTask, an Exclusive Gateway and two User Tasks. Here's a picture of our process:

activiti tutorial bpmn 2.0

Now you need to configure each node. Select the Properties tab. We will configure first  the ServiceTask which simply recalls a callback method of a Java class implementing the JavaDelegate interface.

activiti tutorial

The Class we will simulate the choice between a Simple Task and a Complex Task which should be assigned to different actors:

package com.mastertheboss.task;

import org.activiti.engine.delegate.DelegateExecution;

public class JavaService1 implements org.activiti.engine.delegate.JavaDelegate {

	public void execute(DelegateExecution arg0) throws Exception {

		if (isComplexTask()) {
			System.out.println("This is a complex task!");
			arg0.setVariable("result", "1");
		}	
		else  {
			System.out.println("This is a simple task!");			
		    arg0.setVariable("result", "0");
	    }

	}

	private boolean isComplexTask() {
		return Math.random() < 0.5;
	}

}

As you can see, this project contains two Tasks: we will assign each of them to a different Actor. Say, we will assign the first one to kermit and the second one to gonzo. Here's the Properties for the first Task:

activiti tutorial

And, in turn for the second Task:

activiti tutorial

Finally we will configure the exclusiveGateway which can be seen as a Decision node. Depending on the value of "result" it will lead the process definition to two different Tasks. On each sequence flow choose a condition Expression: for example in upper Flow we will set the following condition:

activiti tutorial

Conversely, the lower Flow will capture the condition where result = 0:

activiti tutorial

Great, you are done with building your first Activiti Process.


Write a simple Activiti Client

Ok. Now the process is completed. We will add a minimal API to start the Process and claim the Tasks generated. 

package com.mastertheboss.activiti.DemoActiviti;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
 
public class App 
{
    public static void main( String[] args )
    {
    	 final ProcessEngine processEngine = ProcessEngineConfiguration
                 .createStandaloneInMemProcessEngineConfiguration()
                 .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE)
                 .setJobExecutorActivate(true)
                 .setDatabaseSchemaUpdate("drop-create")
                 .buildProcessEngine();

         final RepositoryService repositoryService = processEngine
                 .getRepositoryService();
         repositoryService.createDeployment()
                 .addClasspathResource("DemoProcess.bpmn").deploy();
         final Map<String, Object> variables = new HashMap<String, Object>();

 
         final RuntimeService runtimeService = processEngine.getRuntimeService();
       
         ProcessInstance id = runtimeService.startProcessInstanceByKey("myProcess", variables);
         System.out.println("Started Process Id: "+id.getId());
         
         try {
             final TaskService taskService = processEngine.getTaskService();
             final List<Task> tasksSenior = taskService.createTaskQuery().taskAssignee("kermit").list();
             final List<Task> tasksJunior = taskService.createTaskQuery().taskAssignee("gonzo").list();
           
     
             if (tasksSenior.size() > 0) {
                  System.out.println("Found task for Senior " +tasksSenior.get(0).getName() );
                 taskService.claim(tasksSenior.get(0).getId(), "kermit");
 
                 System.out.println("Task " +tasksSenior.get(0).getName() +" terminated");
             }
             else if (tasksJunior.size() > 0) {
                 System.out.println("Found task for Junior " +tasksJunior.get(0).getName() );
                 taskService.claim(tasksJunior.get(0).getId(), "gonzo");

                System.out.println("Task " +tasksJunior.get(0).getName() +" terminated");
            }
             
         } catch (Exception e) {
        	 System.out.println(e.getMessage());
         } finally {

         }
          processEngine.close();
    }
}

As you can see, the central starting point is the ProcessEngine. From the ProcessEngine, you can obtain the various services that contain the workflow/BPM methods.

Typically, there will be only one ProcessEngine instance needed in a end-user application. Building a ProcessEngine is done through a ProcessEngineBuilder instance and is a costly operation which should be avoided. For that purpose, it is advised to store it in a static field or JNDI location (or something similar).
 
Once started the class, an instance of the ProcessInstance will be created. The TaskService API is then used to retrieve the list of Tasks which can be claimed by the users "kermit" and "gonzo". Depending on the Random number generated, the Task can be claimed by one of the two users, therefore a typical output of the execution would look like this:

This is a simple task!
Started Process Id: 5
Found task for Junior SimpleTask
Task SimpleTask terminated

You can download the source code for this article at: https://github.com/fmarchioni/mastertheboss/tree/master/activiti/standalone/DemoActiviti

0
0
0
s2smodern