Dear Community,
I am implementing a Tasklistener that is triggered on task complete. I want to get all variables that were submitted during the corresponding task complete.
However, if I am using
Map<String, Object> variables = delegateTask.getVariables();
I am getting all variables in the process instance. Is there a way to get only the newly submitted ones?
Any hint is appreciated.
Hi @philipp.hehnle,
If variables are submitted as local variables then you can read them using the below code.
delegateTask.getVariablesLocal()
And if needed, you can send back to process instance variables by assigning to corresponding Outputs
I did a further research and I think, what I am supposed to use is a custom HistoryEventHandler.
Because what I am trying to achieve is to save all variables to a history database. However, when I am implementing my custom HistoryEventHandler I don’t have access to the variables.
public class CustomHistoryEventHandler implements HistoryEventHandler {
@Override
public void handleEvent(HistoryEvent historyEvent) {
}
I understand I have to cast the historyEvent to a appropriate child event. However, I do not find any child class that grants me access to the submitted variables. For example, casting to HistoricTaskInstanceEventEntity will grant me access to assignee, due date, etc. but not to variables.
Furthermore, extending HistoryEventHandler will result in camunda not writing events to the camunda history table. The docs state that instead one should use CompositeHistoryEventHandler
(History and Audit Event Log | docs.camunda.org) But I don’t find an example for CompositeHistoryEventHandler either. In this thread, it was already mentioned that there is no Documentation: External provider for history audit log in Spring Boot - #6 by Niall
Hello @philipp.hehnle ,
to access variable data you probably want to take a look at the class HistoricVariableUpdateEventEntity.You can wrap it into a HistoricVariableInstanceEntity using the constructor to finally access the value. Obviously you will need check for event type before.
new HistoricVariableInstanceEntity((HistoricVariableUpdateEventEntity) historyEvent)
Towards your second question, there are two approaches:
1.From Camunda version 7.12 on you can register your listener als custom history event handler. Then, incase you leave the configuration flag “enableDefaultDbHistoryEventHandler” at its default value Camunda will instantiate a composite handler including the default handler.
2. Another option, also for possibly older versions of Camunda, is to manually create a CompositeHistoryEventHandler. You could do this e. g. within a plugin as follows:
HistoryEventHandler configuredHandler = configuration.getHistoryEventHandler();
if (configuredHandler == null) {
configuration.setHistoryEventHandler(new CompositeDbHistoryEventHandler(this));
} else {
configuration.setHistoryEventHandler(new CompositeHistoryEventHandler(configuredHandler, this));
}
I can also link you relevant code snippets of the camunda codebase if you like.
I hope this helps!
Adagatiya
This is a good hint. However, there is no relation to a task. I get the value of the variable update but I do not know the task the variable was updated in.
Probably, I have to correlate the task completion and the variable update via a timestamp. This is very dirty, though.
Hi @philipp.hehnle ,
in the previous answer I described how you can transform the event into a HistoricVariableInstanceEntity. This object also includes a task id, execution id and so on.
Actually for this information the transformation would not even be neccessary as already the HistoricVariableUpdateEventEntity contains such information, because it inherits from HistoricDetailEventEntity.
I tried to get the taskid, but the taskid is always null.
There is no relation to a task.
I think the logic is that the variable update is a single event that can happen during a task complete or another action and hence it is considered to have no relation.
Hi @philipp.hehnle ,
you could also possibly take the activity instance id.
I also wondered when the task id will be populated because in my local database it is always empty as well and I found this thread: Why is TASK_ID_ column always null in act_hi_detail table? - #2 by thorben
Hope this helps!
Adagatiya
1 Like
When I am using the activity instance id I am sometimes getting something like this: Activity_1rr9jdj:300743b5-2225-11ed-a0be-38f3ab40d3cd (which is probably the task definition id) and sometimes I am getting an id like b4c05129-22b9-11ed-944e-38f3ab40d3cd
Hi @philipp.hehnle ,
Usually it will be “activityId:anyid” where “anyId” ist the result of a IdGenerator implementation. If the activity id is the same as the process definition id (not the process definition key) it will be used without any suffix. As reference you can look here and here.
Now towards the original question. You want to retrieve changed variables within a task on completion. What do you want to do with these changes afterwards?
You thought about a HistoryEventHandler on variable updates. Another option would be
- Implementing a HistoryEventHandler which processes Complete-Events
- Then you would have a HistoricTaskInstanceEventEntity
- Now you could query the historic data with the activityInstanceId of your task intance event.
If this fits your usecase depends on when you want to be notified. On any variable update or only on task completion.
I am already using both TaskInstanceEventEntity and HistoricVariableUpdateEventEntity. So, I have all task completions and all variable updates. So, I am looking for a connection between them.
I want to implement a history, which shows the variables that were created/changed by a user in a user task. I do not want to show the technical variables that are created during service tasks or variables that are passed from a parent process (Call Activity).
So, anyhow, I have to find a field that connects the the variable update and the task completion. I guess I can use activityInstanceId. However, this is complicated. The variable update event occurs before the task completion event. So, it is difficult to determine if a variable update is triggered by a user.
Hi @philipp.hehnle ,
you are right. Variable updates come first and at the end the complete operation itself will be processed. That’s why I proposed the solution from my post before. You would be able to get all changes within the activity by creating a HistoricDetailQuery which already offers filtering by activity instance id.
By the way, this would already be possible without a custom history event handler. The data is already available by camunda, obviously without being able to react to changes manually which might even not be neccessary if you only want to display changes.
Edit:Or do you have user-changes and system-changes of variables within one activity and you want somehow know which were part of the complete operation and which not? In that case the operation id might be what you are looking for. Types of operation can be “Complete”, “SetVariable” etc.
Hope this helps!
Adagatiya
In the end, I ended up writing the variable updates with the corresponding activity instance id to the database. When the task completion event occurs I take the activity instance id to find the corresponding variable updates (that are already in the db) and connect them.