Slide 1

Slide 1 text

1 Introducing Drools Mario Fusco @mariofusco Principal Software Engineer Drools Project Lead May, 2021

Slide 2

Slide 2 text

What a rule engine is A business rules engine is a software system that executes one or more business rules in a runtime production environment. The rules might come from legal regulation ("An employee can be fired for any reason or no reason but not for an illegal reason"), company policy ("All customers that spend more than $100 at one time will receive a 10% discount"), or other sources. A business rule system enables these company policies and other operational decisions to be defined, tested, executed and maintained separately from application code.

Slide 3

Slide 3 text

What a rule-based program is ➢ A rule-based program is made up of discrete rules, each of which applies to some subset of the problem ➢ It is simpler, because you can concentrate on the rules for one situation at a time ➢ It can be more flexible in the face of fragmentary or poorly conditioned inputs ➢ Used for problems involving control, diagnosis, prediction, classification, pattern recognition … in short, all problems without clear algorithmic solutions Declarative (What to do) Imperative (How to do it) Vs.

Slide 4

Slide 4 text

Advantages of Declarative Programming ➢ Easier to understand → It is more likely for a technically skilled business analyst to verify, validate or even change a rule than a piece of Java code ➢ Improved maintainability → We don't care about how to implement a solution only what needs to be done to solve a problem ➢ Deals with evolving complexity → It's easier to modify a rule than a Java program and to determine the impact of this change on the rest of the application ➢ Modularity → Each rule models an isolated and small portion of your business logic and is not part of a monolithic program ➢ Requirements can be more naturally translated into rules ➢ Clear separation of business logic from the rest of the system

Slide 5

Slide 5 text

When should you use a Rule Engine? ➢ The problem is beyond any obvious algorithmic solution or it isn't fully understood ➢ The logic changes often ➢ Domain experts (or business analysts) are readily available, but are nontechnical ➢ You want to isolate the key parts of your business logic, especially the really messy parts

Slide 6

Slide 6 text

How a rule-based system works

Slide 7

Slide 7 text

How a rule-based system works Core Engine

Slide 8

Slide 8 text

Rule's anatomy rule “” when then end Quotes on Rule names are optional if the rule name has no spaces. salience agenda-group no-loop auto-focus duration .... Pattern-matching against objects in the Working Memory Code executed when a match is found

Slide 9

Slide 9 text

