In this section, we will look at using Rulette SDK to model some business rules. If you have not yet familiarized yourself with the basic concepts of Rulette, you should do so before diving into this section.
The following code assumes that you are using the official mysql-data-provider library for supplying rules to Rulette engine. If you are using a custom implementation, you will have to use the corresponding techniques to handle your implementation. The Rulette related details should not change.
Many of these examples are also showcased in the rulette-examples module.
Adding dependencies
Rulette jars are published to the public Maven repository. Check the homepage for the latest stable version.
Maven
If you use Maven, you can add the rulette engine and mysql-data-provider dependencies as follows.
<dependency> <groupId>com.github.kislayverma.rulette</groupId><artifactId>rulette-engine</artifactId> <version>${rulette-version}</version> <scope>compile</scope></dependency> <dependency><groupId>com.github.kislayverma.rulette</groupId><artifactId>rulette-mysql-provider</artifactId><version>${rulette-version}</version> <scope>compile</scope> </dependency>
Gradle
If you use Gradle, you can add the required dependencies as follows
compile group: 'com.github.kislayverma.rulette', name: 'rulette-engine', version: '1.3.4'
compile group: 'com.github.kislayverma.rulette', name: 'rulette-mysql-provider', version: '1.3.4'
Setting up the rule system in MySQL
First load all your rules into a MySQL table which has column names representing the rule inputs.
- The table MUST have a primary key to represent unique id of a rule (Rulette expects this column to be called `id` by default, but you can use some other name also).
- The table MUST have a VARCHAR column to represent the output of rule evaluation (this is called `rule_output_id ` by default but you can use some other name).For all range inputs, the min and max value constituting the range should be put in separate columns.
You can run the setup script given in the mysql-provider module to set up your rule system metadata.
Populate the rule system table with the name of your rule system, the name of the table where your rules are stored, and the names of your primary key column and the rule output column.
Populate the rule input table with the name of the rule inputs, their types and data types. For value inputs, ensure that rule input names are set to be EXACTLY the same as the column names of your rule table. For range inputs, ensure that the min and max value column names are populated to be exactly the column names you used to store these values in the rule data table.
You can set up multiple rule systems in this same setup if you want to. Load all of your different rule-sets in different tables and make corresponding entries in the meta-data tables to set everything up.
A sample script for this process is included here.
Creating a database configuration file
Create a properties file containing the database credentials and other configurations which Rulette can use to access the rule-system meta-data. A sample file is included here.
Instantiating a Rule System
First instantiate a data provider to access the rule system data in MySQL. Make sure that the config file is accessible to the code.
File f = new File(configFilePath);
IDataProvider dataProvider = new MysqlDataProvider(f.getPath());
Now instantiate the rule system by passing in this provider and the name of the rule system you want to instantiate.
RuleSystem rs = new RuleSystem(RULE_SYSTEM_NAME, dataProvider);
This can fail if you accidentally configured conflicting rules. Rulette will report the conflicting rules and abort.
Rule Evaluation
Create a map of the inputs for which you want to determine the rule output.
Map<String, String> inputMap = new HashMap<>();
inputMap.put("item_type", "3");
inputMap.put("source_state", "WES");
inputMap.put("mrp_threshold", "10000.00");
Rule applicableRule = rs.getRule(inputMap);
If no rule matches, a null value is returned.
Adding/Updating/Deleting rules
Adding a new rule
Create a map with all input values to be set. The keys should be exactly the same as the rule input names. For range values, keys should be the names of the min and max value column names. Any rule input not specified will be set to null (“Any”).
Map<String, String> inputMap = new HashMap<>();
inputMap.put("source_state", "WES");
inputMap.put("intestate_sale", "NO");
inputMap.put("item_type", "Shorts");
inputMap.put("min_mrp", "1000");
inputMap.put("max_mrp", "5000");
// Not putting material so that it gets set to "Any"
inputMap.put(“rule_output_id”, “5”);
Rule createdRule = rs.addRule(inputMap);
If the rule you are trying to create conflicts with an existing rule, this operation will fail with a RuleConflictException
.
Update a rule
First get the rule you want to modify using one of the many the getRule APIs. Here we get the rule using its primary identifier.
Rule existingRule = rs.getRule(“192);
Now modify the values of rule input using the setColumnData
API. Note that this API does not modify the current rule but rather returns a new Rule object with modified rule values. Rule objects are immutable to prevent accidental updates to rules from spreading unless they are explicitly updated.
Rule modifiedRule = existingRule.setColumnData(“source_state”, “WES”);
Rule updatedRule = rs.updateRule(existingRule, modifiedRule);
This operation can fail with a RuleConflictException
if the modified rule conflicts with some other existing rule.
Delete an existing rule
A rule can be deleted if you have the Rule object itself or if you know its primary key.
rs.deleteRule(“192”); //Deleting rule by id
Rule existingRule = rs.getRule(“192);
rs.deleteRule(existingRule); // Deleting using the rule itself
Adding/Deleting rule inputs
Adding a rule input
You can add a new rule input by passing a RuleInputMetaData object with the properties set to the RuleSystem::createRuleInput
API
RuleInputMetadata rimd = new RuleInputMetaData(“newInput”,“6”,“VALUE”, “STRING”, null, null);
rs.addRuleInput(rimd);
rs.reload();
Adding a new rule input does not immediately bring it into effect. You have to explicitly invoke the RuleSystem::reload
API to build the rule system afresh with the new metadata to make the change effective. The reload API may fail if you added the rule input with some incorrect data (e.g. a name which does not match any column in your MySQL table).
Deleting a rule input
A rule input can be deleted via its name.
rs.deleteRuleInput(“newInput”);
Similar to adding a rule input, deleting a rule input does not bring the changes into effect immediately. You have to call the reload API for this, which might fail with a RuleConflictException
.