Console

The BusinessRules sample demonstrates how Business Rules Scripting can be used to validate changes made by client applications at the server level, before committing the changes to the back-end database. The benefit of putting change validation in the middle tier is that rules can be changed and updated on the fly without having to deploy new versions of the client applications and deal with the possibility that some users have not yet updated to the latest client version.

Getting Started

The sample is typically located in C:\Program Files (x86)\RemObjects Software\Data Abstract for .NET\Samples\<language>\BusinessRules (Console), though you may have installed the Data Abstract for .NET SDK and it's samples in another location.

To build it, you will of course need Visual Studio, and like all the samples provided with Data Abstract for .NET you will need to be running Relativity Server with the DASamples Domain and the Simple Schema available.

Included with the sample is a DataTableExtension class which has a single public static method (LogToString) that takes a DataTable object and creates a nicely formatted string representation of the table that can be printed to the Console which can be useful for debugging purposes. (An example of its output can be seen at the end of this document)

Running the Sample

When run the sample sets up a connection to an instance of Relativity Server and logs in (Step 1). It then retrieves a single row from the "ClientsWithScripting" table which will be used in the following steps and prints it to the console (Step 2).

The following steps modify the data in some way and then attempt to apply that change to the server. The change is tested by the server which will return an exception if it fails to match the conditions and the contents of the exception message will be printed to the console. (Step 3-5)

Examining the Code

All of the client code can be found in the Program source file, the business rules are in the schema attached to the table as discussed below.

The main thing to note in each of the steps (2-5) is that the data is changed in the clients table and then the DataSet is passed to the Update method of RemoteDataAdapter. The Update method call is placed in a try/catch block because the server will raise an instance of DAException which should be appropriately handled; for example generating an error message informing the user about why the change could not be applied. In this sample the exception's message is printed to the console.

The Business Rules

The Business Rules are located on the server in a schema and allow you to add business logic that can be used to validate data or enforce access restrictions. The rules are written as small blocks of EcmaScript, otherwise known as JavaScript, that are triggered on certain events for instance on processing an error, after applying a delta change, before getting data and so on. To learn more about business rules, how to add/edit them and the events available check out the articles Business Rules Scripting, Business Rules Scripting API and Business Rules Scripting Events.

Here we are interested in the rules that are assigned to the "ClientsWithScripting" table. If you open Relativity Server Admin Tool and connect to the instance of Relativity Server your using. Navigate to the "DASamples" domain and select the "Simple" schema and press the "Open in Schema Modeler" button.

In Schema Modeler navigate to the "ClientsWithScripting" table, expand the tree and click on "Scripts" node. This will display a page which contains the business rules used in this sample (duplicated below) which you can modify to test if you desire.

The beforeProcessDeltaChange event is trigged each time a change is received from a client application, but before the change has been processed. It takes four arguments that are:

  • a Delta object that holds all of the changes.
  • a Delta Change object that holds information about a single delta change and contains the old and new values
  • wasRefreshed a bool this indicates if the record was refreshed
  • canRemove a bool to indicate if the record is currently allowed to be removed

There are 5 validation rules to cover all of the conditions used in this sample. If none of them generate a fail message, then the function returns and the changes are applied to the table. The fail message will not be returned until all of the delta changes have been processed.