Imperative vs Declarative public void helloMark(Person person) { if ( person.getName().equals( “mark” ) { System.out.println( “Hello Mark” ); } } rule “Hello Mark” when Person( name == “mark” ) then System.out.println( “Hello Mark” ); end A method must be called directly Specific passing of arguments Rules can never be called directly Specific instances cannot be passed but are automatically selected with pattern- matching

Slide 10

Slide 10 text

What is a pattern Person( name == “mark” ) Pattern Object Type Field Constraint Field Name Restriction

Slide 11

Slide 11 text

Rule's definition // Java public class Applicant { private String name; private int age; private boolean valid; // getter and setter here } rule "Is of valid age" when $a : Applicant( age >= 18 ) then modify( $a ) { valid = true }; end // DRL declare Applicant name : String age : int valid : boolean end

Slide 12

Slide 12 text

More Pattern Examples Person( $age : age ) Person( age == ( $age + 1 ) ) Person(age > 30 && < 40 || hair in (“black”, “brown”) ) Person(pets contain $rover ) Person(pets[’rover’].type == “dog”)

Slide 13

Slide 13 text

Conditional Elements not Bus( color = “red” ) exists Bus( color = “red” ) forall ( $bus : Bus( color == “red” ) ) $owner : Person( name == “mark” ) Pet( name == “rover” ) from $owner.pets $zipCode : ZipCode() Person( ) from $hbn.getNamedQuery(“Find People”) .setParameters( [ “zipCode” : $zipCode ] ) .list() Hibernate session 'from' can work on any expression

Slide 14

Slide 14 text

Complex Event Processing Event A record of state change in the application domain at a particular point in time Complex Event An abstraction of other events called its members Complex Event Processing Processing multiple events with the goal of identifying the meaningful events within the event cloud

Slide 15

Slide 15 text

Drools CEP ➢ Drools modules for Complex Event Processing ➢ Understand and handle events as a first class platform citizen (actually special type of Fact) ➢ Select a set of interesting events in a cloud or stream of events ➢ Detect the relevant relationship (patterns) among these events ➢ Take appropriate actions based on the patterns detected

Slide 16

Slide 16 text

Cloud vs. Stream Mode Cloud Mode (default) Stream Mode ➢ No notion of time ➢ No requirement on event ordering ➢ Since they are based on the concept of “now” it is not possible to use sliding windows ➢ Not possible to determine when events can no longer match, so the application must explicitly retract events when they are no longer necessary ➢ Events in each stream must be time-ordered ➢ The engine will force synchronization between streams through the use of the session clock ➢ Sliding Window support ➢ Automatic Event Lifecycle Management ➢ Automatic Rule Delaying when using Negative Patterns

Slide 17

Slide 17 text

Events as Facts in Time rule "Sound the alarm" when $f : FireDetected( ) not( SprinklerActivated( this after[0s,10s] $f ) ) then // sound the alarm end Temporal relationships between events

Slide 18

Slide 18 text

18 Core Engine

Slide 19

Slide 19 text

From ReteOO

Slide 20

Slide 20 text

Entry-point All facts are inserted here Type Nodes Discriminate on fact type Alpha Network Evaluate name == “Mark” Terminal Nodes Put activated rule into the agenda Beta Network Evaluate age > other.age From ReteOO

Slide 21

Slide 21 text

● Facts are propagated into the network lazily, at firing time instead of insertion time ● Facts are propagated in batches ● Same nodes as ReteOO but grouped in segments ● Segments, like nodes, can be shared across multiple rules ● The sequence of one or more segments performing the evaluation of a rule is called a path ● A segment can be selectively unlinked from the rete network if no facts satisfies the conditions of one of its node ● A path is linked, and then the corresponding rule evaluated, only if all its segments are also linked … to Phreak

Slide 22

Slide 22 text

Phreak - Rule Structure

Slide 23

Slide 23 text

From ReteOO to Phreak Advantages and attention points ● Preserves all ReteOO features and optimizations combining them with pros of other well known algorithms like Leaps, Collection Oriented Match, L/R Unlinking … ○ Order of execution of rules with the same priority may be different ● Laziness: all propagations and corresponding constraints evaluations are performed at firing time and not at insertion time ○ Set based propagation and WMA normalization: In ReteOO every working memory change would cause a rule to fire. In Phreak, a sequence of actions can be normalized to reduce overhead (only the “last” change is applied) ● On average 20% faster then ReteOO (and up to 400% faster on specific use cases) ● Reduced memory footprint ● More forgiving in presence of badly written rules (rules that cannot fire are never evaluated) ● Enables future optimizations including engine parallelization (Drools 7 already includes an experimental parallel engine)

Slide 24

Slide 24 text

Keep innovating

Slide 25

Slide 25 text

25 Executable model

Slide 26

Slide 26 text

26 Drools Deep Dive Representing a rule in pure Java rule “Older than Mark” when $p1: Person( name == “Mark” ) $p2: Person( name != “Mark”, age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end

Slide 27

Slide 27 text

27 Drools Deep Dive Representing a rule in pure Java Variable markV = declarationOf( Person.class ); Variable olderV = declarationOf( Person.class ); Rule rule = rule( "Older than Mark" ) .build( pattern(markV) .expr("exprA", p -> p.getName().equals( "Mark" ), alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name", "age" )), pattern(olderV) .expr("exprB", p -> !p.getName().equals("Mark"), alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name" )) .expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(), betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ), reactOn( "age" )), on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() )) ); rule “Older than Mark” when $p1: Person( name == “Mark” ) $p2: Person( name != “Mark”, age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end Executabl e model

Slide 28

Slide 28 text

28 Drools Deep Dive Representing a rule in pure Java Variable markV = declarationOf( Person.class ); Variable olderV = declarationOf( Person.class ); Rule rule = rule( "Older than Mark" ) .build( pattern(markV) .expr("exprA", p -> p.getName().equals( "Mark" ), alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name", "age" )), pattern(olderV) .expr("exprB", p -> !p.getName().equals("Mark"), alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name" )) .expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(), betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ), reactOn( "age" )), on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() )) ); rule “Older than Mark” when $p1: Person( name == “Mark” ) $p2: Person( name != “Mark”, age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end Executabl e model

Slide 29

Slide 29 text

29 Drools Deep Dive Representing a rule in pure Java Variable markV = declarationOf( Person.class ); Variable olderV = declarationOf( Person.class ); Rule rule = rule( "Older than Mark" ) .build( pattern(markV) .expr("exprA", p -> p.getName().equals( "Mark" ), alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name", "age" )), pattern(olderV) .expr("exprB", p -> !p.getName().equals("Mark"), alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name" )) .expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(), betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ), reactOn( "age" )), on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() )) ); rule “Older than Mark” when $p1: Person( name == “Mark” ) $p2: Person( name != “Mark”, age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end Indexes and reactivity explicitly defined Executabl e model

Slide 30

Slide 30 text

Executable Model at a glance ● A pure Java DSL for Drools rules authoring ● A pure Java canonical representation of a rule base ● Automatically generated by Maven plugin ● Can be embedded in JAR ○ Faster compilation ○ Backward/Forward compatible ● Allow for faster prototyping and experimentation of new features ● Prerequisite to make Drools natively compilable on GraalVM RULES

Slide 31

Slide 31 text

● A cloud-native development, deployment and execution platform for business automation: ○ Rules and Decisions ○ Processes and Cases ● ... under the covers ○ the backbone is code generation based on business assets ○ executable model for the process/rule/decision definitions ○ type safe data model that encapsulates variables ○ REST api for each public business process/decision/rule Introducing

Slide 32

Slide 32 text

+ = Native

Slide 33

Slide 33 text

JVM vs. Native

Slide 34

Slide 34 text

Q&A