JavaScript InProc

◷ Reading Time: 11 minutes

FlexRule allows publishing your rules on the JavaScript platform. That means you can run your rules in offline mode, on mobile devices, and so on.

Business Logic

The type of business logic (i.e., business rules, application logic, etc.) that are supported on the JavaScript platform are:

  1. Decision Table
  2. Natural Language

This means that when you need to support the offline execution of logic on disconnected devices, you need to choose either a Decision table or Natural language.

Publish

When you model the logic i.e., Decision table, Natural language, to run these on the JavaScript platform you need to build the JS version of your model. You can do this in two ways using:

Package Builder

Package builder allows you to target the JavaScript Platform

When you do that you will need to fill out an Application Namespace.

This is just a simple name that allows you to categorize your logic in the web app (e.g., SampleUI.BusinessLogic.LoanRatingSampleUI.BusinessLogic.Approvaletc.).

In the package view, you can add multiple models:

Go back to the builder tab and press Publish

Select Copy to a Target Folder option for your Method in the Packaging Information

The JS files of your model will be copied to the target folder along with the FlexRule.Runtime.min.js. You will learn to reference these in your web application.

JavaScript Compiler

You can automate the process of building the JS file for your model, or you can make it dynamic by using the Compiler API of FlexRule Runtime. There are two steps to do so:

  1. Loading your model
  2. Calling the compiler to create the JS of your model

Below is a sample code to create the JS for a model

