/ Development  

Provide a comment on task completion and ask your consultant to collect it

Hi there “Process Automation” fans,

Welcome to a new installment of “Process Automation” tips.

I see a lot of the OPA platform in projects, I read a lot about the platform, I talk a lot about the platform, write about it, and deep-dive (with R&D sessions) into the platform. Still, I’m amazed by what I see passing by on webservices with lots of questions and answers on how to use them. However, if you want to be a pro, you work with the pros and that’s where you grow during collaboration sessions with them using all the services. Some are undocumented, but this one is; However, the outcome is not always what you expect…


Let’s get right into it…

Boot up the VM and dive into your workspace/project. We’ll create a small entity (product) with a ‘Text’ property prd_name. You can generate all the rest, change the quick-wins (like naming), do a publication for the first tests in runtime…Nothing fancy! WAIT…One thing (actually two; no, three things!)…Open the layout…

  1. …add the ‘Tasks’ panel (because we will execute task actions, like complete).
  2. …add the ‘Progress Bar’ panel (to view the lifecycle instance which we initiate below).
  3. …add the ‘History’ panel for receiving audit details for the product instances.

Now add the ‘History’ building block with a new history log configuration hl_product and add the ‘Lifecycle’ building block; add these states (incl. the state-entry and activity-constructs):

viewmemo_001

Publish it all again, and create a ‘Product’ entity (which will initialize the lifecycle) with a first view like this:

viewmemo_002

Don’t open the task (as we didn’t create any form/layout), but just complete it. Provide an (optional) comment and continue life. Do this for some tasks and ‘Product’ instances, so you have some “commenting” data to play with!

FYI: You can disable this “commenting” feature adding the following property in the ‘wcp.properties’ file and a restart of the TomEE instance: entity.task.showcommentdialog=false

Now also do some ‘Forward’, ‘Delegate’, ‘Suspend’, and ‘Resume’ actions for your tasks to make a full set of data to invest.

From the ‘History’ panel (history for your product!), you will find the comments here:

viewmemo_003

From a database perspective, you’ll find it here (convert_from is a PostgreSQL thing!):

1
2
3
4
5
6
7
SELECT s_when, convert_from(s_history_data, 'UTF8') AS s_history_data 
FROM o2opa_tipsprj_generichistoryloglist
WHERE 1=1
AND s_top_item_id='0800279aadfea1f0b50f736879b9b83c.327682'
AND convert_from(s_history_data, 'UTF8') LIKE '%re=%'
ORDER BY s_when desc
;

We learned about these details before.

AND (after some DB query monitoring), I also found out about this table:

1
SELECT * from notf_memo;

Now, I would expect all my comments would return in this last query, but watch this:

viewmemo_004

I only found two of my comments!? Did we find a bug here? Or is this as designed? You tell me…

Why do I eXplore all these details? Well, for one common call that was not within my knowledge pack (till now!): ViewMemosByTask

It raises questions I’d like to answer:

  1. What does this call do?
  2. How do we run it?
  3. Why do we want to run it?

Q&A section

What does this call do? It returns the memos/comments related to a specified task (got it from the OPA Platform API Reference Guide)

Why do we want to run it? Well, it gives us easy access to the comments on a task by the end-users from a BPM perspective.

How do we run it? Watch and learn…

Add the READ operation from the ‘Web Service’ building block for your entity…

viewmemo_005

For this READ operation, we require a new ‘Application Server Connector’ service container in the ‘System Resource Manager’ artifact which includes the method set of your READ operation:

viewmemo_006

Next, we’ll use the ‘ItemId’ of a ‘Product’ entity instance in runtime (from the URL) and we’ll run the Readproduct service with the ‘Web Service Interface Explorer’:

viewmemo_007

The response will return XML data including a lifecycle instance ID; something like this: 0800279a-adfe-a1f0-b511-39aa010830f2

