Skip to end of metadata
Go to start of metadata

The promotion rule engine in Elastic Path Commerce allows marketers to compose promotions that customers will see in the storefront.

JBoss Rules

The promotion rule engine is built on JBoss Rules (formerly Drools Rules). JBoss Rules is a third-party rules engine that uses a fast algorithm to evaluate rule conditions and execute their actions. The input to the JBoss Rules engine is a set of objects used in the condition evaluation and action execution as well as the set of rules, which we express as text in the proprietary Drools language.

The representation of a rule in Elastic Path is an object model of the components of a rule such as conditions, actions, and parameters used by various rule elements. The object model is persisted in the database directly with one table corresponding to one class in the rule object model. This allows the graph of rule objects to be easily stored, retrieved and modified, and stored again. The objects in the rule object model are responsible for generating Drools language code that is passed to JBoss Rules. The generated code is not persisted and it is not possible to re-create the object model representation of a rule given the Drools code.

JBoss rules supports basic evaluation of objects' properties within the engine itself. However, more complex operations are not supported. In Elastic Path, nearly all conditions are evaluated in Java and the actions are also executed in Java. This allows the condition and action code to be easily debugged and unit tested. The PromotionRuleDelegate is the class that is responsible for computing conditions and executing actions as required by JBoss Rules.

Components of a promotion

A promotion is a rule. A rule consists of rule elements. There are three types of rule elements:

  • Eligibility: Determines which customers are eligible to receive a promotion. When multiple eligibilities are specified, the user can choose whether the customer must meet all of the eligibilities or any of them.
  • Condition: Describes the set of conditions that must be true for the action to be executed. Conditions are optional. If no condition is specified, then the action will execute whenever the customer is eligible. When multiple conditions are specified, the user can again choose whether all or any of them must be satisfied.
  • Action: Describes the action that will be taken if the the customer is eligible and all conditions are met. If multiple actions are present, all actions will be executed when the conditions are met.

Promotion editor

The Commerce Manager promotion editor allows the user to compose rules from rule elements and then save those rules in the database. The storefront then retrieves the rules from the database as object graphs, requests the corresponding Drools code from the rule objects, and passes the rule code to the JBoss Rules engine. JBoss Rules will then determine which rules' actions should be executed on the Java objects that are passed to it.

Using the promotion rule editor in the Commerce Manager, users mix and match promotion rule elements to create rules. Therefore, all rule elements are independent of each other. For example, it is not possible for an action to use information determined by a condition.

Scenarios

Rules are classified into scenarios (also call promotion types) that determine when the rule will be evaluated and potentially executed while a customer is accessing the storefront. Some rule elements are valid in all scenarios and others are specific to a particular scenario. In some cases, rule elements with the same meaning must be implemented differently for multiple scenarios. There are currently two scenarios:

  • Product Catalog: The customer is browsing products in the catalog or viewing product details. Simple rules that affect viewed products can be defined in this scenario.
  • Shopping Cart: The customer is viewing the items in their shopping cart. This scenario supports more complex rules that require awareness of the combinations of items in a customer's cart.

Key classes

The key classes that represent rules in the domain model are:

  • RuleSet - Contains a set of rules valid in a given scenario
  • Rule - Contains collections of rule elements (Eligibilities, Conditions, and Actions).
  • Eligibility - Represents a condition under which a customer is eligible for a promotion
  • Condition - Represents a general condition that must be true for a promotion to be available
  • Action - Represents the action to be taken if the eligibilities and conditions are met
  • RuleParameter - Actions and conditions typically require parameters held by a RuleParameter object

In addition to representing the rules, these domain objects are responsible for generating the Drools code corresponding to the rule. Each object contributes its own portion of the drools code. The rule domain objects are also responsible for self validation. The validation and code generation is invoked by clients at the top level (Rule Set) and propagated down to the child objects.

Other key classes include:

  • EpRuleEngine - Retrieves rules from persistent storage, compiles them into drools language, and fires rules on domain objects when requested by clients.
  • PromotionRuleDelegateImpl - Performs evaluations of rule conditions and executes rule actions.

