We recently came across problem with Workflow notification message. We have set up template workflow for process Purchase requisition approval (PurchReqApproval). When purchase requisition gets approved the process should create automatically Purchase Order (setting parameter “Auto create purchase order” in Accounts payable > Setup > Parameters on tab Purchase requisition). For even Completed we set up following notification:

“Purchase requisition order: %Purchase Requisition.PurchReqId% has been approved and new purchase order was created with number: %Purchase Requisition.Purchase requisition lines.PurchId%”.

After workflow has finished correctly the notification was sent. The problem is that notification looks following:

“Purchase requisition order: PR_000501 has been approved and new purchase order was created with number: ”.

So the second place holder: %Purchase Requisition.Purchase requisition lines.PurchId% has not been replaced correctly, although the Purchase order was created correctly.

The purchase order is created and field PurchReqLine.PurchId  is filled in in following code:

\Classes\PurchAutoCreate_PurchReq\createPurchLine
\Classes\PurchAutoCreate\create
\Classes\PurchAutoCreate_PurchReq\create
\Data Dictionary\Tables\PurchReqTable\Methods\setWorkflowState
\Classes\PurchReqWorkflowEventHandler\completed
\Classes\SysWorkflowEventDispatcher\raiseWorkflowEvent
\Classes\SysWorkflowEventDispatcher\onWorkflowCompleted

while the notification is sent a little later

\Classes\WorkflowDocumentField\substitutePlaceholderAsUser
\Classes\SysWorkflowEventDispatcher\sendNotifications
\Classes\SysWorkflowEventDispatcher\onWorkflowCompleted


As we can see from the  \Classes\PurchAutoCreate_PurchReq\createPurchLine the value of PurchLineReq.PurchId is updated between more than one pairs of “ttsbegin” and “ttscommit” and the query of the field is executed before the last “ttscommit” and the value will not be written into the database until the last “ttscommit” is executed (I have verified this by checking the database in SQL Server when debugging).

In method \Classes\WorkflowDocumentField\substitutePlaceholderAsUser we have following code

if (_userId == curuserid())
    {
        result = WorkflowDocumentField::substitutePlaceholder(args);
    }
    else
    {
        new RunAsPermission(_userId).assert();
        // BP deviation documented
        result = runas(_userId, classnum(WorkflowDocumentField), staticmethodstr(WorkflowDocumentField, substitutePlaceholder), args, _companyId);
        CodeAccessPermission::revertAssert();
    }

In the “runas” method, a new session will be created for the new logged user, and it will invoke the query method to get the value of the field of PurchLineReq.PurchId. Because the data is uncommitted(i.e. it doesn’t exist in table of sql server), we can’t get the value of the field PurchLineReq.PurchId and as a result in the notification message the placeholder “%Purchase Requisition.Purchase requisition lines.PurchId%” will be replaced with null and we can’t see the value, so the problem occurred.

Every time an application connects to SQL Server, a new connection (or SPID) is created. That means in the method Runas a new AX session is created and it will build a new connection to the database while searching a value in database but the new connection can’t read the uncommitted data of the old one, so I think it is right behavior that we can’t get the value by using Runas method.

This is why the placeholder:  %Purchase Requisition.Purchase requisition lines.PurchId% was not replaced correctly.

So the simple workaround is to change above code to not run with runas. Although you need to be aware that it can imply some security problem when you have record level security set up on table PurReqLine.

 

--author: Czesława Langowska Vliegen
--editor: Czesława Langowska Vliegen
--date: 22/Sep/2011