👨🏫Sometimes it is useful to read the process data of old tasks to display them on a history view or to extract statistic data.
There is also an Public API available for thatITask.getEndTaskData()
and ITask.getStartTaskData()
. The first returns the process data at the end of a task's process (at a Process End or Task Switch Input). The second returns the process data at the start of a task's process (at a Request Start or Task Switch Output).
These methods work perfectly as long as you only have one version of your project deployed (one PMV). As soon as you deploy another version of your project to a new PMV the problems start. Note if you redeploy a newer version of your project to the same one PMV you are safe. The problems start with the introduction of another PMV.
👉Let us assume the following situation:
- You have two PMVs ProcessData$1 and ProcessData$2
- The process data class is
process.data.MyProcessData
- You have tasks living in ProcessData$1 (because their cases have been started in ProcessData$1)
- You have tasks living in ProcessData$2 (because their cases have been started in ProcessData$2)
Now the process data of tasks living in ProcessData$1 are of type process.data.MyProcessData
of ProcessData$1 and the process data of tasks living in ProcessData$2 are of type process.data.MyProcessData
of ProcessData$2.
⚠ Note, that for Axon Ivy despite the types have the same name are not the same type!
😱This causes a IvyScriptCastException
if you try to cast the process data of a task living in ProcessData$1 to the type process.data.MyProcessData
of ProcessData$2. The error message looks like this:
IvyScriptCastException 'Cannot cast object of type process.data.MyProcessData(IvyProjectClassLoader [project=1_1_1] ...) to process.data.MyProcessData(IvyProjectClassLoader [project=1_1_2] ...)'
. Note, that the projects mentioned are different. 1_1_1 is for ProcessData$1 and 1_1_2 is for ProcessData$2.
👍 A simple fix for this is instead of casting to the process.data.MyProcessData
use the the base CompositeData
class. This class has a method called get
where you can get the value of a field of the process data class. Let us assume the class process.data.MyProcessData
has a field called name of type String. Then you can use the following code to read this field from all tasks in any PMV:
CompositeObject processData = task.getEndProcessData();
if (#processData == null) {
processData = task.getStartProcessData();
}
if (#processData != null) {
ivy.log.info("Task " + task.getId() + " has process data " + processData.get("name"));
}
If the field itself is a project data class again. Cast it to a CompositeObject
and call the get method on it again to further dig into the object tree.
👌 Another solution is to use the method toType
to map the process data object of type process.data.MyProcessData
of ProcessData$1 to an object of type process.data.MyProcessData of ProcessData$1.
Note, that only those fields are mapped that exists in both versions of the process.data.MyProcessData
class and have the same type.
MyProcessData data = processData.toType(MyProcessData.class) as MyProcessData;
ivy.log.info("Task " + task.getId() + " has process data "+ data.name);
Hope this helps handling process data of tasks in your projects.
⚠ Note, that we recommend storing important business information either in business data or external databases instead of the task's process data.
See also the attached demo project to learn more about this topic.
processdata.zip