1 Step by Step Description
1.1 Get a list of all Workflow Instances
The Workflow Instance Service may be used to get references to all existing workflow instances. The service is accessible through the function "CONTEXT()".
1CONTEXT().getWorkflowInstanceService().getWorkflowInstances()
This statement returns a Java list of "WorkflowInstance" instances. You can convert this list into an indexed collection:
1java.util.List $list := CONTEXT().getWorkflowInstanceService().getWorkflowInstances();
2Indexed WorkflowInstance $workflowInstances := ToIndexed($list, WorkflowInstance);
Now you may iterate over this collection and perform your upgrade actions:
1WorkflowInstance $workflowInstance;
2ForEach $workflowInstance In $workflowInstances Do
3 // todo: upgrade workflow instance
4End
1.2 Filter Workflow Instances by Status and Workflow Id
Most of the time you may want to filter the workflow instances. You may want to restrict the upgrade to active workflow instances:
1String $status := $workflowInstance.getStatus();
2If $status == 'Active' Then
3 // todo
4End
Maybe you only want to upgrade workflow instances for the workflow "AccountOpening". You can use the following statement to get the id of the root workflow in your workflow instance:
1String $workflowId := $workflowInstance.getWorkflowTokenSet().getWorkflowVersionRef().getId();
2If $workflowId == 'AccountOpening' Then
3 // todo
4End
1.3 Lock Workflow Instances during Modification
It is possible that other Appway components access the same workflow instance exactly at the same time you're updating it. To prevent this, you should lock the workflow instance during this time. Locking requires you to know the workflow instance id.
Note that the "workflow instance id" isn't the same value as the "workflow id". You can get the workflow instance id by calling "getId()" on the workflow instance object.
1String $workflowInstanceId := $workflowInstance.getId();
2CONTEXT().getWorkflowInstanceService().lockWorkflowInstance($workflowInstanceId);
3Try
4 // todo
5Finally
6 CONTEXT().getWorkflowInstanceService().unlockWorkflowInstance($workflowInstanceId);
7End
You have to make sure that you unlock the workflow instance, even if there has been an error. Otherwise other components may not access the workflow instance anymore.
1.4 Change Version Filter
Upgrading workflow instances usually requires a modification of the version filter. Every workflow instance has a version filter. You may get and set it using the methods "getVersionFilter()" and "setVersionFilter(...)":
1$workflowInstance.setVersionFilter(VersionFilter('HeadFilter'))
The function "VersionFilter(...)" may be used to construct a new version filter. The parameter for this function is a version filter in string representation. There are many different version filter types, but only three of them are frequently used: "TimestampFilter", "HeadFilter" and "LatestCommittedFilter".
1.4.1 TimestampFilter
Most of the time you will use TimestampFilter. This is the default version filter type used by workflow instances.
The TimestampFilter has one "argument", the timestamp it should use to filter and select versions. If you have to construct a string representation of a TimestampFilter, you simply have to append the timestamp (in milliseconds since January 1st, 1970 00:00 GMT) to the string "TimestampFilter-". You can do this statically, or you can calculate the value given an arbitrary date:
1Date $date := PARSEDATE('2009-01-01');
2String $versionFilterString := JOIN('TimestampFilter-', TIMESTAMP($date));
3$workflowInstance.setVersionFilter(VersionFilter($versionFilterString));
If can omit the timestamp argument and only pass "TimestampFilter" as string. In this case, Appway automatically uses the current date and time for the timestamp.
1.4.2 HeadFilter
HeadFilter is used almost only for debug and test purposes. If you start a workflow instance from within the Appway Studio, it is started with a HeadFilter version filter. This way, you may modify the business objects (e.g. the workflow model) and immediately see the result of your change.
HeadFilter as multiple optional arguments. They are used to specify whether objects marked as "deleted" should be used or not. It is very unlikely that you will ever use them.
1String $versionFilterString := 'HeadFilter'
1.4.3 LatestCommittedFilter
LatestCommittedFilter is used to always select the newest (committed) business object versions. Like HeadFilter, this is an "undeterministic" filter, because it tends to return different business objects version over time. Make sure that you understand the implications before you use this version filter.
LatestCommittedFilter has no arguments.
1String $versionFilterString := 'LatestCommittedFilter'
1.5 Upgrade referenced Screenflow Instances
A workflow instance may refer to screenflow instances. Every screenflow instance has its own version filter. Therefore if you upgrade a workflow instance, you should probably upgrade the referenced screenflow instances as well. The first step is to find all referenced screenflow instances. Screenflow instances are referenced using "ScreenflowTaskToken" instances, a special workflow token type. Given a workflow instance, you can use the following code to get a list of all workflow tokens:
1java.util.List $list2 := $workflowInstance.getWorkflowTokenSet().getTokens(true);
2Indexed WorkflowToken $workflowTokens := ToIndexed($list2, 'WorkflowToken');
Next, you can iterator over this collection and check if the elements are ScreenflowTaskToken (Java class "com.nm.sdk.data.workflow.runtime.tokens.ScreenflowTaskToken").
1WorkflowToken $workflowToken;
2ForEach $workflowToken In $workflowTokens Do
3 If $workflowToken isa com.nm.sdk.data.workflow.runtime.tokens.ScreenflowTaskToken Then
4 // todo
5 End
6End
If this is the case, you can extract the screenflow instance id and screenflow session id from the workflow token:
1String $screenflowInstanceId := CAST(com.nm.sdk.data.workflow.runtime.tokens.ScreenflowTaskToken, $workflowToken).getScreenflowInstanceId()
Given the screenflow instance id, you can load the screenflow instance.
1ScreenflowInstance $screenflowInstance := CONTEXT().getScreenflowInstanceService().getScreenflowInstance($screenflowInstanceId);
2If $screenflowInstance != null Then
3 // todo
4End
A screenflow instance has a method "setVersionFilter(...)":
1$screenflowInstance.setVersionFilter(VersionFilter($versionFilterString))
You should set the same version filter for the workflow instance and every referenced screenflow instance.
1.6 Save modified Workflow Instance and Screenflow Instances
After changing the version filter (or any other property of a workflow instance or screenflow instance), you should mark the instance as "modified". You can to that by calling the method "touchModificationTime()":
1$workflowInstance.touchModificationTime();
2$screenflowInstance.touchModificationTime();
After this, the instance will be persisted by a background job which runs by default every 5 minutes. You may also force an immediate save operation:
1CONTEXT().getWorkflowInstanceService().updateWorkflowInstance($workflowInstance);
2CONTEXT().getScreenflowInstanceService().updateScreenflowInstance($screenflowInstance);
Example Script
You can download the following script from this URL:
http://support.numcom.com/htdocs/downloads/public/howtos/UpgradeWorkflowInstances.txt
1Script
2 //
3 // prepare new version filter
4 //
5 Date $date := PARSEDATE('2009-01-01');
6 String $versionFilterString := JOIN('TimestampFilter-', TIMESTAMP($date));
7 //
8 // get list of workflow instances
9 //
10 java.util.List $list := CONTEXT().getWorkflowInstanceService().getWorkflowInstances();
11 Indexed WorkflowInstance $workflowInstances := ToIndexed($list, WorkflowInstance);
12 //
13 // for every workflow instance ...
14 //
15 WorkflowInstance $workflowInstance;
16 ForEach $workflowInstance In $workflowInstances Do
17 //
18 // check status of workflow instance
19 //
20 String $status := $workflowInstance.getStatus();
21 If $status == 'Active' Then
22 //
23 // update only "AccountOpening" workflows
24 //
25 String $workflowId := $workflowInstance.getWorkflowTokenSet().getWorkflowVersionRef().getId();
26 If $workflowId == 'AccountOpening' Then
27 //
28 // lock workflow instance
29 //
30 String $workflowInstanceId := $workflowInstance.getId();
31 CONTEXT().getWorkflowInstanceService().lockWorkflowInstance($workflowInstanceId);
32 //
33 Try
34 //
35 // set version filter and mark workflow instance as modified
36 //
37 $workflowInstance.setVersionFilter(VersionFilter($versionFilterString));
38 $workflowInstance.touchModificationTime();
39 // CONTEXT().getWorkflowInstanceService().updateWorkflowInstance($workflowInstance);
40 //
41 // get list of all workflow tokens
42 //
43 java.util.List $list2 := $workflowInstance.getWorkflowTokenSet().getTokens(true);
44 Indexed WorkflowToken $workflowTokens := ToIndexed($list2, 'WorkflowToken');
45 //
46 // for every workflow token ...
47 //
48 WorkflowToken $workflowToken;
49 ForEach $workflowToken In $workflowTokens Do
50 //
51 // check if workflow token is a "ScreenflowTaskToken"
52 //
53 If $workflowToken isa com.nm.sdk.data.workflow.runtime.tokens.ScreenflowTaskToken Then
54 //
55 // try to find screenflow instance
56 //
57 String $screenflowInstanceId := CAST(com.nm.sdk.data.workflow.runtime.tokens.ScreenflowTaskToken, $workflowToken).getScreenflowInstanceId();
58 ScreenflowInstance $screenflowInstance := CONTEXT().getScreenflowInstanceService().getScreenflowInstance($screenflowInstanceId);
59 If $screenflowInstance != null Then
60 //
61 // set version filter and mark screenflow instance as modified
62 //
63 $screenflowInstance.setVersionFilter(VersionFilter($versionFilterString));
64 $screenflowInstance.touchModificationTime();
65 // CONTEXT().getScreenflowInstanceService().updateScreenflowInstance($screenflowInstance);
66 End
67 End
68 End
69 //
70 Finally
71 //
72 // unlock workflow instance
73 //
74 CONTEXT().getWorkflowInstanceService().unlockWorkflowInstance($workflowInstanceId);
75 End
76 End
77 End
78 End
79End