Ens.BusinessProcessBPL: context variable is being cleared after a synchronous call to a Business Operation
Hello,
I have a Business Process where I am receiving a JSON payload in the "Body" property of the my request class. I defined a context variable as an object of a class that represents the JSON schema I expect to receive and load the JSON payload in that context variable.
e.g.
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl" ]
{
<process language='objectscript' request='mapi.core.msg.rq.RestBusinessServiceRequest' response='mapi.core.msg.rp.RestBusinessServiceResponse' height='2000' width='2000' >
<context>
<property name='cm' type='mapi.exchange.msg.Communication' instantiate='1'/>
</context>
<sequence xend='200' yend='450' >
<code name='Map request payload' xpos='200' ypos='250' >
<annotation><![CDATA[Map request body to mapi.exchange.msg.communication]]></annotation>
<![CDATA[
s cmReq={}.%FromJSON(request.Body)
s status = context.cm.%JSONImport(cmReq)
]]>
</code>
...
My mapi.exchange.msg.communication class has a property called Recipients which is a list.
I need to loop through the recipients and invoke a Business Operation "Send Email" for each recipient. Here is the example of syntax I use,
<assign property="callrequest" value="context.cm.Recipient.GetAt(key)" action="set" />
</request>
<response type='mapi.exchange.msg.CommonPostResponse' >
</response>
</call>
</foreach>
After the call to BO, it seems like my conext.cm variable gets cleared and <foreach> fails with <INVALID OREF> when trying to do .Next() on my cm.Recipient property. Any ideas on what I am doing wrong here?
Note: if I make an asynchronous call to "Send Email" then context variable is not cleared and my process works but I need the call to "Send Email" to be synchronous.
Regards,
Utsavi
Is
mapi.exchange.msg.Communication
persistent?That said, I'd move JSON parsing to a BS, so
mapi.exchange.msg.Communication
becomes a request.Here is the section in the docs that explains why this is happening and why @Eduard Lebedyuk asked if that class is persistent.
Business Process Execution Context
The life cycle of a business process requires it to have certain state information saved to disk and restored from disk, whenever the business process suspends or resumes execution. This feature is especially important for long-running business processes, which may take days or weeks to complete.
A BPL business process supports the business process life cycle with a group of variables known as the execution context. InterSystems IRIS automatically save the variables in the execution context and restores them each time the BPL business process suspends and resumes execution.
Thank you Marc and Eduard for your reply. After spending some time I figured what you both have pointed i.e the class needs to be persistent.
Hi Eduard,
regarding your comment around moving JSON parsing to BS, is there a reason for doing so?
I have a common business service which can invoke multiple different Business processes based on a parameter. that is why it uses the common class mapi.core.msg.rq.RestBusinessServiceRequest to pass on request data to the BP and let BP do the specifics.
Regards,
Utsavi
In general it might be preferable to move from less structured data (JSON) to more structured data (Objects) as fast and as early in your processing pipeline as possible.
The reasons for it are varied but include:
So in your case I would have structured it like this:
It's also advantageous to move all parsing logic is in one place (Business Service) as it minimizes the amount of code written and frees Business Processes from the more low-level technical tasks which usually obfuscate the more high-level intent of a Business Process.