With this ID, you can call any of these services:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!--This will return the latest task-->
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<GetActivitiesBySource xmlns="http://schemas.cordys.com/notification/workflow/1.0">
<CaseInstanceId>0800279a-adfe-a1f0-b511-39aa010830f2</CaseInstanceId>
<Type>CASE</Type>
</GetActivitiesBySource>
</SOAP:Body>
</SOAP:Envelope>
<!--This will return all the tasks (incl. states)-->
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<GetActivities xmlns="http://schemas.cordys.com/casemanagement/instanceadministration/1.0">
<Query xmlns="http://schemas.cordys.com/cql/1.0">
<Select>
<QueryableObject>ACTIVITY_INSTANCE</QueryableObject>
<Field>ACTIVITY_INSTANCE_ID</Field>
<Field>CORELATION_ID</Field>
<Field>CASE_INSTANCE</Field>
<Field>PLANNED_ON</Field>
<Field>STARTED_ON</Field>
<Field>LASTMODIFIED_ON</Field>
<Field>LASTMODIFIED_BY</Field>
<Field>CURRENT_STATUS</Field>
<Field>STATE_NAME</Field>
<Field>ACTIVITY_NAME</Field>
<Field>ACTIVITY_TYPE</Field>
</Select>
<Filters>
<EQ field="CASE_INSTANCE">
<Value>0800279a-adfe-a1f0-b511-39aa010830f2</Value>
</EQ>
</Filters>
</Query>
</GetActivities>
</SOAP:Body>
</SOAP:Envelope>

Both will return activity details that have an ‘ACTIVITY_INSTANCE_ID’ which equals a ‘TaskId’…Aha! 🤔

So, with this ‘ACTIVITY_INSTANCE_ID’ (aka ‘TaskID’), we can now do calls like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--Will return task details-->
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<GetTask xmlns="http://schemas.cordys.com/notification/workflow/1.0">
<TaskId>0800279a-adfe-a1f0-b511-3b41804a3971</TaskId>
<RetrievePossibleActions>false</RetrievePossibleActions>
<ReturnTaskData>true</ReturnTaskData>
</GetTask>
</SOAP:Body>
</SOAP:Envelope>
<!--Will return the memos for your task-->
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<ViewMemosByTask xmlns="http://schemas.cordys.com/notification/workflow/1.0">
<TaskId>0800279a-adfe-a1f0-b511-3b41804a3971</TaskId>
</ViewMemosByTask>
</SOAP:Body>
</SOAP:Envelope>

The response of the ViewMemosByTask call is this (where I did a second forward to gain more memos):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<data>
<ViewMemosByTaskResponse xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.cordys.com/notification/workflow/1.0">
<tuple>
<old>
<Memo>
<MemoId>0800279a-adfe-a1f0-b511-3d92522cb971</MemoId>
<TaskId>0800279a-adfe-a1f0-b511-3b41804a3971</TaskId>
<MemoData>This is a forward comment</MemoData>
<MemoTitle>Transfer note</MemoTitle>
<MemoType>TRANSFER_REASON</MemoType>
<TimeStamp>1765205310334</TimeStamp>
<UserDisplayName>OPA Developer</UserDisplayName>
<CreatedBy>cn=opadev@opa,cn=organizational users,o=opa_tips,cn=cordys,cn=defaultInst,o=mydomain.com</CreatedBy>
</Memo>
</old>
</tuple>
<tuple>
<old>
<Memo>
<MemoId>0800279a-adfe-a1f0-b511-45888d07b300</MemoId>
<TaskId>0800279a-adfe-a1f0-b511-3b41804a3971</TaskId>
<MemoData>The is a delegate comment</MemoData>
<MemoTitle>Transfer note</MemoTitle>
<MemoType>TRANSFER_REASON</MemoType>
<TimeStamp>1765205363765</TimeStamp>
<UserDisplayName>OPA Developer</UserDisplayName>
<CreatedBy>cn=opadev@opa,cn=organizational users,o=opa_tips,cn=cordys,cn=defaultInst,o=mydomain.com</CreatedBy>
</Memo>
</old>
</tuple>
<tuple>
<old>
<Memo>
<MemoId>0800279a-adfe-a1f0-b513-9154aab6b0f2</MemoId>
<TaskId>0800279a-adfe-a1f0-b511-3b41804a3971</TaskId>
<MemoData>This is a second forward comment</MemoData>
<MemoTitle>Transfer note</MemoTitle>
<MemoType>TRANSFER_REASON</MemoType>
<TimeStamp>1765209308406</TimeStamp>
<UserDisplayName>OPA Developer</UserDisplayName>
<CreatedBy>cn=opadev@opa,cn=organizational users,o=opa_tips,cn=cordys,cn=defaultInst,o=mydomain.com</CreatedBy>
</Memo>
</old>
</tuple>
</ViewMemosByTaskResponse>
</data>

