Overview

Skill Level: Any Skill Level

This recipe describes a reusable framework for handling exceptions within Node-RED flows.

Ingredients

The exception framework is comprised of a JSON object to maintain custom user messages and next action identifiers, Node-RED Function and Catch Nodes, and JavaScript Try-Catch and/or Node-RED Error statements that break the normal flow of execution within a Node.

Elements within the JSON object allow the framework to be used across flows with no, or minimal, modification after being initially created. Support is provided for custom messages as well as identifiers to alternative logic flows that can be executed when an exception occurs.

The steps below detail how to include and customize the JSON object and Node-RED nodes within your Node-RED flows.

Two coded examples demonstrate how the framework is structured and invoked within the Node-RED user interface or Web Page.

Step-by-step

  1. Create the JSON Exception Message Object

    A JSON object is used to maintain custom exception messages and next action codes. Each record can be uniquely identified by an Application Identifier, Exception Label, Activation Timestamp, and Deactivation Timestamp.

    The Application Identifier (i.e. applicationID) allows custom messages and actions to vary among Flows. Recommended data types for Application Identifiers are strings or numbers. The exception framework requires an Application Identifier to exist in the flow-level context and be stored in the variable “appID” (e.g.¬†flow.set(“appID”, msg.payload);) at runtime.¬† Maintaining unique Application Identifiers for each flow allows a single global JSON Exception Message Object to maintain all custom messages and action codes.

    The Exception Label (i.e. exceptionLabel) is a short-hand pointer to the custom message and optional next action codes. The Exception Label is passed to the Node-RED Error Statement (node.error) when a programmed exception condition occurs.

    Messages and Next Action (i.e. nextAction) codes can be dynamically controlled and preconfigured using two timestamps, Activation Timestamp (i.e. activationTS) and Deactivation Timestamp (i.e. deactivationTS). Both timestamps must have values in the JSON object and be entered in the JavaScript ISO Timestamp format. Logic within the Exception Message Lookup node uses the Current Timestamp to determine which exception record is active and should be used. Care must be taken to ensure that exception records with the same Application Identifier and Exception Label do not overlap the same time period when the record is active and may be called in an exception condition.

    Each JSON record can contain an optional Exception Message (i.e exceptionMsg) and an optional Next Action code. Exception Messages are custom messages that can be used to give clarity to an exception condition to an end user, console, or log. The data type for an Exception Message is assumed to be a string.

    Next Action codes allow for logic branching after an exception is caught. For example, a condition can be recorded in a log using the Exception Message and programmatically corrected to allow the Flow to continue to successful completion. A Next Action can be represented by any data type (e.g. string or number) that can be interpreted by a Switch Node. It is recommended that the same data type be used for all Next Action values having the same Application Identifier value.

    The structure of a valid JSON Exception Message Object looks like this:

    [{

    “applicationID”: “”,

    “exceptionLabel”: “”,

    “exceptionMsg”: “”,

    “activationTS”: “”,

    “deactivationTS”: “”,

    “nextAction”: “”

    }]

    The exception framework requires a JSON Exception Message Object to exist in the global-level context and be stored in the variable “xMsgObj” (e.g. global.set(“xMsgObj”, msg.payload);) at runtime.¬† Maintaining the JSON Exception Message Object in the global-context allows one data store to be maintained for messages and next action codes across many flows.

    Two examples of the Exception Handling Framework are provided in this recipe. Both examples use the same JSON object to maintain messages and next action identifiers. Its structure and content are as follows:

    [{
    “applicationID”: “1”,
    “exceptionLabel”: “isNaN”,
    “exceptionMsg”: “The divisor entered is not numeric.”,
    “activationTS”: “2017-05-23T18:30:30.000Z”,
    “deactivationTS”: “2019-05-23T18:30:30.000Z”,
    “nextStep”: null
    }, {
    “applicationID”: “1”,
    “exceptionLabel”: “isZero”,
    “exceptionMsg”: “This message will be replaced during an alternate exception process.”,
    “activationTS”: “2017-05-23T18:30:30.000Z”,
    “deactivationTS”: “2019-05-23T18:30:30.000Z”,
    “nextStep”: 55
    }, {
    “applicationID”: “1”,
    “exceptionLabel”: “isEmpty”,
    “exceptionMsg”: “The divisor is empty.”,
    “activationTS”: “2017-05-23T18:30:30.000Z”,
    “deactivationTS”: “2019-05-23T18:30:30.000Z”,
    “nextStep”: null
    }, {
    “applicationID”: “2”,
    “exceptionLabel”: “isNaN”,
    “exceptionMsg”: “The divisor entered is not numeric. Please retry.”,
    “activationTS”: “2017-05-23T18:30:30.000Z”,
    “deactivationTS”: “2019-05-23T18:30:30.000Z”,
    “nextStep”: null
    }, {
    “applicationID”: “2”,
    “exceptionLabel”: “isZero”,
    “exceptionMsg”: “This message will be replaced during an alternate exception process.”,
    “activationTS”: “2017-05-23T18:30:30.000Z”,
    “deactivationTS”: “2019-05-23T18:30:30.000Z”,
    “nextStep”: 55
    }, {
    “applicationID”: “2”,
    “exceptionLabel”: “isEmpty”,
    “exceptionMsg”: “The divisor is empty. Please retry.”,
    “activationTS”: “2017-05-23T18:30:30.000Z”,
    “deactivationTS”: “2019-05-23T18:30:30.000Z”,
    “nextStep”: null
    }]

  2. Insert and Configure Node-RED Nodes

    The exception framework employs a three-tiered design.  All nodes defined and explained below must be included and configured in each flow where you want the framework to execute.

    First Tier

    First-Tier-1

    The first tier is comprised of Node-RED Catch, Function and Switch Nodes. The Node-RED Catch Node, called Exception Handler Catch, must be configured to catch errors thrown from selected nodes within your flow in which you programmatically raise an error. This Node must be configured for each Flow.

    The Exception Handler Catch is connected to the Exception Message Lookup Function Node. Within this function the Application Identifier and Exception Label passed when an error is raised are used to retrieve a custom message and next action value from the JSON Exception object. This node does not need to be configured or modified.

    Exception Message Lookup connected to a Switch Node called Next Step Action. This node must be configured to support Next Step values inserted in the JSON Exception object. If no Next Actions are desired in your exception handling we recommend you code an “otherwise” rule for the msg.nextStep property.¬† Flows out of the Next Step Action node are connected to other nodes within your Flow. These additional nodes are not part of the framework but are required for successful application functioning.¬† We have included both next action and otherwise rules in the sample flows to improve your understanding.

    Second Tier

    Second-Tier

    The second tier of the framework is included to catch exceptions within the Exception Message Lookup function. This tier consists of a Node-RED Catch node called Catch for Exception Message Lookup and a Debug node called Exceptions from Message Lookup. These nodes do not need to be configured or modified. Coded exceptions or unanticipated errors within the Exception Message Lookup function are caught and sent to the Debug node which is configured to write the complete message object to the debug tab and console.

    Third Tier

    Third-Tier

    The third tier of the framework functions to catch errors not part of the Exception Handling Framework or selected nodes within your flow in which you programmatically raise an error. The Node-RED Catch Node titled, Catch for all other nodes, must be configured for each of your Flows. Messages caught and sent to the Debug node, titled Uncaught Exceptions from Other Nodes, have their complete message object written to the debug tab and console.

     

    Configure the Exception Handler Catch Node

    Exception-Handler-Catch

    The Exception Handler Catch Node must be associated to each node in your flow you want included in the scope of the Exception Handler Framework.  In the figure above the computeFraction function has been selected.  Exceptions and errors in computeFraction will be caught in the Exception Handler Catch Node and passed to Exception Message Lookup for further processing.

    The list of nodes selectable within Exception Handler Catch changes according to the Flow in which it is placed. 

     

    Configure the Next Step Action Node

    Next-Step-Action

    Exceptions that have a Next Step Action value included in the JSON Exception Object are handled by the Next Step Action node.  Values retrieved are passed to this node in the msg.nextStep property.  It is recommended that all Next Action codes be of the same data type within a Flow.  In the figure above configuration Rule 1 is evaluating msg.nextStep for a numeric value equal to 55.  When Rule 1 evaluates to true, flow 1 from the node will be executed.

    Any other data type or value in msg.nextStep will be handled by the “otherwise” Rule and processing will proceed to flow 2 from this node.

    If no alternate exception processing is required in your flow, it is recommended to continue to include the Next Step Action node and configure it to only have one rule, the “otherwise” Rule.¬† See below.

    Next-Step-Action-Otherwise

    Configure the Catch for All Other Nodes

    Catch-All-Nodes

    This node has been added to catch exceptions from nodes within a flow where programmed exception logic is not included.  Nodes that include exception logic must not be selected in this node.

    In the sample above, exceptions occurring within the HTML template node, getDivisorPage, and function, Map Result to Message, will be caught in this node and sent to its associated debug node.  The complete msg object will then be written to the debug tab and console.

    The list of nodes selectable in this node changes according to the Flow in which it is placed.

  3. Raising an Exception

    The Exception Handling Framework uses the built-in Node-RED node.error statement and Catch node.  As shown in Section 2 РInsert and Configure Node-RED Nodes, a Catch node must be added to a flow and associated to a node.

    Nodes associated to a Catch Node can have node.error statements included within them and be called in Try-Catch or If-Else statements.

    Exceptions may be coding errors, errors due to wrong input, and other unforeseeable things.

    In a Try-Catch block the try statement allows you to define a block of code to be tested for errors while it is being executed.

    The catch statement allows you to define a block of code to be executed if an error occurs in the try block. 

    The finally statement lets you execute code, after try and catch, regardless of the result.

    A sample Try-Catch block may look like this:

    try {

    Block of code to try

    throw “<exceptionLabel>”; }

    catch(err) {

    Block of code to handle errors

    node.error(err, msg);}

    finally {    

    Block of code to be executed regardless of the try / catch result

    }

    Note the inclusion of the throw statement and <exceptionLabel> value.  The throw statement throws a user-defined exception.  Each exception the Framework is required to handle must have a record in the JSON Exception Message Object and an <exceptionLabel> value coded.

    In the sample above, the node.error statement is passed the <exceptionLabel> value through the err expression.  The node.error statement then passes the err expression and the Node-RED message object, msg, values to its associated Catch Node.

     If-Else statements can also be used to raise exceptions.

     A sample If-Else statement may look like this:

     if (condition) {

    block of code to be executed if the condition is true

    } else {

    block of code to be executed if the condition is false

    node.error(<exceptionLabel>, msg);

    }

    As in the Try-Catch-Finally code the node.error statement is passed the <exceptionLabel> value.  The node.error statement then passes the <exceptionLabel> value and the Node-RED message object, msg, to the associated Catch Node.

    To see a working example, inspect the code within the Function Node, computeFraction.

  4. Understanding the Exception Message Lookup Function

    The Exception Message Lookup Function is a key component of the Exception Handling Framework.  Its purpose is to retrieve the exception message and Next Action values from the JSON Message Exception Message Object using the Application Identifier and Exception Label.

    This component of the framework does not require any code modifications to be used.  An explaination of its function is included here to complete your understanding of the framework.

    The function has two basic parts.  The first part checks for the existence of the Application Identifier, Exception Label and JSON Exception Message Object.  If any of these fail to exist an internal error message and Next Action value (equal to 999) are set and processing stops.

    You can see this in the code snippet below:

    //Obtain the Application ID.
    var xcpAppID = flow.get(“appID”);
    if (!xcpAppID) {
    msg.exceptionMsg = “Application error. Application identifier doesn’t exist.”;
    msg.nextAction = 999;
    return msg;
    }

    The second part of this function performs the actual retrieval from the JSON object.  Each record is read and its values for Application Identifier, Exception Label, Activation Timestamp and Decactivation Timestamp are compared to values either passed to the function, or in the case of the timestamps, calculated from Current Timestamp. 

    For a record to be selected there must be a match to the Application Identifier and Exception Label and Current Timestamp must fall between the Activation Timestamp and the Decactivation Timestamp.  It is imperative that records in the JSON object with the same Application Identifier and Exception Label have differen Activation and Decactivation Timestamp ranges that do not overlap.

     

     

     

     

  5. Example 1 - Exception Handler in the standard Node-RED UI

    This example demonstrates how the Exception Handling Framework can be configured and used within the standard Node-RED UI.

    Copy the code below into Clipboard.  It can be imported straight into the Node-RED editor by pasting the JSON into the Import dialog (Ctrl-I or via the dropdown menu). Click the Deploy Button in the top right corner of the page to save and deploy the code.

    The section “Set Application ID and Load JSON Message Object” contains nodes¬†to set and store the flow-level Application Identifier and global-level JSON Exception Message Object explained in Step 1 – Create the JSON Exception Message Object.¬† Each node is set to automatically execute when you deploy the code.

    The Exception Handling Framework requires the two variables “appID” and “xMsgObj” to be set and the nodes in this section do that. ¬†We chose this implementation method for simplicity. ¬†You may adopt a different design.

    To excerise the Exception Handling Framework we included the¬†section “Inject Node Test Harness” and five (5) Inject Nodes. Depressing the button to the left of each node will cause a value to be passed into the computeFraction function. ¬†Here the value will be evaluated and the fraction computed or an exception raised. ¬†The result will be displayed in the debug tab.

    Note the Alternate Flow node connected to the Next Step Action node.  For the Zero Division injection an action code equal to 55 will be retreived from the JSON Exception Message Object.  This value will be passed to Next Step Action and routed to Alternate Flow.  Here the default message retreived from the JSON Exception Message Object will be replaced with a new message and the result displayed in the debug tab.

    Example 1 РException Handler for Node-RED UI

    Node-RED-UI-Example

    Example 1 РNode-RED Code 

    Download the Example 1 code from GitHub: https://gist.github.com/Behr3rd/e817e66e086d20ab4ca8a551ebe5dbac

  6. Example 2 - Exception Handler called from a Web Page

    This example demonstrates how the Exception Handling Framework can be configured and called from a Web Page created and hosted in Node-RED.

    Copy the code below into Clipboard.  It can be imported straight into the Node-RED editor by pasting the JSON into the Import dialog (Ctrl-I or via the dropdown menu). Click the Deploy Button in the top right corner of the page to save and deploy the code.

    The section “Set Application ID and Load JSON Message Object” contains nodes¬†to set and store the flow-level Application Identifier and global-level JSON Execption Message Object explained in Step 1 – Create the JSON Exception Message Object. ¬†Each node is set to automatically excute¬†when the code is deployed.

    The Exception Handling Framework requires the two variables “appID” and “xMsgObj” to be set and the nodes in this section do that. ¬†We chose this implementation method for simplicity. ¬†You may adopt a different design.

    Note the Alternate Flow node connected to the Next Step Action node.  For the Zero Division injection an action code equal to 55 will be retreived from the JSON Exception Message Object.  This value will be passed to Next Step Action and routed to Alternate Flow.  Here the default message retreived from the JSON Exception Message Object will be replaced with a new message and the result displayed in the result window of the Web page.

    Web-Page-Example

    To excerise the Exception Handling Framework open a new browser tab and visit the application’s URL. If you are using the local version of Node-RED your URL will be something like http://localhost.1880/input. If you are using BlueMix your URL will be something like https://<my-app>.mybluemix.net/input. “/input” is required as it is the name of the entry page for the test harness.

    Web-Input-Page

    You may scroll to a numeric value in the input box (values range from -2 to +2) or select one of the options and press Submit. The value selected or associated to an option will be evaluated and a fraction computed or an exception raised. The result will be displayed in the debug tab.  To execute the Alternate Flow node select the numeric value, 0, from the input box.

     

    Example 2 РNode-RED Code 

    Download the Example 2 code from GitHub: https://gist.github.com/Behr3rd/6ef7bb7f5c00961302ed391978bbe92c

3 comments on"Node-RED Exception Handling Framework"

  1. ManfredMeise June 10, 2018

    Great recipe! Wanted to try it out, but when copy / pasting the JSON for example1, the editor is unable to validate the code to allow for imports. Where ist the coding error? Can you please post the corrected version?

    Regards,
    Manfred

  2. I think that it would be good to add a section documenting the value of this framework … answering the question “why would we need such a framework”.

Join The Discussion