// Step 1: Loading the model
var baseFolder=...; //the base folder that has the models and related dependent files (i.e., Business glossaries).
var binaryModel = File.ReadAllBytes(Path.Combine(baseFolder, "your_model_file_name.xml");
var model = LoadAdapterUtility.LoadModel(binaryModel);
 
// Step 2: Calling the compiler
FlexRule.JavaScript.Compiler compiler = new FlexRule.JavaScript.Compiler("CompanyName.WebUI.MyApp");
var js = compiler.Run(model, baseFolder);

Support

Expressions

Decision Table

Natural Language

API

Registering Logic

FlexRule.ApplicationsLogic provides a global context for applications to register their logic using namespace and logicName. It’s a registry for applications logic. When logic (i.e. Decision table, Natural language) is deployed as JavaScript, they are automatically registered using the below function.

register

Register a logic in the application registry.

FlexRule.ApplicationsLogic.register(namespace, logicName, fnLogic)

exists

Check if a logic already is registered.

FlexRule.ApplicationsLogic.exists(namespace, logicName)

Creating Runtime Engine

FlexRule.RuntimeEngine provides a function to create an engine from registered applications logic. When an engine is created by calling fromJavaScript then the engine instance allows executing the logic by passing values and parameters information.

fromJavaScript

Create an instance of the runtime engine.

var rule = FlexRule.RuntimeEngine.fromJavaScript(appNamespace, logicName)

RuntimeEngine Members

When an engine is created from FlexRule.RuntimeEngine.fromJavaScript then the engine instance allows executing the logic by passing values and parameters information.

run

Runs the instance of the engine with the input parameters.

var result = rule.run(input1, input2, input3,...)

runWithParameters

Runs the instance of the engine that allows selecting scope. Scope provides a runParameter object. It allows executing individual rules within a logic document.

Also, the document can group multiple rules into a new scope and the engine can call that scope for the execution of multiple rules with one call.

var result = rule.runWithParameters(runParameter, input1, input2, input3,...)
  • runParameter: A JSON object that has a ‘name’ attribute to define the name of the rule
    e.g. {name:'scope 1'}
  • input1, input2…: Values to the input parameters

Examples:

If you have the following Natural Language code,

and you want to call only the logic scope 1, you call it as follows.

   var fact1=...; // define fact1 as input
   var fact2=...; // define fact2 as input
 
   var engine = FlexRule.RuntimeEngine.fromJavaScript("CompanyName.WebUI.MyApp", "calling when with param");
   var res = engine.runWithParameters({name:'scope 1'}, fact1, fact2);

registerFunction

Register custom functions that allow a logic call to the functions.

rule.registerFunction(name, fn)

descriptions

This property holds the rule descriptions

rule.descriptions

Members:

  • logicName: name of the logic document
  • appNamespace: area of the application that this logic is related to
  • logics: list of all rules inside the logic
  • parameters: parameters (in and out) of the logic document

For example, to retrieve all the available rules in a logic document you can use the code below:

rule.descriptions.logic

Integration

References

You need to reference the files below in your web application:

  • FlexRule.Runtime.min.js: this is the core component of the JS engine that enables the execution of models
  • the JS files of your models

for example:

<!--FlexRule JavaScript BRE Reference-->
<script src="js/FlexRule.Runtime.min.js"></script>
 
<!--List of business rules logic-->
<script src="js/Rules/States.xml.js"></script>
<script src="js/Rules/Validation.xml.js"></script>

Creating Runtime Engine

Once you have the references in your application, you can create an instance of the runtime for your logic using FlexRule.RuntimeEngine.fromJavaScript.

Example:

var statesRules = FlexRule.RuntimeEngine.fromJavaScript("SampleUI.BusinessLogic", "States");

Executing Logic

Run

When you want to run the logic, you need to call either:

  • run
  • runWithParameters

on the runtime instance of your logic that is created by fromJavaScript.

Example:

var result = statesRules.run('Australia');

In the above example, the statesRules accepts one parameter as the country name.

Retrieve Results

When you execute the run method, it returns the RuntimeResult.

RuntimeResult {
    context {
           notifications{ ... },
           variableContainer{ ... }
    }
}

The RuntimeResult behavior is similar to the .Net instance of the API, but with the members described in the above structure.

To retrieve the results you can use the variableContainer which has all the output parameters.

Example:

// get the output parameter of the rule which is the list of states for the country
var states = result.context.variableContainer.states;

In the above example, member states on variableContainer is the output of the actual model.

Notification

Notification is supported in the JS runtime. Using context.notifications on the result of the run method give the application access to notifications.

result.context.notifications: where the result is the return object of run:

  1. getNotification(groupName): returns the notification for a group
  2. getAllGroups(): returns all the groups in the notification
  3. default: returns the default notification group
// executing the rules using input parameter
 var res = rule1.run(person);
 
 // listing all the notification groups
 var allGroups = res.context.notifications.getAllGroups();
 
 // accessing notification with a groupName
 var notifications = res.context.notifications.getNotification("g2");
 
 // todo: do what is needed with notifications

Decision Table

Use the Action column and set the Type to Notice.

In the above example, you can set the Notice Type or leave it blank for Error notices as the default behaviour.

Natural Language

Use $context to write notifications in Natural Language.

In the above example, logic Write Error {msg} is used to write a notification error during execution.

Extensibility

Custom Functions

In the JavaScript engine, you can introduce custom functions and use them as part of your logic.

Using Function Declaration

When custom functions are required, to ensure the function can be used in both .Net and JavaScript platform Using the command with a static method signature to register a function must be used.

For example, in below NL IsParticipant is a custom function:

<Natural>
 <Declaration>
     <Using name="IsParticipant" function="true" path="NS.MyType.IsParticipant(object, object)" assembly="CustomAssembly.dll" />
 </Declaration>
 <Dsl>
     input user, agreement
     @name calling custom func
      when R1
         IsParticipant(user, agreement)
     end
 </Dsl>
</Natural>

Register Custom Function

Now in your JavaScript register the function:

// get an instance of a runtime engine for a rule/logic
var rule1 = FlexRule.RuntimeEngine.fromJavaScript("CompanyName.WebUI.MyApp", "calling custom func");
 
// register a custom function (i.e., IsParticipant)
rule1.registerFunction("IsParticipant",
        function(u, a) {
            u.name = 'aaa';
            a.name = 'bbb';
            return true;
        }
);
 
// Running the rule by passing the input parameters
var user = {};
var agreement = {};
var res = rule1.run(user, agreement);
 
assert.equal(user.name, 'aaa', "user.name");
assert.equal(agreement.name, 'bbb', "agreement.name");

Sample

When you install FlexRule Runtime have a look at the path below:

FlexRule\Samples\Client JavaScript Rules

In this folder you can find:

  • Rule project that has the models
    • Decision Table: rules for filtering
    • Natural Language: rules for validating a registration form
  • Angular JS web application

In the JavaScript Angular JS app, two behaviours are implemented:

  1. Filtering: The rule file is called ‘States.xml’. It filters the list of states based on a selected country on the form.
  2. Form Validation: The rule file is called ‘Validation.xml’ It validates the missing and incorrect information on the web page on submission.
Updated on April 5, 2022

Was this article helpful?

Related Articles