Callbacks work across remote calls. To understand this, it is useful to understand the underlying mechanism.
If a remote process does not perform any callback actions, it is treated like any other non-conformant process. The caller picks up the response directly, treats it as a "complete" callback, and continues its own processing.
Assuming that the remote process does perform callback actions:
-
The step that first reads the incoming callbackToken (typically an exists step, an accept step, or a start step) detects that the call came across a channel.
-
A new callback token is created, wrapping the original callback token with additional delivery information
-
This wrapped token is passed to later steps.
-
Whenever a callback is dispatched using the wrapped token, the dispatch executes the step that wrapped the token (using the handleChannelForward channel action), passing in the callbackData the "real" callback that needs to be returned. The step then sends the callback across the appropriate channel.
If the called process want to pass the token on and not perform the callbacks itself, use the exists callbackAction. This checks that the token exists, and assuming it does, sets the callbackToken attribute to the modified token that wraps the original. This can then be passed further into the process.
The exists action will wrap the token and then set the callbackToken attribute to the wrapped token. The accept or start step will wrap the token, then perform a callback, and set the callbackToken attribute to the original (unwrapped) token. Some attribute juggling may be required to ensure the correct token is passed to the next step.
Wrapped token format
An original token has the form
{
"node": "original.node.reference",
"anchor": "original.anchor",
"id": "original.id"
}When it is wrapped, the it takes the form:
{
"node": "transport.node.reference",
"anchor": "transport.anchor",
"useTransport": true,
"transport": [
{
"type": "channel",
"node": "transport.node.reference",
"anchor": "transport.anchor",
"channel": "channel.node.reference",
"processIdentifier": "processIdentifier"
},
... more transport objects
],
"token": {
"node": "original.node.reference",
"anchor": "original.anchor",
"id": "original.id"
}
}The original token is stored in the "token" property. An array is created of each of the transport objects. These indicate the node and anchor (step name) that performed the wrap, and the channel and process identifier required to send the callback through the channel.
The node and anchor from the last transport are set as the top-level node and anchor.