This example demonstrates how to register custom history levels by implementing a process engine plugin.
This examples adds two history levels:
- The
custom-variable
history level behaves like the normal full history except that only variables with a specific name pattern are saved to history. This way you can reduce the number of variables tracked and don't pollute the history with auxiliary variables. - The
per-process
history level allows you to specify the history level per process with the camunda properties. This allows you to disable or reduce the history for unimportant processes. And even change the history level of new instances by redeploying an adjusted process definition.
Note: This is example code and not intended to be used as is in a production setting (especially the per-process
history level).
It rather highlights the mechanics on how a custom history level can be implemented.
If you are interested in this feature, make sure you understand the code and its limitations or ask for help in the Camunda forum.
The process model is composed of one task which adds 4 variables to the process:
public void execute(DelegateExecution execution) throws Exception {
execution.setVariable("foo", "bar");
execution.setVariable("hello", "world");
execution.setVariable("action-id-hist", "important");
execution.setVariable("camunda-hist", "rocks");
}
The process engine plugin is used to register the custom history levels in the preInit
method. Additionally, in the postInit
method all registered custom history levels are
added to the PerProcessHistoryLevel
instance. This way also custom history levels
can be specified per process.
public class CustomHistoryLevelProcessEnginePlugin extends AbstractProcessEnginePlugin {
public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
List<HistoryLevel> customHistoryLevels = processEngineConfiguration.getCustomHistoryLevels();
if (customHistoryLevels == null) {
customHistoryLevels = new ArrayList<HistoryLevel>();
processEngineConfiguration.setCustomHistoryLevels(customHistoryLevels);
}
customHistoryLevels.add(CustomVariableHistoryLevel.getInstance());
customHistoryLevels.add(PerProcessHistoryLevel.getInstance());
}
public void postInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
PerProcessHistoryLevel.getInstance()
.addHistoryLevels(processEngineConfiguration.getCustomHistoryLevels());
}
}
The idea of the custom-variable
history level is that only some variables are
saved to history. In this example we use a variable name pattern to distinguish
these variables. Every variable which name ends with -hist
will be saved to
history; all others are ignored. For the other history events (Process Instance, Activity
Instance) full history is written.
public class CustomVariableHistoryLevel implements HistoryLevel {
public static final CustomVariableHistoryLevel INSTANCE = new CustomVariableHistoryLevel();
protected static final List<HistoryEventType> VARIABLE_EVENT_TYPES = new ArrayList<HistoryEventType>();
static {
VARIABLE_EVENT_TYPES.add(HistoryEventTypes.VARIABLE_INSTANCE_CREATE);
VARIABLE_EVENT_TYPES.add(HistoryEventTypes.VARIABLE_INSTANCE_UPDATE);
VARIABLE_EVENT_TYPES.add(HistoryEventTypes.VARIABLE_INSTANCE_DELETE);
}
public static CustomVariableHistoryLevel getInstance() {
return INSTANCE;
}
public int getId() {
return 11;
}
public String getName() {
return "custom-variable";
}
public boolean isHistoryEventProduced(HistoryEventType historyEventType, Object entity) {
return !VARIABLE_EVENT_TYPES.contains(historyEventType)
|| isVariableEventProduced((VariableInstance) entity);
}
protected boolean isVariableEventProduced(VariableInstance variableInstance) {
return variableInstance == null || variableInstance.getName().endsWith("-hist");
}
}
Another interesting idea is to use camunda properties to specify a history level for every process definition separately.
The property is extracted on the creation of a new process instance and a delegate history level is saved for the instance (see the source for the full code).
public boolean isHistoryEventProduced(HistoryEventType historyEventType, Object entity) {
if (entity == null) {
return true;
}
else if (historyEventType == HistoryEventTypes.PROCESS_INSTANCE_START) {
setDelegateHistoryLevel((ExecutionEntity) entity);
}
return isDelegateHistoryLevelEventProduced(historyEventType, entity);
}
The custom history level engine plugin can be activated in the camunda.cfg.xml
:
<!-- activate bpmn parse listener as process engine plugin -->
<property name="processEnginePlugins">
<list>
<bean class="org.camunda.bpm.example.CustomHistoryLevelProcessEnginePlugin" />
</list>
</property>
To enable the custom history configure it also in the camunda.cfg.xml
:
<property name="history" value="custom-variable" />
or
<property name="history" value="per-process" />
If you are impatient, just have a look at the unit tests CustomVariableHistoryLevelTest and PerProcessVariableHistoryLevelTest.
CustomVariableHistoryLevelTest demonstrates that only the correct variables are saved to history. In PerProcessVariableHistoryLevelTest, several processes are deployed with different camunda properties to configure the history level for this process definition. There is also a test where a modified process definition is redeployed to change the history level of new process instances.
- Checkout the project with Git
- Import the project into your IDE
- Inspect the sources and run the unit test in your IDE or with Maven:
mvn clean verify
- You should expect that all test cases pass.