// From the Schema
// Called before each change is applied to the database
function beforeProcessDeltaChange(delta, change, wasRefreshed, canRemove)
{
    var msg = "";
    var client = "ClientID=" + change.newValues['Id'];


    // Delete rule
    if (change.isDelete) {
        client = "ClientID=" + change.oldValues['Id'];
        msg = "Business Rule: #CLIENT: Deleting clients is prohibited!"
        .replace("#CLIENT", client);
        fail(msg);
    }

    // Discount rule. Min check
    var newDiscountValue = Math.round(100*change.newValues['Discount']);
    if (newDiscountValue < 0) {
        msg = "Business Rule: #CLIENT: Discount cannot be less than zero! Current value is: #VAL %"
        .replace("#CLIENT", client)
        .replace("#VAL", newDiscountValue);
        fail(msg);
    }

    // Discount rule. Max check
    if (newDiscountValue > 60) {
        msg = "Business Rule: #CLIENT: Discount cannot be greater than 60%! Current value is: #VAL %"
        .replace("#CLIENT", client)
        .replace("#VAL", newDiscountValue);
        fail(msg);
    }

    // Birthdate rule. Min check
    var minDate = new Date(1940, 1, 1, 0, 0, 0, 0);
    var newBirthdateValue = change.newValues['Birthdate'];
    if (minDate > newBirthdateValue) {
        msg = "Business Rule: #CLIENT: Birthdate cannot be less than 1940! Current value is: #VAL"
        .replace("#CLIENT", client)
        .replace("#VAL", newBirthdateValue);
        fail(msg);
    }

    // Birthdate rule. Max check
    var maxDate = new Date();
    if (maxDate < newBirthdateValue) {
        msg = "Business Rule: #CLIENT: Birthdate cannot be in future! Current value is: #VAL"
        .replace("#CLIENT", client)
        .replace("#VAL", newBirthdateValue);
        fail(msg);
    }

Example Output

This is an example of the output you will see when the sample is run. As you can see in each step a number of attempts are made to satisfy the Business Rule, initially going outside the bounds and printing the exception raise, before then satisfying the rule.

BusinessRules Sample
Target URL is http://localhost:7099/bin
RO SDK layer is configured.
RO DataAbstract layer is configured.
STEP 1: Login to DataService
User Id="simple";Password="simple";Domain="DASamples";Schema="Simple"
Login has been successful. Going further...

STEP 2. Select the data (single client row) ...

Table: ClientsWithScripting (1 rows from 1)
|-----------------------------------------------------------------|
| Id           | Name              | Discount     | Birthdate     |
|-----------------------------------------------------------------|
| 18           | Brian L. Rowles   |              | 19/09/1968... |
|-----------------------------------------------------------------|

STEP 3. Check the Client Discount Business Rule. Value must be in range [0%..60%]

a) Try to violate rule by setting discount to negative value ...
One or more updates failed to apply on the server.

18: Script failed in beforeProcessDeltaChange: Business Rule: ClientID=18: Discount cannot be less than zero! Current value is: -100 %


b) Try to violate rule and set too high discount  (more than 60%) ...
One or more updates failed to apply on the server.

18: Script failed in beforeProcessDeltaChange: Business Rule: ClientID=18: Discount cannot be greater than 60%! Current value is: 61 %


c) Finally, try to set discount that satisfy business rule ...

Table: ClientsWithScripting (1 rows from 1)
|-----------------------------------------------------------------|
| Id           | Name              | Discount     | Birthdate     |
|-----------------------------------------------------------------|
| 18           | Brian L. Rowles   | 0.4          | 19/09/1968... |
|-----------------------------------------------------------------|

STEP 4. Check the Client Birthdate Business Rule. Value must not be in future and be more than 1940

a) Try to violate rule by setting value beyound 1940 ...
One or more updates failed to apply on the server.

18: Script failed in beforeProcessDeltaChange: Business Rule: ClientID=18: Birthdate cannot be less than 1940! Current value is: 01/01/1935 00:00:00


b) Try to set value to date in future ...
One or more updates failed to apply on the server.

18: Script failed in beforeProcessDeltaChange: Business Rule: ClientID=18: Birthdate cannot be in future! Current value is: 17/05/2016 13:14:59


c) Try to set value that satisfy business rule (1955 year) ...

Table: ClientsWithScripting (1 rows from 1)
|-----------------------------------------------------------------|
| Id           | Name              | Discount     | Birthdate     |
|-----------------------------------------------------------------|
| 18           | Brian L. Rowles   | 0.4          | 01/01/1955... |
|-----------------------------------------------------------------|

STEP 5. Try to violate Business Rule and remove client row ...
One or more updates failed to apply on the server.

18: Script failed in beforeProcessDeltaChange: Business Rule: ClientID=18: Deleting clients is prohibited!

Done!