Introduction to Activiti BPM
Activiti is an open-source Business Process Management (BPM) platform that enables organizations to model, automate, and optimize business processes. It provides a lightweight, Java-based workflow and BPM engine that helps bridge the gap between business analysts and developers. Activiti is crucial for organizations looking to improve efficiency, maintain consistency, and gain visibility into their business processes.
Core Concepts and Components
Key Architecture Components
- Process Engine: The central component that executes BPMN 2.0 processes
- Process Definition: XML representation of a business process in BPMN 2.0 format
- Process Instance: A running execution of a process definition
- Task: A unit of work performed by a user or system
- Service Task: Automated task executed by the system
- User Task: Manual task performed by a human user
- Execution: Represents a path of execution through the process
Important Database Tables
Table Name | Purpose |
---|---|
ACT_RE_* | Repository tables storing static information like process definitions |
ACT_RU_* | Runtime tables storing runtime data of process instances |
ACT_HI_* | History tables storing historical data of completed processes |
ACT_ID_* | Identity tables storing user and group information |
ACT_GE_* | General tables storing general data like properties |
BPMN 2.0 Elements in Activiti
Events
- Start Events: Trigger the beginning of a process (
startEvent
) - End Events: Indicate the completion of a process (
endEvent
) - Intermediate Events: Occur between start and end events
- Timer Events: Trigger based on time (
intermediateCatchEvent
withtimerEventDefinition
) - Message Events: Triggered by messages (
intermediateCatchEvent
withmessageEventDefinition
) - Signal Events: Used for broadcast communication (
intermediateCatchEvent
withsignalEventDefinition
)
- Timer Events: Trigger based on time (
Activities
- Tasks:
- User Task:
<userTask id="approveTask" name="Approve Request" activiti:assignee="${initiator}" />
- Service Task:
<serviceTask id="sendEmail" activiti:class="org.example.EmailTask" />
- Script Task:
<scriptTask id="calculateValues" scriptFormat="groovy">
- Business Rule Task:
<businessRuleTask id="evaluateRule" activiti:ruleVariablesInput="${data}" />
- Receive Task:
<receiveTask id="waitForMessage" />
- User Task:
- Gateways:
- Exclusive Gateway (XOR):
<exclusiveGateway id="approvalDecision" />
- Parallel Gateway (AND):
<parallelGateway id="forkProcess" />
- Inclusive Gateway (OR):
<inclusiveGateway id="conditionalPaths" />
- Event-based Gateway:
<eventBasedGateway id="waitForEvent" />
- Exclusive Gateway (XOR):
- Subprocesses:
- Embedded Subprocess:
<subProcess id="reviewSubProcess">
- Call Activity (Reusable Subprocess):
<callActivity id="invoiceProcess" calledElement="invoiceProcess">
- Event Subprocess:
<subProcess id="errorHandler" triggeredByEvent="true">
- Embedded Subprocess:
Flow Elements
- Sequence Flow:
<sequenceFlow id="flow1" sourceRef="task1" targetRef="task2" />
- Conditional Flow:
<sequenceFlow id="flow2" sourceRef="gateway" targetRef="task3"><conditionExpression>${amount > 1000}</conditionExpression></sequenceFlow>
- Default Flow:
<sequenceFlow id="defaultFlow" sourceRef="gateway" targetRef="task4" default="true" />
Setting Up Activiti
Maven Dependencies
xml
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-engine</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>6.0.0</version>
</dependency>
Process Engine Configuration
java
// Standalone configuration
ProcessEngine processEngine = ProcessEngineConfiguration
.createStandaloneProcessEngineConfiguration()
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
.setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000")
.setJdbcDriver("org.h2.Driver")
.setJdbcUsername("sa")
.setJdbcPassword("")
.buildProcessEngine();
// Spring configuration
@Bean
public ProcessEngineConfiguration processEngineConfiguration() {
SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
configuration.setDataSource(dataSource);
configuration.setTransactionManager(transactionManager);
configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
return configuration;
}
API Usage Examples
Deploying Process Definitions
java
// Deploy from classpath resource
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("processes/approval-process.bpmn20.xml")
.name("Approval Process")
.deploy();
// Deploy from input stream
InputStream inputStream = new FileInputStream(new File("/path/to/process.bpmn20.xml"));
Deployment deployment = processEngine.getRepositoryService()
.createDeployment()
.addInputStream("process.bpmn20.xml", inputStream)
.deploy();
Starting Process Instances
java
// Start by process definition key
Map<String, Object> variables = new HashMap<>();
variables.put("requestor", "John");
variables.put("amount", 5000);
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceByKey("approvalProcess", variables);
// Start by process definition ID
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceById("approvalProcess:1:1267", variables);
Working with Tasks
java
// Query for tasks
List<Task> tasks = processEngine.getTaskService()
.createTaskQuery()
.taskAssignee("manager")
.processVariableValueEquals("amount", 5000)
.list();
// Complete a task
processEngine.getTaskService().complete(task.getId());
// Complete with variables
Map<String, Object> variables = new HashMap<>();
variables.put("approved", true);
processEngine.getTaskService().complete(task.getId(), variables);
// Claim and unclaim tasks
taskService.claim(task.getId(), "john");
taskService.unclaim(task.getId());
Query APIs
java
// Process instance queries
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
// Historic process instance queries
HistoricProcessInstance historicInstance = historyService
.createHistoricProcessInstanceQuery()
.processInstanceId(processInstanceId)
.finished()
.singleResult();
// Execution queries
List<Execution> executions = runtimeService.createExecutionQuery()
.processVariableValueEquals("approved", true)
.list();
Working with Process Variables
Setting Variables
java
// Set variable on execution
runtimeService.setVariable(executionId, "approved", true);
// Set multiple variables
Map<String, Object> variables = new HashMap<>();
variables.put("approved", true);
variables.put("comment", "Looks good");
runtimeService.setVariables(executionId, variables);
// Set local variables (scope limited to current activity)
runtimeService.setVariableLocal(executionId, "temporaryData", data);
Retrieving Variables
java
// Get single variable
Boolean approved = (Boolean) runtimeService.getVariable(executionId, "approved");
// Get all variables
Map<String, Object> variables = runtimeService.getVariables(executionId);
// Get variables with specific names
List<String> varNames = Arrays.asList("approved", "comment");
Map<String, Object> specificVars = runtimeService.getVariables(executionId, varNames);
Transaction Management
Using Transactions
java
// Programmatic transaction
TransactionContext transactionContext = Context.getCommandContext().getTransactionContext();
try {
// Your operations here
transactionContext.commit();
} catch (Exception e) {
transactionContext.rollback();
}
// With Spring (@Transactional)
@Transactional
public void executeProcessLogic() {
// Process operations here, Spring handles the transaction
}
Handling Process Events
Event Listeners
java
// Create event listener
public class ProcessStartListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) {
String processInstanceId = execution.getProcessInstanceId();
// Logic to handle process start
}
}
// Add to process definition
<startEvent id="start">
<extensionElements>
<activiti:executionListener class="org.example.ProcessStartListener" event="start" />
</extensionElements>
</startEvent>
Task Listeners
java
// Task listener implementation
public class TaskAssignmentListener implements TaskListener {
@Override
public void notify(DelegateTask delegateTask) {
String assignee = delegateTask.getAssignee();
// Logic for task assignment
}
}
// Add to task definition
<userTask id="approveTask" name="Approve Request">
<extensionElements>
<activiti:taskListener event="assignment" class="org.example.TaskAssignmentListener" />
</extensionElements>
</userTask>
Common Challenges and Solutions
Challenge | Solution |
---|---|
Process deployment fails | Check BPMN XML syntax, ensure resources are in classpath, verify database connection |
Task not appearing for users | Check assignee configuration, verify user/group mappings, check task query parameters |
Process instance stuck | Use management APIs to find suspended executions, check async continuations, verify service task implementations |
Performance issues | Implement proper indexing on database, tune history level, optimize queries, consider alternative execution strategies |
Debugging process execution | Enable debug logging, use Activiti Explorer UI, analyze runtime tables, create custom event listeners |
Best Practices
Design Best Practices
- Keep processes simple and modular
- Use call activities for reusable subprocesses
- Model error handling explicitly with boundary events
- Document process with BPMN annotations
- Validate processes before deployment
Implementation Best Practices
- Follow naming conventions for process definitions and elements
- Minimize the amount of data stored in process variables
- Use proper transaction boundaries
- Implement proper exception handling
- Set appropriate history levels
Deployment Best Practices
- Version your process definitions
- Use category and tenant concepts for organization
- Consider using separate database for history
- Implement proper monitoring and auditing
- Create deployment scripts/procedures
Activiti Extensions and Hooks
Form Extensions
xml
<userTask id="approveTask" name="Approve Request">
<extensionElements>
<activiti:formProperty id="approved" name="Approved" type="boolean" required="true" />
<activiti:formProperty id="comments" name="Comments" type="string" />
</extensionElements>
</userTask>
Service Task Extensions
xml
<serviceTask id="sendEmail" activiti:class="org.example.EmailTask">
<extensionElements>
<activiti:field name="to" stringValue="manager@example.com" />
<activiti:field name="subject" expression="${process.name}: New request" />
</extensionElements>
</serviceTask>
Execution Listeners
xml
<process id="myProcess">
<extensionElements>
<activiti:executionListener class="org.example.ProcessStartListener" event="start" />
<activiti:executionListener class="org.example.ProcessEndListener" event="end" />
</extensionElements>
<!-- Process elements -->
</process>
Resources for Further Learning
- Official Documentation: Activiti User Guide
- Books:
- “Activiti in Action” by Tijs Rademakers
- “Mastering Activiti” by Jakub Holý
- Online Courses:
- Alfresco Activiti Developer Course
- Camunda BPM (similar concepts to Activiti)
- Community Resources:
- Tools:
- Activiti Designer Eclipse Plugin
- BPMN.io (online modeler)
- Activiti Explorer Web Application
Activiti vs Other BPM Platforms
Feature | Activiti | Camunda | jBPM | Flowable |
---|---|---|---|---|
Core Engine | Java-based, lightweight | Java-based, robust | Java-based, integrated with KIE | Fork of Activiti, enhanced |
Standards | BPMN 2.0 | BPMN 2.0, DMN, CMMN | BPMN 2.0, DMN | BPMN 2.0, DMN, CMMN, Forms |
UI Components | Basic Explorer | Cockpit, Tasklist, Admin | Designer, Console | Admin UI, Task App, IDM |
Cloud Support | Limited | Good | Good | Excellent |
Community | Active | Very active | Active | Growing |
Commercial Support | Available | Available | Available through Red Hat | Available |
Integration | Good | Excellent | Excellent with Red Hat | Excellent |
This cheatsheet provides a comprehensive reference for working with Activiti BPM, covering everything from basic concepts to advanced implementation techniques. Use it to streamline your business process development and management with Activiti.