The drools-examples project contains a sample process
(org.drools.examples.process.order
) that illustrates
some of the advantages of being able to combine processes and rules. This
process describes an order application where incoming orders are validated,
discounts are calculated and shipping of the goods is requested.
Drools Flow can easily include a set of rules as part of the process. The rules that need to be evaluated should be grouped in a ruleflow group, using the <kw>ruleflow-group</kw> rule attribute. Activating a RuleSet node for the group triggers the evaluation of these rules in your process. This example uses two RuleSet nodes in the process: one for the validation of the order and one for calculating the discount. For example, one of the rules for validiting an order is shown below. Note the <kw>ruleflow-group</kw> attribute, which ensures that this rule is evaluated as part of the RuleSet node with the same ruleflow group shown in the figure.
rule "Invalid item id" ruleflow-group "validate" lock-on-active true when o: Order() i: Order.OrderItem() from o.getOrderItems() not (Item() from itemCatalog.getItem(i.getItemId())) then System.err.println("Invalid item id found!"); o.addError("Invalid item id " + i.getItemId()); end
Rules can be used for expressing and evaluating complex constraints in your process. For example, when to decide about the choice of the execution path at a Split node, rules could be used to define these conditions. Similarly, a Wait state could use a rule to define the wait duration. This example uses rules for deciding the next action after validating the order. If the order contains errors, a sales representative should try to correct the order. Orders with a value > 1000$ are more important, so that a senior sales representative should attend to the order. All other orders should just proceed normally. A decision node is used to select one of these alternatives, and rules are used to describe the constraints for each of them.
Human tasks can be used in a process to describe work that needs to be executed by a human actor. The selection of the actor could be based on the current state of the process and the history. Assignment rules describe how to determine the actor, based on this information. These assignment rules will then be applied automatically whenever a new human task needs to be executed.
Note that the rules shown below are written in a Domain Specific Language (DSL), tailored to the specific requirements for formulating conditions in the order processing environment.
/********** Generic assignment rules **********/ rule "Assign 'Correct Order' to any sales representative" salience 30 when There is a human task - with task name "Correct Order" - without actor id then Set actor id "Sales Representative" end /********** Assignment rules for the RuleSetExample process **********/ rule "Assign 'Follow-up Order' to a senior sales representative" salience 40 when Process "org.drools.examples.process.ruleset.RuleSetExample" contains a human task - with task name "Follow-up Order" - without actor id then Set actor id "Senior Sales Representative" end
Rules can be used for describing exceptional situations and how to respond to these situations. Adding all this information in the control flow of the regular process makes the basic process much more complex. Rules can be used to handle each of these situations separately, leaving the core process in its simple form. It also makes it much easier to adapt existing processes to take previously unanticipated events into account.
The process defines the overall control flow. Rules could be used to add additional concerns to this process without making the overall control flow more complex. For example, rules could be defined to log certain information during the execution of the process. The original process is not altered, whereas all logging functionality is cleanly modularized as a set of rules. This greatly improves reusability, allowing users to easily apply the same strategy to different processes, readability (by not altering the control flow of the original process) and maintainability, due to the separation of the logging strategy rules from those of the process itself.
Rules let you dynamically fine-tune the behavior of your processes. Imagine that a problem is encountered, at runtime, with one of the processes. Now, new rules could be added, at runtime, to log additional information or for handling specific process states. Once the problem is solved or the circumstances have changed, these rules can easily be removed again. Based on the current status, different strategies could be selected dynamically. For example, based on the current load of all the services, rules could be used to optimize the process to the current load. This process contains a simple example that allows you to dynamically add or remove logging for the "Check Order" task. When the "Debugging output" checkbox in the main application window is checked, the rule shown below is loaded dynamically, to write log output to the console whenever the "Check Order" task is requested. Unchecking the box will dynamically remove the rule again.
rule "Log the execution of 'Correct Order'" salience 25 when workItemNodeInstance: WorkItemNodeInstance( workItemId <= 0, node.name == "Correct Order" ) workItem: WorkItemImpl( state == WorkItemImpl.PENDING ) from workItemNodeInstance.getWorkItem() then ProcessInstance proc = workItemNodeInstance.getProcessInstance(); VariableScopeInstance variableScopeInstance = (VariableScopeInstance)proc.getContextInstance( VariableScope.VARIABLE_SCOPE ); System.out.println( "LOGGING: Requesting the correction of " + variableScopeInstance.getVariable("order")); end
Processes and rules are integrated in the Drools Eclipse IDE. Both processes and rules are simply considered as different types of business logic, to be managed almost identically. For example, loading a process or a set of rules into the engine is very similar. Also, different rule implementations, such DRL or DSL, are handled in a uniform way.
private static KnowledgeBase createKnowledgeBase() throws Exception { KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add( ResourceFactory.newClassPathResource( "RuleSetExample.rf", OrderExample.class), ResourceType.DRF ); kbuilder.add( ResourceFactory.newClassPathResource( "workflow_rules.drl", OrderExample.class), ResourceType.DRL ); kbuilder.add( ResourceFactory.newClassPathResource( "assignment.dsl", OrderExample.class), ResourceType.DSL ); kbuilder.add( ResourceFactory.newClassPathResource( "assignment.dslr", OrderExample.class), ResourceType.DSLR ); KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase(); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); return kbase; }
Our audit log also contains an integrated view, showing how rules and processes are influencing each other. For example, a part of the log shows how rule "5% discount" is executed as part of the node "Calculate Discount".
Rules do not need to be defined using the core rule language syntax, but they also can be defined using our more advanced rule editors, using domain-specific languages, decision tables, guided editors, etc. Our example defines a domain-specific language for describing assignment rules, based on the type of task, its properties, the process it is defined in, etc. This makes the assignment rules much more understandable for non-experts.
/********** Generic assignment rules **********/ rule "Assign 'Correct Order' to any sales representative" salience 30 when There is a human task - with task name "Correct Order" - without actor id then Set actor id "Sales Representative" end /********** Assignment rules for the RuleSetExample process **********/ rule "Assign 'Follow-up Order' to a senior sales representative" salience 40 when Process "org.drools.examples.process.ruleset.RuleSetExample" contains a human task - with task name "Follow-up Order" - without actor id then Set actor id "Senior Sales Representative" end