Perfect…We can now use this in our BPMs (via the Method Set Notification 1.0 runtimereference webservice) with some fascinating expressions to grab the latest one in the list:

1
2
3
4
5
6
7
8
--Get the latest transfer reason timestamp and save it in a variable 'latestTimestamp':
max(ns2:ViewMemosByTaskResponse/ns2:ViewMemosByTaskResponse/ns2:tuple/ns2:old/ns2:Memo[MemoType = 'TRANSFER_REASON']/ns2:TimeStamp/text())

--Reuse that variable in a call like this:
ns2:ViewMemosByTaskResponse/ns2:ViewMemosByTaskResponse/ns2:tuple/ns2:old/ns2:Memo[TimeStamp = //bpm:latestTimestamp/text()]/ns2:MemoData/text()

--Or do it in one call:
ns2:ViewMemosByTaskResponse/ns2:ViewMemosByTaskResponse/ns2:tuple/ns2:old/ns2:Memo[not(ns2:TimeStamp < //ns2:tuple/ns2:old/ns2:Memo/ns2:TimeStamp)]/ns2:MemoData/text()

So, ViewMemosByTask is explained (post DONE), but the greatest question of all remains open. How to grab the full list of comments without asking OT for a fix, whether or not it is a bug!? Well, we learned already that when the ‘History’ building block is in place, we see all our comments passing by in the greatest table ‘o2opa_tipsprj_generichistoryloglist’. My first thoughts would be like this…

A long time ago, I explained about the Northwind database (over a ‘WS-App Server connector’)…

I did a quick setup on my own VM, following that Northwind post, and generating a fancy service like this from the ‘Database Metadata’ type of document:

viewmemo_008

Where this is the call from the ‘Web Service Interface Explorer’ (after the service generation and publication):

1
2
3
4
5
6
7
<SOAP:Envelope xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP:Body>
<opa_tipsprj_generichistoryloglist xmlns="http://schemas.cordys.com/opa_tipsprj_generichistoryloglist">
<item_id>0800279aadfea1f0b50f736879b9b83c.327682</item_id>
</opa_tipsprj_generichistoryloglist>
</SOAP:Body>
</SOAP:Envelope>

This is the magic ordered response with ALL our comments (search for re=") to further consume in your BPMs!:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<data>
<opa_tipsprj_generichistoryloglistResponse xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.cordys.com/opa_tipsprj_generichistoryloglist">
<tuple>
<old>
<o2opa_tipsprj_generichistoryloglist>
<s_when>2025-12-08T15:55:08.527000000</s_when>
<s_history_data>&lt;History G1="90B11C8A394711E5F7F05406E6CE7FCB"&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."&gt;&lt;options an="Review product" cu="OPA Developer" li="0800279aadfea1f0b510a7b3a40c3300.327682.327684" nd="null" nt="OPA Administrator" od="null" ot="OPA Tester" re="This is a second forward comment" ta="ForwardBEHALF" te="OPA Tester" tt="user"/&gt;&lt;/TA&gt;&lt;/History&gt;</s_history_data>
</o2opa_tipsprj_generichistoryloglist>
</old>
</tuple>
<tuple>
<old>
<o2opa_tipsprj_generichistoryloglist>
<s_when>2025-12-08T14:49:23.924000000</s_when>
<s_history_data>&lt;History G1="90B11C8A394711E5F7F05406E6CE7FCB"&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."&gt;&lt;options an="Review product" cu="OPA Developer" li="0800279aadfea1f0b510a7b3a40c3300.327682.327684" nd="null" nt="OPA Developer" od="null" ot="OPA Tester" re="The is a delegate comment" ta="DelegateBEHALF" te="OPA Tester" tt="null"/&gt;&lt;/TA&gt;&lt;/History&gt;</s_history_data>
</o2opa_tipsprj_generichistoryloglist>
</old>
</tuple>
<tuple>
<old>
<o2opa_tipsprj_generichistoryloglist>
<s_when>2025-12-08T14:48:56.545000000</s_when>
<s_history_data>&lt;History G1="90B11C8A394711E5F7F05406E6CE7FCB"&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."&gt;&lt;options an="Review product" cu="OPA Developer" li="0800279aadfea1f0b510a7b3a40c3300.327682.327684" nd="null" nt="null" od="null" ot="null" re="This is a resume comment" ta="RESUMEBEHALFWITHCOMMENT" te="OPA Tester" tt="null"/&gt;&lt;/TA&gt;&lt;/History&gt;</s_history_data>
</o2opa_tipsprj_generichistoryloglist>
</old>
</tuple>
<tuple>
<old>
<o2opa_tipsprj_generichistoryloglist>
<s_when>2025-12-08T14:48:47.443000000</s_when>
<s_history_data>&lt;History G1="90B11C8A394711E5F7F05406E6CE7FCB"&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."&gt;&lt;options an="Review product" cu="OPA Developer" li="0800279aadfea1f0b510a7b3a40c3300.327682.327684" nd="null" nt="null" od="null" ot="null" re="This is a suspend comment" ta="SUSPENDBEHALFWITHCOMMENT" te="OPA Tester" tt="null"/&gt;&lt;/TA&gt;&lt;/History&gt;</s_history_data>
</o2opa_tipsprj_generichistoryloglist>
</old>
</tuple>
<tuple>
<old>
<o2opa_tipsprj_generichistoryloglist>
<s_when>2025-12-08T14:48:30.356000000</s_when>
<s_history_data>&lt;History G1="90B11C8A394711E5F7F05406E6CE7FCB"&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."&gt;&lt;options an="Review product" li="0800279aadfea1f0b510a7b3a40c3300.327682.327684" nd="null" nt="OPA Tester" od="null" ot="OPA Developer" re="This is a forward comment" ta="Forward" tt="user"/&gt;&lt;/TA&gt;&lt;/History&gt;</s_history_data>
</o2opa_tipsprj_generichistoryloglist>
</old>
</tuple>
<tuple>
<old>
<o2opa_tipsprj_generichistoryloglist>
<s_when>2025-12-08T14:48:14.828000000</s_when>
<s_history_data>&lt;History G1="90B11C8A394711E5F7F05406E6CE7FCB"&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327683" t="0800279aadfea1f0b510a7b3a40c3300.327682.327683" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327683."&gt;&lt;options an="Initialize product" li="0800279aadfea1f0b510a7b3a40c3300.327682.327683" nd="null" nt="null" od="null" ot="null" re="This is a complete comment" ta="COMPLETEWITHCOMMENT" tt="null"/&gt;&lt;/TA&gt;&lt;LB e="0800279aadfea1f0b51099cc24bfb971" i="0800279aadfea1f0b50f736879b9b83c.327682" t="product-327682" v="914972360c28353b9dd96821c7a08ca2" x="0800279aadfea1f0b50f736879b9b83c.327682."&gt;&lt;options la="Activity" li="Review product" lm="Planned"/&gt;&lt;/LB&gt;&lt;CD e="0800279aadfea1f0b510a7b3a40c3300" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="914972360c28353b9dd96821c7a08ca2" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."/&gt;&lt;TA e="{G1}" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="5c58c3f47c463e41958dfd1302689c4e" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."&gt;&lt;options an="Review product" li="0800279aadfea1f0b510a7b3a40c3300.327682.327684" nd="null" nt="opadev@opa" od="null" ot="null" ta="Initiate" tt="user"/&gt;&lt;/TA&gt;&lt;IC e="0800279aadfea1f0b510a7b3a40c3300" i="0800279aadfea1f0b510a7b3a40c3300.327682.327684" t="0800279aadfea1f0b510a7b3a40c3300.327682.327684" v="914972360c28353b9dd96821c7a08ca2" x="0800279aadfea1f0b50f736879b9b83c.327682.0800279aadfea1f0b510a7b3a40c3300.327684."/&gt;&lt;/History&gt;</s_history_data>
</o2opa_tipsprj_generichistoryloglist>
</old>
</tuple>
</opa_tipsprj_generichistoryloglistResponse>
</data>

It’s a party! 🥳


This was another post about a hidden service call only the experts of the platform know the existence of. It’s a “DONE” where you now also gain knowledge about this secret call and reuse it for your own project. I will never forget this call (and the masterdata DB-trick) again as it will benefit in every project where you want to collect data on the decisions and comments made by your knowledge workers! Have a great weekend and CU next week with a new topic about Process Automation Tips.

Don’t forget to subscribe to get updates on the activities happening on this site. Have you noticed the quiz where you find out if you are also “The Process Automation guy”?