JBoss rules code

The rules objects generate Drools code such as the example below:

Adding a new rule element

Rules are composed of Rule Elements, which can be Eligibilities, Conditions, or Actions. There are several steps involved in adding a new rule element:

  1. Add the implementation to the com.elasticpath.domain.rules.impl package and extend from an appropriate base class. If you are creating an action, extend AbstractRuleActionImpl, otherwise extend AbstractRuleElementImpl.
  2. Add a JUnit test case for the element, which should extend AbstractTestRuleElementImpl.
  3. Add a method in PromotionRuleDelegateImpl (and its interface) that will execute the action or condition of your rule element.
  4. Unit test this delegate method in PromotionRuleDelegateImplTest
  5. Add the rule element bean name to ContextIdNames and also to the bean definitions in PrototypeBeanFactory
  6. Add the rule element to the appropriate category in the rule service bean definition in service.xml
  7. Integration test a rule containing the new rule element by firing it through the harness set up in EpRuleEngineImplTest.
  8. Add an entry in the RuleElementType enum for the new rule element.
  9. If adding a new rule parameter type, you will need to modify the Java code for the Commerce Manager Client rule editor.  The files you may need to change include:
    1. NewPromotionWizardRulesPage - UI for adding a new rule
    2. PromotionRulesDefinitionPart - UI for editing a rule
    3. PromotionRulesWidgetUtil - utility methods for creating UI elements and performing rule element parameter data binding
    4. PromotionsMessages - defines localized text for the rule element
    5. PromotionsResources.properties - localized text for the rule element

Note: Existing rules stored in the database will not be useable if existing code is changed due to serialization, since the precompiled classes themselves are stored. It is recommended that the TRULESTORAGE data is cleaned out if this occurs.

Testing rules

Rules are extensively tested by JUnit at several levels. The following kinds of JUnit tests are most frequently added or extended when extending the rules system:

  • Rule Element Tests. Each RuleElement should have a unit test. Tests for Eligibilities and Conditions should extend from AbstractTestRuleElementImpl. Tests for actions should extend from AbstractRuleElementImplTest.
  • PromotionRuleDelegateImplTest. Add test cases to this class to test the execution of rule actions by the PromotionRuleDelegateImpl. Tests should also be added for each condition and eligibility decision that is delegated to the PromotionRuleDelegate.
  • EpRuleEngineImplTest. This test suite is used to test the highest level of integration in the core rules system and actually runs the JBoss Rules engine to test that it executes generated rule code. When testing a new rule, add the rule element to the rule set in createShoppingCartRuleSet or createCatalogRuleSet depending on the scenario in which the rule element is valid. The rule delegate method that should be invoked by the rule engine must then be mocked in testFireShoppingCartRules() or testFireCatalogRules().

Once the rule system is successfully executing through the unit tests, rules can be tested in the Commerce Manager Client and Storefront. Refer to the Configuration section below to set up the system for easier rule testing.

To assist with troubleshooting rules engine failures, the Drools code generated by the rules domain objects is logged to the log file or console.

Firing rules in the storefront

The Store Front uses EpRuleEngineImpl to apply promotion rules to products and shopping carts. Most of the calls for firing the shopping cart rules are made by the shopping cart itself in response to changes in shopping cart state. Services typically fire rules on products as required. The set of rules to be passed to JBoss Rules is loaded at start time and cached by the EpRuleEngineImpl. EpRuleEngine.compileRuleBase() is invoked periodically by a quartz scheduler to re-load rules from the database.

Configuration

  • The promotion rulebase can be configured to re-build periodically. Scheduling and configuration can be found under the search server's quartz.xml. This means that rules will be re-loaded from the database and compiled into the input format for JBoss Rules. This rule compilation operation is expensive and should not be performed more frequently than every 5-10 seconds.
  • For rules to take effect immediately after rulebase compilation, it is necessary to disable caching (Both the second-level cache and the product retrieval strategy defined in service.xml). This is useful for testing but disabling caching is not recommended for production environments.
Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.