JBoss.orgCommunity Documentation
Drools Flow is a workflow and process engine that allows advanced integration of processes and rules. This chapter discusses the integration of rules and processes, ranging from simple to advanced scenarios.
Workflow languages that depend purely on process constructs (like nodes and connections) to describe the business logic of applications tend to be quite complex. While these workflow constructs are very well suited to describe the overall control flow of an application, it can be very difficult to describe complex logic and exceptional situations. Therefore, executable processes tend to become very complex. We believe that, by extending a process engine with support for declarative rules in combination with these regular process constructs, this complexity can be kept under control.
Simplicity: Complex decisions are usually easier to specify using a set of rules. Rules can pinpoint complex business logic more easily, using their advanced constraint language. Multiple rules can be combined, each describing a part of the business logic.
Agility: Rules and processes can have a separate life cycle. This means that we can change the rules describing some crucial decision points without having to change the process itself. Rules can be added, removed or modified to fine-tune the behavior of the process to the constantly evolving requirements and environment.
Different scope: Rules can be reused across processes or outside processes. Therefore, your business logic is not locked inside your processes.
Declarativeness: Focus on describing "what" instead of "how".
Granularity: It is easy to write simple rules that handle specific circumstances. Processes are more suited to describe the overall control flow but tend to become very complex if they also need to describe a lot of exceptional situations.
Data-centric: Rules can easily handle large data sets.
Performance: Rule evaluation is optimized.
Advanced condition and action language: Rule languages support advanced features like custom functions, collections, conditional elements, including quantifiers, etc.
High-level: By using DSLs, business editors, decision tables, and decision trees, your business logic could be described in a way that can be understood (and possibly even modified) by business users.
Drools Flow combines a process and a rules engine in one software product. This offers several advantages, compared to trying to loosely couple an existing process and rules product.
Simplicity: Easier for end user to combine both rules and processes.
Encapsulation: Sometimes close integration between processes and rules is beneficial.
Performance: No unnecessary passing, transformation or synchronization of data
Learning curve: Easier to learn one product.
Manageability: Easier to manage one product, rules and processes can be similar artefacts in a larger knowledge repository.
Integration of features: We provide an integrated IDE, audit log, web-based management platform, repository, debugging, etc.
Workflow languages describe the order in which activities should be performed using a flow chart. A process engine is responsible for selecting which activities should be executed based on the current state of the executing processes. On the other hand, rules are composed of a set of conditions that describe when a rule is applicable and an action that is executed when the conditions are met. The rules engine is then responsible for evaluating and executing the rules. It decides which rules need to be executed based on the current state of the application.
Workflow processes are very good at describing the overall control flow of (possibly long-running) applications. However, processes that are used to define complex business decisions, to handle a lot of exceptional situations, and need to respond to various external events tend to become very complex indeed. Rules are very good at describing complex decisions and reasoning about large amounts of data or events. It is, however, not trivial to define long-running processes using rules.
In the past, users were forced to choose between defining their business logic using either a process or a rules engine. Problems that required complex reasoning about large amounts of data used a rules engine, while users that wanted to focus on describing the control flow of their processes were forced to use a process engine. However, businesses nowadays might want to combine both processes and rules in order to be able to define all their business logic in the format that best suits their needs.
Basically, both a rules and a process engine will derive the next steps that need to be executed by looking at its Knowledge Base (a set of rules or processes, respectively) and the current known state of the application (the data in the Working Memory or the state of the executing process instances, respectively). If we want to integrate rules and processes, we need an engine that can decide the next steps taking into account the logic that is defined inside both the processes and the rules.
It is very difficult (and probably very inefficient as well) to extend a process engine to also take rules into account. The process engine would need to check for rules that might need to be executed at every step and would have to keep the data that is used by the rules engine up to date. However, it is not that difficult to "teach" a rules engine about processes. If the current state of the processes is also inserted as part of the Working Memory data the rules engine reasons about, and we instruct the rules engine how to derive the next steps of an executing process, the rules engine will then be able to derive the next steps taking rules and processes into account jointly.
From the process perspective, this means that there is an inversion of control. A normal process engine exercises full control, deriving the next steps based on the current state of the process instance. If needed, it can contact external services to retrieve additional information, but it solely decides which steps to take, and is alone responsible for executing these steps.
However, only our extended rules engine (that can reason jointly about rules and processes) is capable of deriving the next steps taking both rules and processes into account. If a part of the process needs to be executed, the rules engine will request the process engine to execute this step. Once this step has been performed, the process engine returns control to the rules engine to again derive the next steps. This means that the control on what to do next has been inverted: the process engine itself no longer decides the next step to take but our enhanced rules engine will be in control, notifying the process engine what to execute next, and when.
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 ruleflow-group
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
ruleflow-group
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