Node reference (nodeRef)
A node reference (nodeRef) is a special task type that helps you to invoke another
node from within a node. It promotes reusability and modularity by enabling nodes to call other nodes as
subroutines, eliminating the need to duplicate node logic across multiple workflows.
Purpose
Node references promote reusability and modularity by enabling workflows to call other workflows as subroutines, similar to how functions call other functions in programming. Node references help you to do the following steps.
- Reuse node logic. Define node logic once and reference it from multiple locations.
- Reduce duplication. Eliminate the need to copy and paste node definitions.
- Simplify maintenance. Update logic in one place and have all references automatically use the updated version.
- Organize complex nodes. Break down large nodes into smaller, focused components.
- Promote modularity. Create library nodes that can be shared across different workflows.
XML structure
The basic syntax for a workflow reference is as shown in the following example.
<?xml version="1.0"?>
<nodeRef name="NodeRefName" nodeName="ReferencedNodeName"/>
nodeRef element are shown in the following table.
| Attribute | Required | Description |
|---|---|---|
| name | Yes | The unique name for this node reference task within the parent workflow. This name is used for logging and debugging. |
| nodeName | Yes | The name of the node that needs to be invoked. This node needs to exist in the system and be accessible at runtime. |
For example,
<?xml version="1.0"?>
<node name="PaymentValidation">
<task name="CheckFormat" type="validation"/>
<!-- Reference to a reusable verification node -->
<nodeRef name="AccountVerifyRef" nodeName="AccountVerificationNode"/>
<task name="FinalCheck" type="validation"/>
</node>
Behavior
When the workflow engine encounters a nodeRef node, the steps that occur are shown in the
following list.
- Invocation. When the workflow engine encounters a
nodeReftask, it loads the referenced node. - Context sharing. The referenced node runs in the same context as the parent node, sharing all variables and payment message data.
- Assignment Execution. The referenced node's
onEntryandonExitassignments execute normally. - Task Execution. All tasks within the referenced node execute in sequence.
- Return. Control returns to the parent node after the referenced node completes.
Assignment handling
NodeRef executes both onEntry and onExit assignments
from the referenced node. It indicates that the task is critical. For example, xml
<!-- Referenced node with assignments -->
<node name="AgentVerificationNode">
<onEntry>
<assign field="refAgentAcct" value=""/>
<assign field="refAgentBankCode" value=""/>
</onEntry>
<task name="LookupAgent" type="lookup"/>
<onExit>
<assign field="refAgentRC" value="SUCCESS"/>
</onExit>
</node>
<!-- Parent node using nodeRef -->
<node name="PaymentRouting">
<nodeRef name="AgentVerifyRef" nodeName="AgentVerificationNode"/>
<!-- After nodeRef completes, refAgentRC will be set to "SUCCESS" -->
</node>- Referenced node's
onEntryassignments execute. - Referenced node's
tasksexecute. - Referenced node's
onExitassignments execute. - Control returns to the parent node.
Variable handling
nodeRef shares the variable scope as the parent workflow. It means the following.
Variables set in the referenced node persistafter the node completes.The parent node can access these variablesin the subsequent nodes.onEntry and onExit assignments executeas if the node were inlineVariable names must be uniqueacross to avoid conflicts.Referenced nodes can modify parent node variables.
ref prefix) for variables set by
referenced nodes to clearly indicate their source.Success and failure
- The
nodeReftask succeeds if the referenced node completes successfully. - The
nodeReftask fails if the referenced node fails. - The referenced node's success or failure status is determined by the following.
- Task execution results
onExitassignmentstopResultsvalues (if set)- Error conditions during execution
Use cases
<?xml version="1.0"?>
<!-- Reusable agent verification node -->
<node name="IntermediaryAgentVerifyNode">
<onEntry>
<assign field="refAgentAcct" value=""/>
<assign field="refAgentBankCode" value=""/>
<assign field="refAgentName" value=""/>
</onEntry>
<task name="LookupAgentBank" type="lookup">
<!-- Lookup logic -->
</task>
<task name="ValidateAgentAccount" type="validation">
<!-- Validation logic -->
</task>
<onExit>
<assign field="refAgentRC" value="SUCCESS"/>
</onExit>
</node>
<!-- Multiple nodes can reference it -->
<node name="EuroPaymentRouting">
<task name="DetermineRoute" type="decision"/>
<nodeRef name="Agent1Verify" nodeName="IntermediaryAgentVerifyNode"/>
<task name="ApplyRouting" type="assignment"/>
</node>
<node name="NordicPaymentRouting">
<task name="CheckCurrency" type="validation"/>
<nodeRef name="Agent2Verify" nodeName="IntermediaryAgentVerifyNode"/>
<task name="SetRoutingFields" type="assignment"/>
</node><?xml version="1.0"?>
<!-- Reusable settlement node -->
<node name="NextAgentSettlementNode">
<onEntry>
<assign field="refNextAgentSttlAcct" value=""/>
<assign field="refNextAgentSttlMethod" value=""/>
</onEntry>
<task name="DetermineSettlement" type="lookup">
<!-- Settlement logic -->
</task>
<onExit>
<assign field="refNextAgentRC" value="COMPLETE"/>
</onExit>
</node>
<!-- Used in routing workflow -->
<node name="PaymentSettlement">
<task name="ValidateAmount" type="validation"/>
<nodeRef name="SettlementRef" nodeName="NextAgentSettlementNode"/>
<!-- Can now use refNextAgentSttlAcct and refNextAgentRC -->
<task name="ApplySettlement" type="assignment"/>
</node><?xml version="1.0"?>
<!-- Reusable validation node -->
<node name="StandardAccountValidation">
<onEntry>
<assign field="validationResult" value="PENDING"/>
</onEntry>
<task name="CheckAccountFormat" type="validation"/>
<task name="CheckAccountStatus" type="lookup"/>
<task name="CheckAccountLimits" type="validation"/>
<onExit>
<assign field="validationResult" value="PASSED"/>
</onExit>
</node>
<!-- Multiple workflows use the same validation -->
<node name="ACHProcessing">
<nodeRef name="ValidateRef" nodeName="StandardAccountValidation"/>
<task name="ProcessACH" type="processing"/>
</node>
<node name="WireProcessing">
<nodeRef name="ValidateRef" nodeName="StandardAccountValidation"/>
<task name="ProcessWire" type="processing"/>
</node><?xml version="1.0"?>
<!-- Reusable correspondent routing node -->
<node name="CorrespondentBankNode">
<onEntry>
<assign field="corrBankBIC" value=""/>
<assign field="corrBankName" value=""/>
<assign field="corrBankCountry" value=""/>
</onEntry>
<task name="LookupCorrespondent" type="lookup"/>
<task name="ValidateCorrespondent" type="validation"/>
<onExit>
<assign field="corrBankRC" value="FOUND"/>
</onExit>
</node>
<!-- Used in international payment routing -->
<node name="InternationalRouting">
<task name="CheckDestination" type="decision"/>
<nodeRef name="CorrBankRef" nodeName="CorrespondentBankNode"/>
<task name="ApplyCorrBank" type="assignment"/>
</node>Restrictions and limitations
- Supported
- A referenced node can contain
nodeReftasks. - ️Depth Limit
- No automatic depth limit enforcement (use with caution).
- Circular references
- Not allowed.
Invalid circular reference is as shown in the following example.
<?xml version="1.0"?>
<!-- NodeA references NodeB -->
<node name="NodeA">
<nodeRef name="RefB" nodeName="NodeB"/>
</node>
<!-- NodeB references NodeA - CIRCULAR! -->
<node name="NodeB">
<nodeRef name="RefA" nodeName="NodeA"/>
</node>
- NodeRef is a
task type, not a node type. - NodeRef tasks can appear within the
<node>element only. - NodeRef tasks execute in sequence with other tasks in the node.
- The referenced node is loaded by using the same effective date as the parent node.
- If the referenced node does not exist for that effective date, the
nodeReffails. - The referenced nodes need to have matching effective date ranges.
- Each
nodeRefinvocation loads the referenced node from cache. - Excessive nesting can impact performance.
- Consider consolidating deeply nested nodes.
Best practices
<?xml version="1.0"?>
<!-- Use descriptive names that indicate purpose -->
<nodeRef name="AgentVerifyRef" nodeName="IntermediaryAgentVerifyNode"/>
<nodeRef name="SettlementRef" nodeName="NextAgentSettlementNode"/>
<nodeRef name="ValidationRef" nodeName="StandardAccountValidation"/><?xml version="1.0"?>
<!-- Referenced node uses prefixes to avoid conflicts -->
<node name="AgentVerificationNode">
<onEntry>
<assign field="refAgentAcct" value=""/>
<assign field="refAgentBankCode" value=""/>
<assign field="refAgentName" value=""/>
</onEntry>
<onExit>
<assign field="refAgentRC" value="SUCCESS"/>
</onExit>
</node><?xml version="1.0"?>
<!-- Document what the reference does and what variables it sets/expects -->
<nodeRef name="AgentVerifyRef" nodeName="IntermediaryAgentVerifyNode"/>
<!--
Input variables expected: agentBIC, agentCountry
Output variables set: refAgentAcct, refAgentBankCode, refAgentName, refAgentRC-->Good: "AccountVerificationNode"Good: "SettlementDeterminationNode"Poor: "ValidateAndRouteAndSettleNode" (too many responsibilities)
onEntry assignments to
initialize output variables.<?xml version="1.0"?>
node name="ReusableNode">
<onEntry>
<!-- Initialize all output variables to safe defaults -->
<assign field="refResult" value=""/>
<assign field="refStatus" value="PENDING"/>
<assign field="refErrorCode" value=""/>
</onEntry>
<!-- Tasks that populate these variables -->
<onExit>
<!-- Set final status -->
<assign field="refStatus" value="COMPLETE"/>
</onExit>
</node>