{"id":90780,"date":"2019-04-17T10:00:51","date_gmt":"2019-04-17T07:00:51","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=90780"},"modified":"2019-04-16T10:56:31","modified_gmt":"2019-04-16T07:56:31","slug":"a-complete-tutorial-on-the-drools-business-rule-engine","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html","title":{"rendered":"A complete tutorial on the Drools business rule engine"},"content":{"rendered":"<p>As always we share the code presented in the tutorial in a companion repository: <a href=\"https:\/\/github.com\/ftomassetti\/EmailSchedulingRules\">EmailSchedulingRules<\/a>.<\/p>\n<p>Business rules work very well to represent the logic for certain domains. They work well because <strong>they result intuitive and close to the way of thinking of many types of domain experts<\/strong>. The reason for that it is that they permit to decompose a large problem in single components. In this way the user has not to deal with the orchestration of all the single rules: this is the added value provided by the business rule engine.<\/p>\n<p>In this article we will discuss one specific example of application written by using business rules. We will write the rules to decide which email to send to the subscribers to a newsletter. We will see different types of rules and how we could express them using the Drools Rule Language. We will also see how to configure <a href=\"https:\/\/www.drools.org\/\">Drools<\/a> (spoiler: it will be easy) and have the system elaborate the rules to produce a result we can use.<\/p>\n<p>I think that business rules are quite interesting because they permit to look at problems in a different way. As developers we are very used to the imperative paradigm or functional paradigms. However there are other paradigms, like state machines and business rules, which are not so commonly used and which can be a much better fit in some contexts.<\/p>\n<p><em>As always we share the code presented in the tutorial in a companion repository: <a href=\"https:\/\/github.com\/ftomassetti\/EmailSchedulingRules\">EmailSchedulingRules<\/a>.<\/em><\/p>\n<h2 class=\"wp-block-heading\">What problem we are trying to solve<\/h2>\n<p>Let\u2019s consider the domain of email marketing. As marketers we have an email list of persons interested in our content. Each of them may have demonstrate interest in a specific topic, read some of our articles and bought certain products. Considering all their history and preferences we want to send to them at each time the most appropriate content. This content may be either educative or proposing some deal. The problem is that there are constraints we want to consider (i.e., not sending emails on sunday or not sending emails promoting a product to someone who already bought it).<\/p>\n<p>All these rules are simple per se, but the complexity derives by how they are combined and how they interact.&nbsp;The business rule engine will deal with that complexity for us, all we have to do is to express clearly the single rules. Rules will be expressed in the terms of our domain data so let\u2019s focus on our domain model first.<\/p>\n<h3 class=\"wp-block-heading\">The model of our domain<\/h3>\n<p>In our domain model we have:<\/p>\n<ul class=\"wp-block-list\">\n<li><em>Emails<\/em>: the single emails we want to send, described by their title and content<\/li>\n<li><em>Email Sequences<\/em>: groups of emails that have to be sent in a specific order, for example a set of emails representing a tutorial or describing different features of a product<\/li>\n<li><em>Subscribers<\/em>: the single subscriber to the mailing list. We will need to know which emails we sent to him, what things he is interested in, and which products he bought<\/li>\n<li><em>Products<\/em>: the products we sell<\/li>\n<li><em>Purchases<\/em>: the purchases subscribers have made<\/li>\n<li><em>Email Sending:&nbsp;<\/em>the fact we sent or are about to send a certain email, on a certain date to a certain subscriber<\/li>\n<li><em>Email Scheduling<\/em>:&nbsp;the plan for sending an email, with some additional information<\/li>\n<\/ul>\n<p>The latter two elements of our domain model could seem less obvious compared to the others, but we will see in the implementation for which reasons we need them.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/scheduling-1024x615.png\" alt=\"business rule engine\" class=\"wp-image-90798\" width=\"768\" height=\"461\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/scheduling-1024x615.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/scheduling-300x180.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/scheduling-768x461.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/04\/scheduling.png 1112w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure>\n<\/div>\n<h3 class=\"wp-block-heading\">What our system should do<\/h3>\n<p>Our system should execute all the rules, using the Drools engine, and to determine for each user which email we should send on a specific day. The result could be the decision to not send any email, or to send an email, selecting one among many possible emails.<\/p>\n<p>An important thing to consider is that these rules may evolve over time. The people in charge of marketing may want to try new rules and see how they affect the system. Using Drools it should be easy for them to add or remove rules or tweak the existing rules.<\/p>\n<p>Let\u2019s stress this out:<\/p>\n<p><em>these domain experts should be able to experiment with the system and try things out quickly, without always needing help from developers<\/em>.<\/p>\n<h3 class=\"wp-block-heading\">The rules<\/h3>\n<p>Ok, now that we know which data do we have, we can express rules based on that model.<\/p>\n<p>Let\u2019s see some examples of rules we may want to write:<\/p>\n<ul class=\"wp-block-list\">\n<li>We may have sequences of emails, for example the content of a course. They have to be sent in order<\/li>\n<li>We may have time sensitive emails that should either be sent in a specific time window or not sent at all<\/li>\n<li>We may want to avoid sending emails on specific days of the week, for example on the public holidays&nbsp;<em>in the country where the subscriber is based<\/em><\/li>\n<li>We may want to send certain type of emails (for example proposing a deal) only to persons who received certain other emails (for example at least 3 informative emails on the same subject)<\/li>\n<li>We do not want to propose a deal on a certain product to a subscriber who has already bought that product<\/li>\n<li>We may want to limit the frequency we send emails to users. For example, we may decide to not send an email to a user if we have sent already one in the last 5 days<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Setting up drools<\/h2>\n<p>Setting up drools can be very simple. We are looking into running drools in a standalone application. Depending on your context this may or may not be an acceptable solution and in some cases you will have to look into JBoss, the application server supporting Drools. However if you want to get started you can forget all of this and just configure your dependencies using Gradle (or Maven). You can figure out the boring configuration bits later, if you really have to.<\/p>\n<div>\n<div id=\"highlighter_950233\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<div class=\"line number20 index19 alt1\">20<\/div>\n<div class=\"line number21 index20 alt2\">21<\/div>\n<div class=\"line number22 index21 alt1\">22<\/div>\n<div class=\"line number23 index22 alt2\">23<\/div>\n<div class=\"line number24 index23 alt1\">24<\/div>\n<div class=\"line number25 index24 alt2\">25<\/div>\n<div class=\"line number26 index25 alt1\">26<\/div>\n<div class=\"line number27 index26 alt2\">27<\/div>\n<div class=\"line number28 index27 alt1\">28<\/div>\n<div class=\"line number29 index28 alt2\">29<\/div>\n<div class=\"line number30 index29 alt1\">30<\/div>\n<div class=\"line number31 index30 alt2\">31<\/div>\n<div class=\"line number32 index31 alt1\">32<\/div>\n<div class=\"line number33 index32 alt2\">33<\/div>\n<div class=\"line number34 index33 alt1\">34<\/div>\n<div class=\"line number35 index34 alt2\">35<\/div>\n<div class=\"line number36 index35 alt1\">36<\/div>\n<div class=\"line number37 index36 alt2\">37<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">buildscript {<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ext.droolsVersion = <\/code><code class=\"bash string\">\"7.20.0.Final\"<\/code><\/div>\n<div class=\"line number3 index2 alt2\">&nbsp;<\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">repositories {<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">mavenCentral()<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number8 index7 alt1\">&nbsp;<\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash plain\">plugins {<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash functions\">id<\/code> <code class=\"bash string\">\"org.jetbrains.kotlin.jvm\"<\/code> <code class=\"bash plain\">version <\/code><code class=\"bash string\">\"1.3.21\"<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number12 index11 alt1\">&nbsp;<\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash plain\">apply plugin: <\/code><code class=\"bash string\">'java'<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash plain\">apply plugin: <\/code><code class=\"bash string\">'idea'<\/code><\/div>\n<div class=\"line number15 index14 alt2\">&nbsp;<\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash plain\">group <\/code><code class=\"bash string\">'com.strumenta'<\/code><\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash plain\">version <\/code><code class=\"bash string\">'0.1.1-SNAPSHOT'<\/code><\/div>\n<div class=\"line number18 index17 alt1\">&nbsp;<\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash plain\">repositories {<\/code><\/div>\n<div class=\"line number20 index19 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">mavenLocal()<\/code><\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">mavenCentral()<\/code><\/div>\n<div class=\"line number22 index21 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">maven {<\/code><\/div>\n<div class=\"line number23 index22 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">url <\/code><code class=\"bash string\">'<a href=\"https:\/\/repository.jboss.org\/nexus\/content\/groups\/public\/\">https:\/\/repository.jboss.org\/nexus\/content\/groups\/public\/<\/a>'<\/code><\/div>\n<div class=\"line number24 index23 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number26 index25 alt1\">&nbsp;<\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash plain\">dependencies {<\/code><\/div>\n<div class=\"line number28 index27 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">compile <\/code><code class=\"bash string\">\"org.kie:kie-api:${droolsVersion}\"<\/code><\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">compile <\/code><code class=\"bash string\">\"org.drools:drools-compiler:${droolsVersion}\"<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">compile <\/code><code class=\"bash string\">\"org.drools:drools-core:${droolsVersion}\"<\/code><\/div>\n<div class=\"line number31 index30 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">compile <\/code><code class=\"bash string\">\"ch.qos.logback:logback-classic:1.1.+\"<\/code><\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">compile <\/code><code class=\"bash string\">\"org.slf4j:slf4j-api:1.7.+\"<\/code>&nbsp;&nbsp;&nbsp;<\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">implementation <\/code><code class=\"bash string\">\"org.jetbrains.kotlin:kotlin-stdlib\"<\/code><\/div>\n<div class=\"line number34 index33 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">implementation <\/code><code class=\"bash string\">\"org.jetbrains.kotlin:kotlin-reflect\"<\/code><\/div>\n<div class=\"line number35 index34 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">testImplementation <\/code><code class=\"bash string\">\"org.jetbrains.kotlin:kotlin-test\"<\/code><\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">testImplementation <\/code><code class=\"bash string\">\"org.jetbrains.kotlin:kotlin-test-junit\"<\/code><\/div>\n<div class=\"line number37 index36 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>In our Gradle script we use:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/superkotlin.com\">Kotlin<\/a>, because Kotlin rocks!<\/li>\n<li>IDEA, because it is my favorite IDE<\/li>\n<li>Kotlin StdLib, reflect and test<\/li>\n<li>Drools<\/li>\n<\/ul>\n<p>And this is how our program will be structured:<\/p>\n<div>\n<div id=\"highlighter_833112\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">fun main(args: Array&lt;String&gt;) {<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">try {<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val kbase = readKnowledgeBase(listOf(<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">File(<\/code><code class=\"bash string\">\"rules\/generic.drl\"<\/code><code class=\"bash plain\">),<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">File(<\/code><code class=\"bash string\">\"rules\/book.drl\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val ksession = kbase.newKieSession()<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">\/\/<\/code> <code class=\"bash plain\">typically we want to consider today but we may decide to schedule<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">\/\/<\/code> <code class=\"bash plain\">emails <\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">the future or we may want to run tests using a different <\/code><code class=\"bash functions\">date<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val dayToConsider = LocalDate.now()<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">loadDataIntoSession(ksession, dayToConsider)<\/code><\/div>\n<div class=\"line number11 index10 alt2\">&nbsp;<\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.fireAllRules()<\/code><\/div>\n<div class=\"line number13 index12 alt2\">&nbsp;<\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">showSending(ksession)<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">} catch (t: Throwable) {<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">t.printStackTrace()<\/code><\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>Pretty simple, pretty neat.<\/p>\n<p>What we do in, details is:<\/p>\n<ul class=\"wp-block-list\">\n<li>We load the rules from file. For now we just load the file <code>rules\/generic.drl<\/code><\/li>\n<li>We setup a new session. Think of the session as the universe as seen by the rules: all data they can access is there<\/li>\n<li>We load our data model into the session<\/li>\n<li>We fire all the rules. They could change stuff in the session<\/li>\n<li>We read the modified data model (a.k.a. the session) to figure out which emails we should send today<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Writing the classes for the data model<\/h2>\n<p>We have previously seen how our data model looks like, let\u2019s now see the code for it.<\/p>\n<p>Given we are using Kotlin it will be pretty concise and obvious.<\/p>\n<div>\n<div id=\"highlighter_535560\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<div class=\"line number20 index19 alt1\">20<\/div>\n<div class=\"line number21 index20 alt2\">21<\/div>\n<div class=\"line number22 index21 alt1\">22<\/div>\n<div class=\"line number23 index22 alt2\">23<\/div>\n<div class=\"line number24 index23 alt1\">24<\/div>\n<div class=\"line number25 index24 alt2\">25<\/div>\n<div class=\"line number26 index25 alt1\">26<\/div>\n<div class=\"line number27 index26 alt2\">27<\/div>\n<div class=\"line number28 index27 alt1\">28<\/div>\n<div class=\"line number29 index28 alt2\">29<\/div>\n<div class=\"line number30 index29 alt1\">30<\/div>\n<div class=\"line number31 index30 alt2\">31<\/div>\n<div class=\"line number32 index31 alt1\">32<\/div>\n<div class=\"line number33 index32 alt2\">33<\/div>\n<div class=\"line number34 index33 alt1\">34<\/div>\n<div class=\"line number35 index34 alt2\">35<\/div>\n<div class=\"line number36 index35 alt1\">36<\/div>\n<div class=\"line number37 index36 alt2\">37<\/div>\n<div class=\"line number38 index37 alt1\">38<\/div>\n<div class=\"line number39 index38 alt2\">39<\/div>\n<div class=\"line number40 index39 alt1\">40<\/div>\n<div class=\"line number41 index40 alt2\">41<\/div>\n<div class=\"line number42 index41 alt1\">42<\/div>\n<div class=\"line number43 index42 alt2\">43<\/div>\n<div class=\"line number44 index43 alt1\">44<\/div>\n<div class=\"line number45 index44 alt2\">45<\/div>\n<div class=\"line number46 index45 alt1\">46<\/div>\n<div class=\"line number47 index46 alt2\">47<\/div>\n<div class=\"line number48 index47 alt1\">48<\/div>\n<div class=\"line number49 index48 alt2\">49<\/div>\n<div class=\"line number50 index49 alt1\">50<\/div>\n<div class=\"line number51 index50 alt2\">51<\/div>\n<div class=\"line number52 index51 alt1\">52<\/div>\n<div class=\"line number53 index52 alt2\">53<\/div>\n<div class=\"line number54 index53 alt1\">54<\/div>\n<div class=\"line number55 index54 alt2\">55<\/div>\n<div class=\"line number56 index55 alt1\">56<\/div>\n<div class=\"line number57 index56 alt2\">57<\/div>\n<div class=\"line number58 index57 alt1\">58<\/div>\n<div class=\"line number59 index58 alt2\">59<\/div>\n<div class=\"line number60 index59 alt1\">60<\/div>\n<div class=\"line number61 index60 alt2\">61<\/div>\n<div class=\"line number62 index61 alt1\">62<\/div>\n<div class=\"line number63 index62 alt2\">63<\/div>\n<div class=\"line number64 index63 alt1\">64<\/div>\n<div class=\"line number65 index64 alt2\">65<\/div>\n<div class=\"line number66 index65 alt1\">66<\/div>\n<div class=\"line number67 index66 alt2\">67<\/div>\n<div class=\"line number68 index67 alt1\">68<\/div>\n<div class=\"line number69 index68 alt2\">69<\/div>\n<div class=\"line number70 index69 alt1\">70<\/div>\n<div class=\"line number71 index70 alt2\">71<\/div>\n<div class=\"line number72 index71 alt1\">72<\/div>\n<div class=\"line number73 index72 alt2\">73<\/div>\n<div class=\"line number74 index73 alt1\">74<\/div>\n<div class=\"line number75 index74 alt2\">75<\/div>\n<div class=\"line number76 index75 alt1\">76<\/div>\n<div class=\"line number77 index76 alt2\">77<\/div>\n<div class=\"line number78 index77 alt1\">78<\/div>\n<div class=\"line number79 index78 alt2\">79<\/div>\n<div class=\"line number80 index79 alt1\">80<\/div>\n<div class=\"line number81 index80 alt2\">81<\/div>\n<div class=\"line number82 index81 alt1\">82<\/div>\n<div class=\"line number83 index82 alt2\">83<\/div>\n<div class=\"line number84 index83 alt1\">84<\/div>\n<div class=\"line number85 index84 alt2\">85<\/div>\n<div class=\"line number86 index85 alt1\">86<\/div>\n<div class=\"line number87 index86 alt2\">87<\/div>\n<div class=\"line number88 index87 alt1\">88<\/div>\n<div class=\"line number89 index88 alt2\">89<\/div>\n<div class=\"line number90 index89 alt1\">90<\/div>\n<div class=\"line number91 index90 alt2\">91<\/div>\n<div class=\"line number92 index91 alt1\">92<\/div>\n<div class=\"line number93 index92 alt2\">93<\/div>\n<div class=\"line number94 index93 alt1\">94<\/div>\n<div class=\"line number95 index94 alt2\">95<\/div>\n<div class=\"line number96 index95 alt1\">96<\/div>\n<div class=\"line number97 index96 alt2\">97<\/div>\n<div class=\"line number98 index97 alt1\">98<\/div>\n<div class=\"line number99 index98 alt2\">99<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">package com.strumenta.funnel<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.DayOfWeek<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.LocalDate<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.util.*<\/code><\/div>\n<div class=\"line number6 index5 alt1\">&nbsp;<\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash plain\">enum class Priority {<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">TRIVIAL,<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">NORMAL,<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">IMPORTANT,<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">VITAL<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number13 index12 alt2\">&nbsp;<\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash plain\">data class Product(val name: String,<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val price: Float)<\/code><\/div>\n<div class=\"line number16 index15 alt1\">&nbsp;<\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash plain\">data class Purchase(val product: Product,<\/code><\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val price: Float,<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val <\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">: LocalDate)<\/code><\/div>\n<div class=\"line number20 index19 alt1\">&nbsp;<\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash plain\">data class Subscriber(val name: String,<\/code><\/div>\n<div class=\"line number22 index21 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val subscriptionDate: LocalDate,<\/code><\/div>\n<div class=\"line number23 index22 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val country: String,<\/code><\/div>\n<div class=\"line number24 index23 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val email: String = <\/code><code class=\"bash string\">\"$name@foo.com\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val tags: List&lt;String&gt; = emptyList(),<\/code><\/div>\n<div class=\"line number26 index25 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val purchases: List&lt;Purchase&gt; = emptyList(),<\/code><\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val emailsReceived: MutableList&lt;EmailSending&gt; = LinkedList()) {<\/code><\/div>\n<div class=\"line number28 index27 alt1\">&nbsp;<\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val actualEmailsReceived<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">get() = emailsReceived.map { it.email }<\/code><\/div>\n<div class=\"line number31 index30 alt2\">&nbsp;<\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun isInSequence(emailSequence: EmailSequence) =<\/code><\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">hasReceived(emailSequence.first)<\/code><\/div>\n<div class=\"line number34 index33 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">&amp;&amp; !hasReceived(emailSequence.last)<\/code><\/div>\n<div class=\"line number35 index34 alt2\">&nbsp;<\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun hasReceived(email: Email) = emailsReceived.any { it.email == email }<\/code><\/div>\n<div class=\"line number37 index36 alt2\">&nbsp;<\/div>\n<div class=\"line number38 index37 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun hasReceivedEmailsInLastDays(nDays: Long, day: LocalDate)<\/code><\/div>\n<div class=\"line number39 index38 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">: Boolean {<\/code><\/div>\n<div class=\"line number40 index39 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash plain\">emailsReceived.any {<\/code><\/div>\n<div class=\"line number41 index40 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">it.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">.isAfter(day.minusDays(nDays))<\/code><\/div>\n<div class=\"line number42 index41 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number43 index42 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number44 index43 alt1\">&nbsp;<\/div>\n<div class=\"line number45 index44 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun isOnHolidays(<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">: LocalDate) : Boolean {<\/code><\/div>\n<div class=\"line number46 index45 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash functions\">date<\/code><code class=\"bash plain\">.dayOfWeek == DayOfWeek.SATURDAY<\/code><\/div>\n<div class=\"line number47 index46 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">|| <\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">.dayOfWeek == DayOfWeek.SUNDAY<\/code><\/div>\n<div class=\"line number48 index47 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number49 index48 alt2\">&nbsp;<\/div>\n<div class=\"line number50 index49 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun emailReceivedWithTag(tag: String) =<\/code><\/div>\n<div class=\"line number51 index50 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">emailsReceived.count { tag <\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">it.email.tags }<\/code><\/div>\n<div class=\"line number52 index51 alt1\">&nbsp;<\/div>\n<div class=\"line number53 index52 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number54 index53 alt1\">&nbsp;<\/div>\n<div class=\"line number55 index54 alt2\"><code class=\"bash plain\">data class Email(val title: String,<\/code><\/div>\n<div class=\"line number56 index55 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val content: String,<\/code><\/div>\n<div class=\"line number57 index56 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val tags: List&lt;String&gt; = emptyList())<\/code><\/div>\n<div class=\"line number58 index57 alt1\">&nbsp;<\/div>\n<div class=\"line number59 index58 alt2\"><code class=\"bash plain\">data class EmailSequence(val title: String,<\/code><\/div>\n<div class=\"line number60 index59 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val emails: List&lt;Email&gt;,<\/code><\/div>\n<div class=\"line number61 index60 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val tags: List&lt;String&gt; = emptyList()) {<\/code><\/div>\n<div class=\"line number62 index61 alt1\">&nbsp;<\/div>\n<div class=\"line number63 index62 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val first = emails.first()<\/code><\/div>\n<div class=\"line number64 index63 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val last = emails.last()<\/code><\/div>\n<div class=\"line number65 index64 alt2\">&nbsp;<\/div>\n<div class=\"line number66 index65 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">init {<\/code><\/div>\n<div class=\"line number67 index66 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">require(emails.isNotEmpty())<\/code><\/div>\n<div class=\"line number68 index67 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number69 index68 alt2\">&nbsp;<\/div>\n<div class=\"line number70 index69 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun next(emailsReceived: List&lt;Email&gt;) =<\/code><\/div>\n<div class=\"line number71 index70 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">emails.first { it !<\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">emailsReceived }<\/code><\/div>\n<div class=\"line number72 index71 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number73 index72 alt2\">&nbsp;<\/div>\n<div class=\"line number74 index73 alt1\"><code class=\"bash plain\">data class EmailSending(val email: Email,<\/code><\/div>\n<div class=\"line number75 index74 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val subscriber: Subscriber,<\/code><\/div>\n<div class=\"line number76 index75 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val <\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">: LocalDate) {<\/code><\/div>\n<div class=\"line number77 index76 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">override fun equals(other: Any?): Boolean {<\/code><\/div>\n<div class=\"line number78 index77 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash keyword\">if<\/code> <code class=\"bash plain\">(other is EmailSending) {<\/code><\/div>\n<div class=\"line number79 index78 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">this.email === other.email &amp;&amp; this.subscriber === other.subscriber &amp;&amp; this.<\/code><code class=\"bash functions\">date<\/code> <code class=\"bash plain\">== other.<\/code><code class=\"bash functions\">date<\/code><\/div>\n<div class=\"line number80 index79 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">} <\/code><code class=\"bash keyword\">else<\/code> <code class=\"bash plain\">{<\/code><\/div>\n<div class=\"line number81 index80 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash functions\">false<\/code><\/div>\n<div class=\"line number82 index81 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number83 index82 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number84 index83 alt1\">&nbsp;<\/div>\n<div class=\"line number85 index84 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">override fun hashCode(): Int {<\/code><\/div>\n<div class=\"line number86 index85 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash plain\">this.email.title.hashCode() * 7 + this.subscriber.name.hashCode() * 3 + this.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">.hashCode()<\/code><\/div>\n<div class=\"line number87 index86 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number88 index87 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number89 index88 alt2\">&nbsp;<\/div>\n<div class=\"line number90 index89 alt1\"><code class=\"bash plain\">data class EmailScheduling @JvmOverloads constructor(val sending: EmailSending,<\/code><\/div>\n<div class=\"line number91 index90 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val priority: Priority,<\/code><\/div>\n<div class=\"line number92 index91 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val timeSensitive: Boolean = <\/code><code class=\"bash functions\">false<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number93 index92 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">var blocked: Boolean = <\/code><code class=\"bash functions\">false<\/code><code class=\"bash plain\">) {<\/code><\/div>\n<div class=\"line number94 index93 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val <\/code><code class=\"bash functions\">id<\/code> <code class=\"bash plain\">= ++nextId<\/code><\/div>\n<div class=\"line number95 index94 alt2\">&nbsp;<\/div>\n<div class=\"line number96 index95 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">companion object {<\/code><\/div>\n<div class=\"line number97 index96 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">private var nextId = 0<\/code><\/div>\n<div class=\"line number98 index97 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number99 index98 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>Nothing surprising here: we have the seven classes we were expecting. We have a few utility methods here and there but nothing that you cannot figure out by yourself.<\/p>\n<h2 class=\"wp-block-heading\">Writing a rule to schedule an email<\/h2>\n<p>It is now time to write our first business rule. This rule will state that, given a sequence and given a person, we will schedule the first email of the sequence to be sent to a person if that person is not already receiving an email from that sequence.<\/p>\n<div>\n<div id=\"highlighter_594869\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">dialect <\/code><code class=\"bash string\">\"java\"<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Start sequence\"<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sequence : EmailSequence ()<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">subscriber : Subscriber ( !isInSequence(sequence) )<\/code><\/div>\n<div class=\"line number6 index5 alt1\">&nbsp;<\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSending $sending = new EmailSending(sequence.getFirst(), subscriber, day);<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailScheduling $scheduling = new EmailScheduling($sending, Priority.NORMAL);<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">insert($scheduling);<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>In the header of the rule we specify the language we are using for writing the clauses. In this tutorial we will consider only Java. There is another possible value:&nbsp;<em>mvel<\/em>. We will not look into that. Also, while in this example we specify the dialect on the rule it can be instead specified once for the whole file. There is even a better option: not specifing the dialect at all, as Java is the default anyway and the usage of mvel is discouraged.<\/p>\n<p>The <code>when<\/code>&nbsp;section determines on which elements our rule will operate. In this case we state that it will operate on an <em>EmailSequence<\/em> and a <em>Subscriber<\/em>. It will not work just on any person but only on a person for which the condition <code>!isInSequence(sequence)<\/code>&nbsp;is satisfied. This condition is based on a call to the method&nbsp;<code>isInsequence<\/code>&nbsp;that we will show below:<\/p>\n<div>\n<div id=\"highlighter_843606\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<div class=\"line number3 index2 alt2\">3<\/div>\n<div class=\"line number4 index3 alt1\">4<\/div>\n<div class=\"line number5 index4 alt2\">5<\/div>\n<div class=\"line number6 index5 alt1\">6<\/div>\n<div class=\"line number7 index6 alt2\">7<\/div>\n<div class=\"line number8 index7 alt1\">8<\/div>\n<div class=\"line number9 index8 alt2\">9<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">data class Subscriber(...) {<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun isInSequence(emailSequence: EmailSequence) = <\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">hasReceived(emailSequence.first) &amp;&amp; <\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!hasReceived(emailSequence.last)<\/code><\/div>\n<div class=\"line number6 index5 alt1\">&nbsp;<\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun hasReceived(email: Email) = <\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">emailReceived.any { it.email == email }<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>Let\u2019s now look at the <code>then<\/code>&nbsp;section of our rule. In such section we specify what happens when the rule is fired. The rule will be fired when elements satisfying the <code>when<\/code>&nbsp;section can be found.<\/p>\n<p>In this case we will create an <code>EmailScheduling<\/code> and add it to the session. In particular we want to send to the considered person the first email of the sequence, on the day considered. We also specify the priority of this email (<code>NORMAL<\/code> in this case). This is necessary to decide which email effectively to send when we have more than one. Indeed we will have another rule looking at these values to decide which emails to prioritize (hint: it will be the email with the highest priority).<\/p>\n<p>In general you may want to typically add things into the session in the <code>then<\/code>clause. Alternatively you may want to modify objects which are part of the session. You could also call methods on objects which have side-effects. While the recommended approach is to limit yourself to manipulate the session you may want to add side effects for logging, for example. This is especially useful when learning Drools and trying to wrap your head around your first rules.<\/p>\n<h2 class=\"wp-block-heading\">Writing a rule to block an email from being sent<\/h2>\n<p>We will see that we have two possible types of rules: rules to schedule new emails and rules to prevent scheduled emails to be sent. We have seen before how to write a rule to send an email and we will now see how to write an email to prevent an email from being sent.<\/p>\n<p>In this rule we want to check if an email is scheduled to be sent to a person who has received already emails in the last three days. If this is the case we want to block that email from being sent.<\/p>\n<div>\n<div id=\"highlighter_142982\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<div class=\"line number3 index2 alt2\">3<\/div>\n<div class=\"line number4 index3 alt1\">4<\/div>\n<div class=\"line number5 index4 alt2\">5<\/div>\n<div class=\"line number6 index5 alt1\">6<\/div>\n<div class=\"line number7 index6 alt2\">7<\/div>\n<div class=\"line number8 index7 alt1\">8<\/div>\n<div class=\"line number9 index8 alt2\">9<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Prevent overloading\"<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling(<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber.hasReceivedEmailsInLastDays(3, day),<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked )<\/code><\/div>\n<div class=\"line number6 index5 alt1\">&nbsp;<\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>In the <code>when<\/code>&nbsp;section we specify that this rule will operate on an <code>EmailScheduling<\/code>. So, every time another rule will add an <code>EmailScheduling<\/code>&nbsp;this rule could be triggered to decide if we have to block it from being sent.<\/p>\n<p>This rule will apply to all scheduling which are directed to subscribers who have received emails in the last 3 days. In addition to that we will check if the <code>EmailScheduling<\/code>&nbsp;was not already blocked. If that is the case we will not need to apply this rule.<\/p>\n<p>We use the <code>setBlocked<\/code> method of the scheduling object to modify an element which is part of the session.<\/p>\n<p>At this point we have seen the pattern we will use:<\/p>\n<ul class=\"wp-block-list\">\n<li>We will create <code>EmailScheduling<\/code> when we think it makes sense to send an email to the user<\/li>\n<li>We will check if we have reasons to block those emails. If that is the case we will set the <code>blocked<\/code>&nbsp;flag to true, effectively removing the <code>EmailScheduling<\/code><\/li>\n<\/ul>\n<p>Using a flag to mark elements to remove\/invalidate\/block is a common pattern used in business rules. It can sound a bit unfamiliar at the beginning but it is actually quite useful. You may think that you could just&nbsp;<em>delete<\/em>&nbsp;elements from the session, however doing so it becomes easy to create infinite loops in which you create new elements with some rules, remove them with others and keep recreating them again. The block-flag pattern avoids all of that.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h2 class=\"wp-block-heading\">The session<\/h2>\n<p>Rules operate on data which is part of the session. Data is typically inserted into the session during the initialization phase. Later we could have rules inserting more data into the session, potentially triggering other rules.<\/p>\n<p>This is how we could populate the session with some example data:<\/p>\n<div>\n<div id=\"highlighter_589174\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<div class=\"line number20 index19 alt1\">20<\/div>\n<div class=\"line number21 index20 alt2\">21<\/div>\n<div class=\"line number22 index21 alt1\">22<\/div>\n<div class=\"line number23 index22 alt2\">23<\/div>\n<div class=\"line number24 index23 alt1\">24<\/div>\n<div class=\"line number25 index24 alt2\">25<\/div>\n<div class=\"line number26 index25 alt1\">26<\/div>\n<div class=\"line number27 index26 alt2\">27<\/div>\n<div class=\"line number28 index27 alt1\">28<\/div>\n<div class=\"line number29 index28 alt2\">29<\/div>\n<div class=\"line number30 index29 alt1\">30<\/div>\n<div class=\"line number31 index30 alt2\">31<\/div>\n<div class=\"line number32 index31 alt1\">32<\/div>\n<div class=\"line number33 index32 alt2\">33<\/div>\n<div class=\"line number34 index33 alt1\">34<\/div>\n<div class=\"line number35 index34 alt2\">35<\/div>\n<div class=\"line number36 index35 alt1\">36<\/div>\n<div class=\"line number37 index36 alt2\">37<\/div>\n<div class=\"line number38 index37 alt1\">38<\/div>\n<div class=\"line number39 index38 alt2\">39<\/div>\n<div class=\"line number40 index39 alt1\">40<\/div>\n<div class=\"line number41 index40 alt2\">41<\/div>\n<div class=\"line number42 index41 alt1\">42<\/div>\n<div class=\"line number43 index42 alt2\">43<\/div>\n<div class=\"line number44 index43 alt1\">44<\/div>\n<div class=\"line number45 index44 alt2\">45<\/div>\n<div class=\"line number46 index45 alt1\">46<\/div>\n<div class=\"line number47 index46 alt2\">47<\/div>\n<div class=\"line number48 index47 alt1\">48<\/div>\n<div class=\"line number49 index48 alt2\">49<\/div>\n<div class=\"line number50 index49 alt1\">50<\/div>\n<div class=\"line number51 index50 alt2\">51<\/div>\n<div class=\"line number52 index51 alt1\">52<\/div>\n<div class=\"line number53 index52 alt2\">53<\/div>\n<div class=\"line number54 index53 alt1\">54<\/div>\n<div class=\"line number55 index54 alt2\">55<\/div>\n<div class=\"line number56 index55 alt1\">56<\/div>\n<div class=\"line number57 index56 alt2\">57<\/div>\n<div class=\"line number58 index57 alt1\">58<\/div>\n<div class=\"line number59 index58 alt2\">59<\/div>\n<div class=\"line number60 index59 alt1\">60<\/div>\n<div class=\"line number61 index60 alt2\">61<\/div>\n<div class=\"line number62 index61 alt1\">62<\/div>\n<div class=\"line number63 index62 alt2\">63<\/div>\n<div class=\"line number64 index63 alt1\">64<\/div>\n<div class=\"line number65 index64 alt2\">65<\/div>\n<div class=\"line number66 index65 alt1\">66<\/div>\n<div class=\"line number67 index66 alt2\">67<\/div>\n<div class=\"line number68 index67 alt1\">68<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">fun loadDataIntoSession(ksession: KieSession,<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">dayToConsider: LocalDate) {<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val products = listOf(<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"My book\"<\/code><code class=\"bash plain\">, 20.0f),<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"Video course\"<\/code><code class=\"bash plain\">, 100.0f),<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"Consulting package\"<\/code><code class=\"bash plain\">, 500.0f)<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val persons = listOf(<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Subscriber(<\/code><code class=\"bash string\">\"Mario\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.JANUARY, 1),<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Italy\"<\/code><code class=\"bash plain\">),<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Subscriber(<\/code><code class=\"bash string\">\"Amelie\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.FEBRUARY, 1),<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"France\"<\/code><code class=\"bash plain\">),<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Subscriber(<\/code><code class=\"bash string\">\"Bernd\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.APRIL, 18),<\/code><\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Germany\"<\/code><code class=\"bash plain\">),<\/code><\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Subscriber(<\/code><code class=\"bash string\">\"Eric\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2018, Month.OCTOBER, 1),<\/code><\/div>\n<div class=\"line number20 index19 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"USA\"<\/code><code class=\"bash plain\">),<\/code><\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Subscriber(<\/code><code class=\"bash string\">\"Albert\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number22 index21 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2016, Month.OCTOBER, 12),<\/code><\/div>\n<div class=\"line number23 index22 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"USA\"<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number24 index23 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val sequences = listOf(<\/code><\/div>\n<div class=\"line number26 index25 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSequence(<\/code><code class=\"bash string\">\"Present book\"<\/code><code class=\"bash plain\">, listOf(<\/code><\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 1\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number28 index27 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 2\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number31 index30 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 3\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number34 index33 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSequence(<\/code><code class=\"bash string\">\"Present course\"<\/code><code class=\"bash plain\">, listOf(<\/code><\/div>\n<div class=\"line number35 index34 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present course 1\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the course...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"course_explanation\"<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number37 index36 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present course 2\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the course...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number38 index37 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"course_explanation\"<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number39 index38 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present course 3\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the course...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number40 index39 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"course_explanation\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number41 index40 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number42 index41 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number43 index42 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Question to user\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number44 index43 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number45 index44 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Interesting topic A\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number46 index45 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number47 index46 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Interesting topic B\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number48 index47 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number49 index48 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest book\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number50 index49 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I wrote a book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number51 index50 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number52 index51 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest course\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number53 index52 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I wrote a course...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number54 index53 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"course_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number55 index54 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest consulting\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number56 index55 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I offer consulting...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number57 index56 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"consulting_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number58 index57 alt1\">&nbsp;<\/div>\n<div class=\"line number59 index58 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.setGlobal(<\/code><code class=\"bash string\">\"day\"<\/code><code class=\"bash plain\">, dayToConsider)<\/code><\/div>\n<div class=\"line number60 index59 alt1\">&nbsp;<\/div>\n<div class=\"line number61 index60 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(products)<\/code><\/div>\n<div class=\"line number62 index61 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">persons.forEach {<\/code><\/div>\n<div class=\"line number63 index62 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(it)<\/code><\/div>\n<div class=\"line number64 index63 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number65 index64 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sequences.forEach {<\/code><\/div>\n<div class=\"line number66 index65 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(it)<\/code><\/div>\n<div class=\"line number67 index66 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number68 index67 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>Of course in a real application we would access some database or some form of storage to retrieve the data to be used to populate the session.<\/p>\n<h2 class=\"wp-block-heading\">Global objects<\/h2>\n<p>In rules we will not only access elements which are part of the session but also global objects.<br \/>Global objects are inserted in the session using <code>setGlobal<\/code>. We have seen an example in <code>loadDataIntoSession<\/code>:<\/p>\n<div>\n<div id=\"highlighter_533099\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<div class=\"line number3 index2 alt2\">3<\/div>\n<div class=\"line number4 index3 alt1\">4<\/div>\n<div class=\"line number5 index4 alt2\">5<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">fun loadDataIntoSession(ksession: StatefulKnowledgeSession, dayToConsider: LocalDate) : EmailScheduler {<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">...<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.setGlobal(<\/code><code class=\"bash string\">\"day\"<\/code><code class=\"bash plain\">, dayToConsider)<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">...<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>In the rules we declare the globals:<\/p>\n<div>\n<div id=\"highlighter_48445\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">package com.strumenta.funnellang<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.Email;<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailSequence;<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailScheduling<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailScheduler;<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.Person<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.LocalDate;<\/code><\/div>\n<div class=\"line number9 index8 alt2\">&nbsp;<\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash plain\">global LocalDate day;<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>At this point we can refer to these globals in all rules. In our example we use <code>day<\/code>&nbsp;value to know which day we are considering for the scheduling. Typically it would be tomorrow, as we would like to do the scheduling one day in advance. However for testing reasons we could use any day we want. Or we may want to use days in the future for simulation purposes.<\/p>\n<p>Global should not be abused. Personally I like to use them to specify configuration parameters. Others prefer to insert this data into the session and this is the recommended approach. The reason why I use globals (carefully and rarely) is because I like to distinguish between the data I am working on (stored in the session) and the configuration (for that I use globals).<\/p>\n<h2 class=\"wp-block-heading\">Writing the generic rules<\/h2>\n<p>Let\u2019s now see the whole set of generic rules that we have written. By generic rules we mean rules that could be applied to all email schedulings we want to do. To complement these rules we may have others for specific products or topics we are promoting.<\/p>\n<div>\n<div id=\"highlighter_562242\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">001<\/div>\n<div class=\"line number2 index1 alt1\">002<\/div>\n<div class=\"line number3 index2 alt2\">003<\/div>\n<div class=\"line number4 index3 alt1\">004<\/div>\n<div class=\"line number5 index4 alt2\">005<\/div>\n<div class=\"line number6 index5 alt1\">006<\/div>\n<div class=\"line number7 index6 alt2\">007<\/div>\n<div class=\"line number8 index7 alt1\">008<\/div>\n<div class=\"line number9 index8 alt2\">009<\/div>\n<div class=\"line number10 index9 alt1\">010<\/div>\n<div class=\"line number11 index10 alt2\">011<\/div>\n<div class=\"line number12 index11 alt1\">012<\/div>\n<div class=\"line number13 index12 alt2\">013<\/div>\n<div class=\"line number14 index13 alt1\">014<\/div>\n<div class=\"line number15 index14 alt2\">015<\/div>\n<div class=\"line number16 index15 alt1\">016<\/div>\n<div class=\"line number17 index16 alt2\">017<\/div>\n<div class=\"line number18 index17 alt1\">018<\/div>\n<div class=\"line number19 index18 alt2\">019<\/div>\n<div class=\"line number20 index19 alt1\">020<\/div>\n<div class=\"line number21 index20 alt2\">021<\/div>\n<div class=\"line number22 index21 alt1\">022<\/div>\n<div class=\"line number23 index22 alt2\">023<\/div>\n<div class=\"line number24 index23 alt1\">024<\/div>\n<div class=\"line number25 index24 alt2\">025<\/div>\n<div class=\"line number26 index25 alt1\">026<\/div>\n<div class=\"line number27 index26 alt2\">027<\/div>\n<div class=\"line number28 index27 alt1\">028<\/div>\n<div class=\"line number29 index28 alt2\">029<\/div>\n<div class=\"line number30 index29 alt1\">030<\/div>\n<div class=\"line number31 index30 alt2\">031<\/div>\n<div class=\"line number32 index31 alt1\">032<\/div>\n<div class=\"line number33 index32 alt2\">033<\/div>\n<div class=\"line number34 index33 alt1\">034<\/div>\n<div class=\"line number35 index34 alt2\">035<\/div>\n<div class=\"line number36 index35 alt1\">036<\/div>\n<div class=\"line number37 index36 alt2\">037<\/div>\n<div class=\"line number38 index37 alt1\">038<\/div>\n<div class=\"line number39 index38 alt2\">039<\/div>\n<div class=\"line number40 index39 alt1\">040<\/div>\n<div class=\"line number41 index40 alt2\">041<\/div>\n<div class=\"line number42 index41 alt1\">042<\/div>\n<div class=\"line number43 index42 alt2\">043<\/div>\n<div class=\"line number44 index43 alt1\">044<\/div>\n<div class=\"line number45 index44 alt2\">045<\/div>\n<div class=\"line number46 index45 alt1\">046<\/div>\n<div class=\"line number47 index46 alt2\">047<\/div>\n<div class=\"line number48 index47 alt1\">048<\/div>\n<div class=\"line number49 index48 alt2\">049<\/div>\n<div class=\"line number50 index49 alt1\">050<\/div>\n<div class=\"line number51 index50 alt2\">051<\/div>\n<div class=\"line number52 index51 alt1\">052<\/div>\n<div class=\"line number53 index52 alt2\">053<\/div>\n<div class=\"line number54 index53 alt1\">054<\/div>\n<div class=\"line number55 index54 alt2\">055<\/div>\n<div class=\"line number56 index55 alt1\">056<\/div>\n<div class=\"line number57 index56 alt2\">057<\/div>\n<div class=\"line number58 index57 alt1\">058<\/div>\n<div class=\"line number59 index58 alt2\">059<\/div>\n<div class=\"line number60 index59 alt1\">060<\/div>\n<div class=\"line number61 index60 alt2\">061<\/div>\n<div class=\"line number62 index61 alt1\">062<\/div>\n<div class=\"line number63 index62 alt2\">063<\/div>\n<div class=\"line number64 index63 alt1\">064<\/div>\n<div class=\"line number65 index64 alt2\">065<\/div>\n<div class=\"line number66 index65 alt1\">066<\/div>\n<div class=\"line number67 index66 alt2\">067<\/div>\n<div class=\"line number68 index67 alt1\">068<\/div>\n<div class=\"line number69 index68 alt2\">069<\/div>\n<div class=\"line number70 index69 alt1\">070<\/div>\n<div class=\"line number71 index70 alt2\">071<\/div>\n<div class=\"line number72 index71 alt1\">072<\/div>\n<div class=\"line number73 index72 alt2\">073<\/div>\n<div class=\"line number74 index73 alt1\">074<\/div>\n<div class=\"line number75 index74 alt2\">075<\/div>\n<div class=\"line number76 index75 alt1\">076<\/div>\n<div class=\"line number77 index76 alt2\">077<\/div>\n<div class=\"line number78 index77 alt1\">078<\/div>\n<div class=\"line number79 index78 alt2\">079<\/div>\n<div class=\"line number80 index79 alt1\">080<\/div>\n<div class=\"line number81 index80 alt2\">081<\/div>\n<div class=\"line number82 index81 alt1\">082<\/div>\n<div class=\"line number83 index82 alt2\">083<\/div>\n<div class=\"line number84 index83 alt1\">084<\/div>\n<div class=\"line number85 index84 alt2\">085<\/div>\n<div class=\"line number86 index85 alt1\">086<\/div>\n<div class=\"line number87 index86 alt2\">087<\/div>\n<div class=\"line number88 index87 alt1\">088<\/div>\n<div class=\"line number89 index88 alt2\">089<\/div>\n<div class=\"line number90 index89 alt1\">090<\/div>\n<div class=\"line number91 index90 alt2\">091<\/div>\n<div class=\"line number92 index91 alt1\">092<\/div>\n<div class=\"line number93 index92 alt2\">093<\/div>\n<div class=\"line number94 index93 alt1\">094<\/div>\n<div class=\"line number95 index94 alt2\">095<\/div>\n<div class=\"line number96 index95 alt1\">096<\/div>\n<div class=\"line number97 index96 alt2\">097<\/div>\n<div class=\"line number98 index97 alt1\">098<\/div>\n<div class=\"line number99 index98 alt2\">099<\/div>\n<div class=\"line number100 index99 alt1\">100<\/div>\n<div class=\"line number101 index100 alt2\">101<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">package com.strumenta.funnellang<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.Email;<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailSequence;<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailScheduling<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailSending;<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.Subscriber<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.LocalDate;<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.Priority<\/code><\/div>\n<div class=\"line number10 index9 alt1\">&nbsp;<\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash plain\">global LocalDate day;<\/code><\/div>\n<div class=\"line number12 index11 alt1\">&nbsp;<\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Continue sequence\"<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sequence : EmailSequence ()<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">subscriber : Subscriber ( isInSequence(sequence) )<\/code><\/div>\n<div class=\"line number17 index16 alt2\">&nbsp;<\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSending $sending = new EmailSending(sequence.next(subscriber.getActualEmailsReceived()), subscriber, day);<\/code><\/div>\n<div class=\"line number20 index19 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailScheduling $scheduling = new EmailScheduling($sending, Priority.IMPORTANT, <\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">insert($scheduling);<\/code><\/div>\n<div class=\"line number22 index21 alt1\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number23 index22 alt2\">&nbsp;<\/div>\n<div class=\"line number24 index23 alt1\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Start sequence\"<\/code><\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number26 index25 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sequence : EmailSequence ()<\/code><\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">subscriber : Subscriber ( !isInSequence(sequence) )<\/code><\/div>\n<div class=\"line number28 index27 alt1\">&nbsp;<\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSending $sending = new EmailSending(sequence.getFirst(), subscriber, day);<\/code><\/div>\n<div class=\"line number31 index30 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailScheduling $scheduling = new EmailScheduling($sending, Priority.NORMAL);<\/code><\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">insert($scheduling);<\/code><\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number34 index33 alt1\">&nbsp;<\/div>\n<div class=\"line number35 index34 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Prevent overloading\"<\/code><\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number37 index36 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling(<\/code><\/div>\n<div class=\"line number38 index37 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber.hasReceivedEmailsInLastDays(3, day),<\/code><\/div>\n<div class=\"line number39 index38 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked )<\/code><\/div>\n<div class=\"line number40 index39 alt1\">&nbsp;<\/div>\n<div class=\"line number41 index40 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number42 index41 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number43 index42 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number44 index43 alt1\">&nbsp;<\/div>\n<div class=\"line number45 index44 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Block on holidays\"<\/code><\/div>\n<div class=\"line number46 index45 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number47 index46 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling( sending.subscriber.isOnHolidays(scheduling.sending.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">), !blocked )<\/code><\/div>\n<div class=\"line number48 index47 alt1\">&nbsp;<\/div>\n<div class=\"line number49 index48 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number50 index49 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number51 index50 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number52 index51 alt1\">&nbsp;<\/div>\n<div class=\"line number53 index52 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Precedence to time sensitive emails\"<\/code><\/div>\n<div class=\"line number54 index53 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number55 index54 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling1 : EmailScheduling( timeSensitive == <\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">, !blocked )<\/code><\/div>\n<div class=\"line number56 index55 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling2 : EmailScheduling( this != scheduling1,<\/code><\/div>\n<div class=\"line number57 index56 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked,<\/code><\/div>\n<div class=\"line number58 index57 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber == scheduling1.sending.subscriber,<\/code><\/div>\n<div class=\"line number59 index58 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.<\/code><code class=\"bash functions\">date<\/code> <code class=\"bash plain\">== scheduling1.sending.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number60 index59 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">timeSensitive == <\/code><code class=\"bash functions\">false<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number61 index60 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number62 index61 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling2.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number63 index62 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number64 index63 alt1\">&nbsp;<\/div>\n<div class=\"line number65 index64 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Precedence to higher priority emails\"<\/code><\/div>\n<div class=\"line number66 index65 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number67 index66 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling1 : EmailScheduling( !blocked )<\/code><\/div>\n<div class=\"line number68 index67 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling2 : EmailScheduling( this != scheduling1,<\/code><\/div>\n<div class=\"line number69 index68 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked,<\/code><\/div>\n<div class=\"line number70 index69 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber == scheduling1.sending.subscriber,<\/code><\/div>\n<div class=\"line number71 index70 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.<\/code><code class=\"bash functions\">date<\/code> <code class=\"bash plain\">== scheduling1.sending.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number72 index71 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">timeSensitive == scheduling1.timeSensitive,<\/code><\/div>\n<div class=\"line number73 index72 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">priority &lt; scheduling1.priority)<\/code><\/div>\n<div class=\"line number74 index73 alt1\">&nbsp;<\/div>\n<div class=\"line number75 index74 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number76 index75 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling2.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number77 index76 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number78 index77 alt1\">&nbsp;<\/div>\n<div class=\"line number79 index78 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Limit to one email per day\"<\/code><\/div>\n<div class=\"line number80 index79 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number81 index80 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling1 : EmailScheduling( blocked == <\/code><code class=\"bash functions\">false<\/code> <code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number82 index81 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling2 : EmailScheduling( this != scheduling1,<\/code><\/div>\n<div class=\"line number83 index82 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">blocked == <\/code><code class=\"bash functions\">false<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number84 index83 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber == scheduling1.sending.subscriber,<\/code><\/div>\n<div class=\"line number85 index84 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.<\/code><code class=\"bash functions\">date<\/code> <code class=\"bash plain\">== scheduling1.sending.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number86 index85 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">timeSensitive == scheduling1.timeSensitive,<\/code><\/div>\n<div class=\"line number87 index86 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">priority == scheduling1.priority,<\/code><\/div>\n<div class=\"line number88 index87 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash functions\">id<\/code> <code class=\"bash plain\">&gt; scheduling1.<\/code><code class=\"bash functions\">id<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number89 index88 alt2\">&nbsp;<\/div>\n<div class=\"line number90 index89 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number91 index90 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling2.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number92 index91 alt1\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number93 index92 alt2\">&nbsp;<\/div>\n<div class=\"line number94 index93 alt1\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Never resend same email\"<\/code><\/div>\n<div class=\"line number95 index94 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number96 index95 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling( !blocked )<\/code><\/div>\n<div class=\"line number97 index96 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">subscriber : Subscriber( this == scheduling.sending.subscriber,<\/code><\/div>\n<div class=\"line number98 index97 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">hasReceived(scheduling.sending.email) )<\/code><\/div>\n<div class=\"line number99 index98 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number100 index99 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number101 index100 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>Let\u2019s examine all these rules, one by one:<\/p>\n<ul class=\"wp-block-list\">\n<li><em>Continue sequence: <\/em>if someone started receiving an email sequence and he did not receive the last email yet, then he should get the next email in the sequence<\/li>\n<li><em>Start sequence:&nbsp;<\/em>if someone did not yet receive the first email of a sequence he should. Note that technically speaking this rule alone would cause everyone who has finished a sequence to immediately restart it. This does not happen because of the&nbsp;<em>Never resend same email<\/em> rule. However you could decide to rewrite this rule to explicitly forbidding someone who has already received a certain sequence to be re-inserted in it.<\/li>\n<li><em>Prevent overloading:&nbsp;<\/em>if someone has received an email in the last three days then we should block any email scheduling directed to that person<\/li>\n<li><em>Block on holidays:&nbsp;<\/em>if someone is on holidays we should not send emails to them<\/li>\n<li><em>Precedence to time sensitive emails:&nbsp;<\/em>given a pair of email schedulings directed to the same person on the same date, if only one of the two is time sensitive we should block the other<\/li>\n<li><em>Precedence to higher priority emails:&nbsp;<\/em>given a pair of email schedulings directed to the same person on the same date being both time sensitive or both not time sensitive, we should block the one with lower importance<\/li>\n<li><em>Limit to one email per day:&nbsp;<\/em>we should not schedule to send more than one email per day to the same person. If this happens we have to pick one somehow. We use the internal ID to discriminate between the two<\/li>\n<li><em>Never resend same email:&nbsp;<\/em>if someone has already received a certain email he should not receive it again in the future<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Writing the rules specific to the book emails<\/h2>\n<p>Our marketing experts may want to write specific rules for specific products or topics. Let\u2019s assume they want to create a set of emails to promote and sell a book. We could write these rules in a separate file, perhaps maintained by the marketing expert in charge of selling that book.<\/p>\n<p>To write rules regarding a specific topic we will take advantage of tags, a mechanism that will give us a certain amount of flexibility. Let\u2019s see the rules we can write:<\/p>\n<div>\n<div id=\"highlighter_189200\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<div class=\"line number20 index19 alt1\">20<\/div>\n<div class=\"line number21 index20 alt2\">21<\/div>\n<div class=\"line number22 index21 alt1\">22<\/div>\n<div class=\"line number23 index22 alt2\">23<\/div>\n<div class=\"line number24 index23 alt1\">24<\/div>\n<div class=\"line number25 index24 alt2\">25<\/div>\n<div class=\"line number26 index25 alt1\">26<\/div>\n<div class=\"line number27 index26 alt2\">27<\/div>\n<div class=\"line number28 index27 alt1\">28<\/div>\n<div class=\"line number29 index28 alt2\">29<\/div>\n<div class=\"line number30 index29 alt1\">30<\/div>\n<div class=\"line number31 index30 alt2\">31<\/div>\n<div class=\"line number32 index31 alt1\">32<\/div>\n<div class=\"line number33 index32 alt2\">33<\/div>\n<div class=\"line number34 index33 alt1\">34<\/div>\n<div class=\"line number35 index34 alt2\">35<\/div>\n<div class=\"line number36 index35 alt1\">36<\/div>\n<div class=\"line number37 index36 alt2\">37<\/div>\n<div class=\"line number38 index37 alt1\">38<\/div>\n<div class=\"line number39 index38 alt2\">39<\/div>\n<div class=\"line number40 index39 alt1\">40<\/div>\n<div class=\"line number41 index40 alt2\">41<\/div>\n<div class=\"line number42 index41 alt1\">42<\/div>\n<div class=\"line number43 index42 alt2\">43<\/div>\n<div class=\"line number44 index43 alt1\">44<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">package com.strumenta.funnellang<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.Subscriber;<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">com.strumenta.funnel.EmailScheduling;<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.DayOfWeek;<\/code><\/div>\n<div class=\"line number6 index5 alt1\">&nbsp;<\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Send book offer only after at least 3 book presentation emails\"<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">subscriber : Subscriber (<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">emailReceivedWithTag(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">) &lt; 3<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling(<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked,<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber == subscriber,<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.email.tags contains <\/code><code class=\"bash string\">\"book_offer\"<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number20 index19 alt1\">&nbsp;<\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Block book offers on monday\"<\/code><\/div>\n<div class=\"line number22 index21 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number23 index22 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling(<\/code><\/div>\n<div class=\"line number24 index23 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked,<\/code><\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.<\/code><code class=\"bash functions\">date<\/code><code class=\"bash plain\">.dayOfWeek == DayOfWeek.MONDAY,<\/code><\/div>\n<div class=\"line number26 index25 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.email.tags contains <\/code><code class=\"bash string\">\"book_offer\"<\/code><\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number28 index27 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash plain\">end<\/code><\/div>\n<div class=\"line number31 index30 alt2\">&nbsp;<\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash plain\">rule <\/code><code class=\"bash string\">\"Block book offers for people who bought\"<\/code><\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">when<\/code><\/div>\n<div class=\"line number34 index33 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">subscriber : Subscriber (<\/code><\/div>\n<div class=\"line number35 index34 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags contains <\/code><code class=\"bash string\">\"book_bought\"<\/code><\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number37 index36 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling : EmailScheduling(<\/code><\/div>\n<div class=\"line number38 index37 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">!blocked,<\/code><\/div>\n<div class=\"line number39 index38 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.subscriber == subscriber,<\/code><\/div>\n<div class=\"line number40 index39 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sending.email.tags contains <\/code><code class=\"bash string\">\"book_offer\"<\/code><\/div>\n<div class=\"line number41 index40 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number42 index41 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">then<\/code><\/div>\n<div class=\"line number43 index42 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">scheduling.setBlocked(<\/code><code class=\"bash functions\">true<\/code><code class=\"bash plain\">);<\/code><\/div>\n<div class=\"line number44 index43 alt1\"><code class=\"bash plain\">end<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>Let\u2019s examine our rules:<\/p>\n<ul class=\"wp-block-list\">\n<li><em>Send book offer only after at least 3 book presentation emails:&nbsp;<\/em>we want to block any email selling the book if the subscriber did not receive at least three emails explaining the content of the book<\/li>\n<li><em>Block book offers on monday:&nbsp;<\/em>we want to block book offers to be sent on monday, for example because we have seen that subscribers are less inclined to buy on that day of the week<\/li>\n<li><em>Block book offers for people who bought:&nbsp;<\/em>we do not want to propose a deal on the book to subscribers who already bought it<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\">Testing the business rules<\/h2>\n<p>There are different types of tests we may want to write to verify that our rules behave as expected. On one side of the spectrum we may want to have tests that verify complex scenarios and check for unexpected interactions between rules. These tests will run considering complex data sets and the whole set of business rules. On the other side of the spectrum we may want to write simple unit tests to verify single rules. We will see an example of these unit tests, but most of what we will see could be adapted to test the whole set of rules instead of single rules.<\/p>\n<p>What do we want to do in our unit tests?<\/p>\n<ol class=\"wp-block-list\">\n<li>We setup the knowledge base<\/li>\n<li>We want to load some data into the session<\/li>\n<li>We want to run the rule business engine, enabling&nbsp;just the one business rule we want to test<\/li>\n<li>We want to verify that the resulting email schedulings are the one expected<\/li>\n<\/ol>\n<p>To satisfy point 1 we load all the files containing our rules and we verify there are no issues.<\/p>\n<div>\n<div id=\"highlighter_684585\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">private fun prepareKnowledgeBase(files: List&lt;File&gt;): InternalKnowledgeBase {<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder()<\/code><\/div>\n<div class=\"line number3 index2 alt2\">&nbsp;<\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">files.forEach { kbuilder.add(ResourceFactory.newFileResource(it), ResourceType.DRL) }<\/code><\/div>\n<div class=\"line number5 index4 alt2\">&nbsp;<\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val errors = kbuilder.errors<\/code><\/div>\n<div class=\"line number7 index6 alt2\">&nbsp;<\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">if<\/code> <code class=\"bash plain\">(errors.size &gt; 0) {<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">for<\/code> <code class=\"bash plain\">(error <\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">errors) {<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">System.err.println(error)<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">throw IllegalArgumentException(<\/code><code class=\"bash string\">\"Could not parse knowledge.\"<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number14 index13 alt1\">&nbsp;<\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val kbase = KnowledgeBaseFactory.newKnowledgeBase()<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">kbase.addPackages(kbuilder.knowledgePackages)<\/code><\/div>\n<div class=\"line number17 index16 alt2\">&nbsp;<\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash plain\">kbase<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>How do we load data into the session? We do that by loading some default data and then giving the possibility to change this data a little bit in each test. In the following piece of code you will see that we can pass a function as the&nbsp;<em>dataTransformer<\/em> parameter. Such function can operate on the data before we load them into the session. This is our hook to tweak the data in each test.<\/p>\n<div>\n<div id=\"highlighter_350486\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<div class=\"line number20 index19 alt1\">20<\/div>\n<div class=\"line number21 index20 alt2\">21<\/div>\n<div class=\"line number22 index21 alt1\">22<\/div>\n<div class=\"line number23 index22 alt2\">23<\/div>\n<div class=\"line number24 index23 alt1\">24<\/div>\n<div class=\"line number25 index24 alt2\">25<\/div>\n<div class=\"line number26 index25 alt1\">26<\/div>\n<div class=\"line number27 index26 alt2\">27<\/div>\n<div class=\"line number28 index27 alt1\">28<\/div>\n<div class=\"line number29 index28 alt2\">29<\/div>\n<div class=\"line number30 index29 alt1\">30<\/div>\n<div class=\"line number31 index30 alt2\">31<\/div>\n<div class=\"line number32 index31 alt1\">32<\/div>\n<div class=\"line number33 index32 alt2\">33<\/div>\n<div class=\"line number34 index33 alt1\">34<\/div>\n<div class=\"line number35 index34 alt2\">35<\/div>\n<div class=\"line number36 index35 alt1\">36<\/div>\n<div class=\"line number37 index36 alt2\">37<\/div>\n<div class=\"line number38 index37 alt1\">38<\/div>\n<div class=\"line number39 index38 alt2\">39<\/div>\n<div class=\"line number40 index39 alt1\">40<\/div>\n<div class=\"line number41 index40 alt2\">41<\/div>\n<div class=\"line number42 index41 alt1\">42<\/div>\n<div class=\"line number43 index42 alt2\">43<\/div>\n<div class=\"line number44 index43 alt1\">44<\/div>\n<div class=\"line number45 index44 alt2\">45<\/div>\n<div class=\"line number46 index45 alt1\">46<\/div>\n<div class=\"line number47 index46 alt2\">47<\/div>\n<div class=\"line number48 index47 alt1\">48<\/div>\n<div class=\"line number49 index48 alt2\">49<\/div>\n<div class=\"line number50 index49 alt1\">50<\/div>\n<div class=\"line number51 index50 alt2\">51<\/div>\n<div class=\"line number52 index51 alt1\">52<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">fun loadDataIntoSession(ksession: KieSession,<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">dayToConsider: LocalDate, dataTransformer: ((Subscriber, Email) -&gt; Unit)? = null) {<\/code><\/div>\n<div class=\"line number3 index2 alt2\">&nbsp;<\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val amelie = Subscriber(<\/code><code class=\"bash string\">\"Amelie\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.FEBRUARY, 1),<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"France\"<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val bookSeqEmail1 = Email(<\/code><code class=\"bash string\">\"Present book 1\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number9 index8 alt2\">&nbsp;<\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val products = listOf(<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"My book\"<\/code><code class=\"bash plain\">, 20.0f),<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"Video course\"<\/code><code class=\"bash plain\">, 100.0f),<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"Consulting package\"<\/code><code class=\"bash plain\">, 500.0f)<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val persons = listOf(amelie)<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val sequences = listOf(<\/code><\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSequence(<\/code><code class=\"bash string\">\"Present book\"<\/code><code class=\"bash plain\">, listOf(<\/code><\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">bookSeqEmail1,<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 2\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number20 index19 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 3\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number22 index21 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number23 index22 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number24 index23 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">dataTransformer?.invoke(amelie, bookSeqEmail1)<\/code><\/div>\n<div class=\"line number26 index25 alt1\">&nbsp;<\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Question to user\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number28 index27 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Interesting topic A\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number31 index30 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Interesting topic B\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest book\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number34 index33 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I wrote a book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number35 index34 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest course\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number37 index36 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I wrote a course...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number38 index37 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"course_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number39 index38 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest consulting\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number40 index39 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I offer consulting...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number41 index40 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"consulting_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number42 index41 alt1\">&nbsp;<\/div>\n<div class=\"line number43 index42 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.setGlobal(<\/code><code class=\"bash string\">\"day\"<\/code><code class=\"bash plain\">, dayToConsider)<\/code><\/div>\n<div class=\"line number44 index43 alt1\">&nbsp;<\/div>\n<div class=\"line number45 index44 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(products)<\/code><\/div>\n<div class=\"line number46 index45 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">persons.forEach {<\/code><\/div>\n<div class=\"line number47 index46 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(it)<\/code><\/div>\n<div class=\"line number48 index47 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number49 index48 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sequences.forEach {<\/code><\/div>\n<div class=\"line number50 index49 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(it)<\/code><\/div>\n<div class=\"line number51 index50 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number52 index51 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>We achieve point 3 by specifying a filter on the rules to be executed:<\/p>\n<div>\n<div id=\"highlighter_871835\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">ksession.fireAllRules { match -&gt; match.rule.name <\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">rulesToKeep }<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>At this point we can simply check the results.<\/p>\n<p>Once this infrastructure has been put in place the tests we will write will look like this:<\/p>\n<div>\n<div id=\"highlighter_65049\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<div class=\"line number15 index14 alt2\">15<\/div>\n<div class=\"line number16 index15 alt1\">16<\/div>\n<div class=\"line number17 index16 alt2\">17<\/div>\n<div class=\"line number18 index17 alt1\">18<\/div>\n<div class=\"line number19 index18 alt2\">19<\/div>\n<div class=\"line number20 index19 alt1\">20<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">@<\/code><code class=\"bash functions\">test<\/code> <code class=\"bash plain\">fun startSequencePositiveCase() {<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val schedulings = setupSessionAndFireRules(<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.MARCH, 17), listOf(<\/code><code class=\"bash string\">\"Start sequence\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">assertEquals(1, schedulings.size)<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">assertNotNull(schedulings.<\/code><code class=\"bash functions\">find<\/code> <code class=\"bash plain\">{<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">it.sending.email.title == <\/code><code class=\"bash string\">\"Present book 1\"<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">&amp;&amp; it.sending.subscriber.name == <\/code><code class=\"bash string\">\"Amelie\"<\/code> <code class=\"bash plain\">})<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number9 index8 alt2\">&nbsp;<\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash plain\">@<\/code><code class=\"bash functions\">test<\/code> <code class=\"bash plain\">fun startSequenceWhenFirstEmailReceived() {<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val schedulings = setupSessionAndFireRules(<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.MARCH, 17),<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">listOf(<\/code><code class=\"bash string\">\"Start sequence\"<\/code><code class=\"bash plain\">)) { amelie, bookSeqEmail1 -&gt;<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">amelie.emailsReceived.add(<\/code><\/div>\n<div class=\"line number15 index14 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSending(bookSeqEmail1, amelie,<\/code><\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2018, Month.NOVEMBER, 12)))<\/code><\/div>\n<div class=\"line number17 index16 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number18 index17 alt1\">&nbsp;<\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">assertEquals(0, schedulings.size)<\/code><\/div>\n<div class=\"line number20 index19 alt1\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>In the first test we expect&nbsp;<em>Amelie<\/em> to receive the first email of a sequence, given she did not receive yet. In the second test instead we set in the session athat&nbsp;<em>Amelie<\/em> already received the first email of the sequence, so we expect it to not receive it again (no email schedulings expected at all).<\/p>\n<p>This is the whole code of the test class:<\/p>\n<div>\n<div id=\"highlighter_177555\" class=\"syntaxhighlighter  bash\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">001<\/div>\n<div class=\"line number2 index1 alt1\">002<\/div>\n<div class=\"line number3 index2 alt2\">003<\/div>\n<div class=\"line number4 index3 alt1\">004<\/div>\n<div class=\"line number5 index4 alt2\">005<\/div>\n<div class=\"line number6 index5 alt1\">006<\/div>\n<div class=\"line number7 index6 alt2\">007<\/div>\n<div class=\"line number8 index7 alt1\">008<\/div>\n<div class=\"line number9 index8 alt2\">009<\/div>\n<div class=\"line number10 index9 alt1\">010<\/div>\n<div class=\"line number11 index10 alt2\">011<\/div>\n<div class=\"line number12 index11 alt1\">012<\/div>\n<div class=\"line number13 index12 alt2\">013<\/div>\n<div class=\"line number14 index13 alt1\">014<\/div>\n<div class=\"line number15 index14 alt2\">015<\/div>\n<div class=\"line number16 index15 alt1\">016<\/div>\n<div class=\"line number17 index16 alt2\">017<\/div>\n<div class=\"line number18 index17 alt1\">018<\/div>\n<div class=\"line number19 index18 alt2\">019<\/div>\n<div class=\"line number20 index19 alt1\">020<\/div>\n<div class=\"line number21 index20 alt2\">021<\/div>\n<div class=\"line number22 index21 alt1\">022<\/div>\n<div class=\"line number23 index22 alt2\">023<\/div>\n<div class=\"line number24 index23 alt1\">024<\/div>\n<div class=\"line number25 index24 alt2\">025<\/div>\n<div class=\"line number26 index25 alt1\">026<\/div>\n<div class=\"line number27 index26 alt2\">027<\/div>\n<div class=\"line number28 index27 alt1\">028<\/div>\n<div class=\"line number29 index28 alt2\">029<\/div>\n<div class=\"line number30 index29 alt1\">030<\/div>\n<div class=\"line number31 index30 alt2\">031<\/div>\n<div class=\"line number32 index31 alt1\">032<\/div>\n<div class=\"line number33 index32 alt2\">033<\/div>\n<div class=\"line number34 index33 alt1\">034<\/div>\n<div class=\"line number35 index34 alt2\">035<\/div>\n<div class=\"line number36 index35 alt1\">036<\/div>\n<div class=\"line number37 index36 alt2\">037<\/div>\n<div class=\"line number38 index37 alt1\">038<\/div>\n<div class=\"line number39 index38 alt2\">039<\/div>\n<div class=\"line number40 index39 alt1\">040<\/div>\n<div class=\"line number41 index40 alt2\">041<\/div>\n<div class=\"line number42 index41 alt1\">042<\/div>\n<div class=\"line number43 index42 alt2\">043<\/div>\n<div class=\"line number44 index43 alt1\">044<\/div>\n<div class=\"line number45 index44 alt2\">045<\/div>\n<div class=\"line number46 index45 alt1\">046<\/div>\n<div class=\"line number47 index46 alt2\">047<\/div>\n<div class=\"line number48 index47 alt1\">048<\/div>\n<div class=\"line number49 index48 alt2\">049<\/div>\n<div class=\"line number50 index49 alt1\">050<\/div>\n<div class=\"line number51 index50 alt2\">051<\/div>\n<div class=\"line number52 index51 alt1\">052<\/div>\n<div class=\"line number53 index52 alt2\">053<\/div>\n<div class=\"line number54 index53 alt1\">054<\/div>\n<div class=\"line number55 index54 alt2\">055<\/div>\n<div class=\"line number56 index55 alt1\">056<\/div>\n<div class=\"line number57 index56 alt2\">057<\/div>\n<div class=\"line number58 index57 alt1\">058<\/div>\n<div class=\"line number59 index58 alt2\">059<\/div>\n<div class=\"line number60 index59 alt1\">060<\/div>\n<div class=\"line number61 index60 alt2\">061<\/div>\n<div class=\"line number62 index61 alt1\">062<\/div>\n<div class=\"line number63 index62 alt2\">063<\/div>\n<div class=\"line number64 index63 alt1\">064<\/div>\n<div class=\"line number65 index64 alt2\">065<\/div>\n<div class=\"line number66 index65 alt1\">066<\/div>\n<div class=\"line number67 index66 alt2\">067<\/div>\n<div class=\"line number68 index67 alt1\">068<\/div>\n<div class=\"line number69 index68 alt2\">069<\/div>\n<div class=\"line number70 index69 alt1\">070<\/div>\n<div class=\"line number71 index70 alt2\">071<\/div>\n<div class=\"line number72 index71 alt1\">072<\/div>\n<div class=\"line number73 index72 alt2\">073<\/div>\n<div class=\"line number74 index73 alt1\">074<\/div>\n<div class=\"line number75 index74 alt2\">075<\/div>\n<div class=\"line number76 index75 alt1\">076<\/div>\n<div class=\"line number77 index76 alt2\">077<\/div>\n<div class=\"line number78 index77 alt1\">078<\/div>\n<div class=\"line number79 index78 alt2\">079<\/div>\n<div class=\"line number80 index79 alt1\">080<\/div>\n<div class=\"line number81 index80 alt2\">081<\/div>\n<div class=\"line number82 index81 alt1\">082<\/div>\n<div class=\"line number83 index82 alt2\">083<\/div>\n<div class=\"line number84 index83 alt1\">084<\/div>\n<div class=\"line number85 index84 alt2\">085<\/div>\n<div class=\"line number86 index85 alt1\">086<\/div>\n<div class=\"line number87 index86 alt2\">087<\/div>\n<div class=\"line number88 index87 alt1\">088<\/div>\n<div class=\"line number89 index88 alt2\">089<\/div>\n<div class=\"line number90 index89 alt1\">090<\/div>\n<div class=\"line number91 index90 alt2\">091<\/div>\n<div class=\"line number92 index91 alt1\">092<\/div>\n<div class=\"line number93 index92 alt2\">093<\/div>\n<div class=\"line number94 index93 alt1\">094<\/div>\n<div class=\"line number95 index94 alt2\">095<\/div>\n<div class=\"line number96 index95 alt1\">096<\/div>\n<div class=\"line number97 index96 alt2\">097<\/div>\n<div class=\"line number98 index97 alt1\">098<\/div>\n<div class=\"line number99 index98 alt2\">099<\/div>\n<div class=\"line number100 index99 alt1\">100<\/div>\n<div class=\"line number101 index100 alt2\">101<\/div>\n<div class=\"line number102 index101 alt1\">102<\/div>\n<div class=\"line number103 index102 alt2\">103<\/div>\n<div class=\"line number104 index103 alt1\">104<\/div>\n<div class=\"line number105 index104 alt2\">105<\/div>\n<div class=\"line number106 index105 alt1\">106<\/div>\n<div class=\"line number107 index106 alt2\">107<\/div>\n<div class=\"line number108 index107 alt1\">108<\/div>\n<div class=\"line number109 index108 alt2\">109<\/div>\n<div class=\"line number110 index109 alt1\">110<\/div>\n<div class=\"line number111 index110 alt2\">111<\/div>\n<div class=\"line number112 index111 alt1\">112<\/div>\n<div class=\"line number113 index112 alt2\">113<\/div>\n<div class=\"line number114 index113 alt1\">114<\/div>\n<div class=\"line number115 index114 alt2\">115<\/div>\n<div class=\"line number116 index115 alt1\">116<\/div>\n<div class=\"line number117 index116 alt2\">117<\/div>\n<div class=\"line number118 index117 alt1\">118<\/div>\n<div class=\"line number119 index118 alt2\">119<\/div>\n<div class=\"line number120 index119 alt1\">120<\/div>\n<div class=\"line number121 index120 alt2\">121<\/div>\n<div class=\"line number122 index121 alt1\">122<\/div>\n<div class=\"line number123 index122 alt2\">123<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"bash plain\">package com.strumenta.funnel<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.drools.core.impl.InternalKnowledgeBase<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.drools.core.impl.KnowledgeBaseFactory<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.kie.api.io.ResourceType<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.kie.api.runtime.KieSession<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.kie.internal.builder.KnowledgeBuilderFactory<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.kie.internal.io.ResourceFactory<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.io.File<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.LocalDate<\/code><\/div>\n<div class=\"line number11 index10 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">java.<\/code><code class=\"bash functions\">time<\/code><code class=\"bash plain\">.Month<\/code><\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">kotlin.<\/code><code class=\"bash functions\">test<\/code><code class=\"bash plain\">.assertEquals<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">kotlin.<\/code><code class=\"bash functions\">test<\/code><code class=\"bash plain\">.assertNotNull<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"bash functions\">import<\/code> <code class=\"bash plain\">org.junit.Test as <\/code><code class=\"bash functions\">test<\/code><\/div>\n<div class=\"line number15 index14 alt2\">&nbsp;<\/div>\n<div class=\"line number16 index15 alt1\"><code class=\"bash plain\">class GenericRulesTest {<\/code><\/div>\n<div class=\"line number17 index16 alt2\">&nbsp;<\/div>\n<div class=\"line number18 index17 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">private fun prepareKnowledgeBase(files: List&lt;File&gt;): InternalKnowledgeBase {<\/code><\/div>\n<div class=\"line number19 index18 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder()<\/code><\/div>\n<div class=\"line number20 index19 alt1\">&nbsp;<\/div>\n<div class=\"line number21 index20 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">files.forEach { kbuilder.add(ResourceFactory.newFileResource(it), ResourceType.DRL) }<\/code><\/div>\n<div class=\"line number22 index21 alt1\">&nbsp;<\/div>\n<div class=\"line number23 index22 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val errors = kbuilder.errors<\/code><\/div>\n<div class=\"line number24 index23 alt1\">&nbsp;<\/div>\n<div class=\"line number25 index24 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">if<\/code> <code class=\"bash plain\">(errors.size &gt; 0) {<\/code><\/div>\n<div class=\"line number26 index25 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">for<\/code> <code class=\"bash plain\">(error <\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">errors) {<\/code><\/div>\n<div class=\"line number27 index26 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">System.err.println(error)<\/code><\/div>\n<div class=\"line number28 index27 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number29 index28 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">throw IllegalArgumentException(<\/code><code class=\"bash string\">\"Could not parse knowledge.\"<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number30 index29 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number31 index30 alt2\">&nbsp;<\/div>\n<div class=\"line number32 index31 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val kbase = KnowledgeBaseFactory.newKnowledgeBase()<\/code><\/div>\n<div class=\"line number33 index32 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">kbase.addPackages(kbuilder.knowledgePackages)<\/code><\/div>\n<div class=\"line number34 index33 alt1\">&nbsp;<\/div>\n<div class=\"line number35 index34 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash plain\">kbase<\/code><\/div>\n<div class=\"line number36 index35 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number37 index36 alt2\">&nbsp;<\/div>\n<div class=\"line number38 index37 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">fun loadDataIntoSession(ksession: KieSession,<\/code><\/div>\n<div class=\"line number39 index38 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">dayToConsider: LocalDate, dataTransformer: ((Subscriber, Email) -&gt; Unit)? = null) {<\/code><\/div>\n<div class=\"line number40 index39 alt1\">&nbsp;<\/div>\n<div class=\"line number41 index40 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val amelie = Subscriber(<\/code><code class=\"bash string\">\"Amelie\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number42 index41 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.FEBRUARY, 1),<\/code><\/div>\n<div class=\"line number43 index42 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"France\"<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number44 index43 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val bookSeqEmail1 = Email(<\/code><code class=\"bash string\">\"Present book 1\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number45 index44 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number46 index45 alt1\">&nbsp;<\/div>\n<div class=\"line number47 index46 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val products = listOf(<\/code><\/div>\n<div class=\"line number48 index47 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"My book\"<\/code><code class=\"bash plain\">, 20.0f),<\/code><\/div>\n<div class=\"line number49 index48 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"Video course\"<\/code><code class=\"bash plain\">, 100.0f),<\/code><\/div>\n<div class=\"line number50 index49 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Product(<\/code><code class=\"bash string\">\"Consulting package\"<\/code><code class=\"bash plain\">, 500.0f)<\/code><\/div>\n<div class=\"line number51 index50 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number52 index51 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val persons = listOf(amelie)<\/code><\/div>\n<div class=\"line number53 index52 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val sequences = listOf(<\/code><\/div>\n<div class=\"line number54 index53 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSequence(<\/code><code class=\"bash string\">\"Present book\"<\/code><code class=\"bash plain\">, listOf(<\/code><\/div>\n<div class=\"line number55 index54 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">bookSeqEmail1,<\/code><\/div>\n<div class=\"line number56 index55 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 2\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number57 index56 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">)),<\/code><\/div>\n<div class=\"line number58 index57 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">Email(<\/code><code class=\"bash string\">\"Present book 3\"<\/code><code class=\"bash plain\">, <\/code><code class=\"bash string\">\"Here is the book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number59 index58 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_explanation\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number60 index59 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number61 index60 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">)<\/code><\/div>\n<div class=\"line number62 index61 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">dataTransformer?.invoke(amelie, bookSeqEmail1)<\/code><\/div>\n<div class=\"line number63 index62 alt2\">&nbsp;<\/div>\n<div class=\"line number64 index63 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Question to user\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number65 index64 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number66 index65 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Interesting topic A\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number67 index66 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number68 index67 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Interesting topic B\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number69 index68 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"Do you...\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number70 index69 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest book\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number71 index70 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I wrote a book...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number72 index71 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"book_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number73 index72 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest course\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number74 index73 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I wrote a course...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number75 index74 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"course_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number76 index75 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(Email(<\/code><code class=\"bash string\">\"Suggest consulting\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number77 index76 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash string\">\"I offer consulting...\"<\/code><code class=\"bash plain\">,<\/code><\/div>\n<div class=\"line number78 index77 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">tags= listOf(<\/code><code class=\"bash string\">\"consulting_offer\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number79 index78 alt2\">&nbsp;<\/div>\n<div class=\"line number80 index79 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.setGlobal(<\/code><code class=\"bash string\">\"day\"<\/code><code class=\"bash plain\">, dayToConsider)<\/code><\/div>\n<div class=\"line number81 index80 alt2\">&nbsp;<\/div>\n<div class=\"line number82 index81 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(products)<\/code><\/div>\n<div class=\"line number83 index82 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">persons.forEach {<\/code><\/div>\n<div class=\"line number84 index83 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(it)<\/code><\/div>\n<div class=\"line number85 index84 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number86 index85 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">sequences.forEach {<\/code><\/div>\n<div class=\"line number87 index86 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.insert(it)<\/code><\/div>\n<div class=\"line number88 index87 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number89 index88 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number90 index89 alt1\">&nbsp;<\/div>\n<div class=\"line number91 index90 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">private fun setupSessionAndFireRules(dayToConsider: LocalDate, rulesToKeep: List&lt;String&gt;,<\/code><\/div>\n<div class=\"line number92 index91 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">dataTransformer: ((Subscriber, Email) -&gt; Unit)? = null) : List&lt;EmailScheduling&gt; {<\/code><\/div>\n<div class=\"line number93 index92 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val kbase = prepareKnowledgeBase(listOf(File(<\/code><code class=\"bash string\">\"rules\/generic.drl\"<\/code><code class=\"bash plain\">)))<\/code><\/div>\n<div class=\"line number94 index93 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val ksession = kbase.newKieSession()<\/code><\/div>\n<div class=\"line number95 index94 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">loadDataIntoSession(ksession, dayToConsider, dataTransformer)<\/code><\/div>\n<div class=\"line number96 index95 alt1\">&nbsp;<\/div>\n<div class=\"line number97 index96 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">ksession.fireAllRules { match -&gt; match.rule.name <\/code><code class=\"bash keyword\">in<\/code> <code class=\"bash plain\">rulesToKeep }<\/code><\/div>\n<div class=\"line number98 index97 alt1\">&nbsp;<\/div>\n<div class=\"line number99 index98 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash keyword\">return<\/code> <code class=\"bash plain\">ksession.selectScheduling(dayToConsider)<\/code><\/div>\n<div class=\"line number100 index99 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number101 index100 alt2\">&nbsp;<\/div>\n<div class=\"line number102 index101 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">@<\/code><code class=\"bash functions\">test<\/code> <code class=\"bash plain\">fun startSequencePositiveCase() {<\/code><\/div>\n<div class=\"line number103 index102 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val schedulings = setupSessionAndFireRules(<\/code><\/div>\n<div class=\"line number104 index103 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.MARCH, 17), listOf(<\/code><code class=\"bash string\">\"Start sequence\"<\/code><code class=\"bash plain\">))<\/code><\/div>\n<div class=\"line number105 index104 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">assertEquals(1, schedulings.size)<\/code><\/div>\n<div class=\"line number106 index105 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">assertNotNull(schedulings.<\/code><code class=\"bash functions\">find<\/code> <code class=\"bash plain\">{<\/code><\/div>\n<div class=\"line number107 index106 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">it.sending.email.title == <\/code><code class=\"bash string\">\"Present book 1\"<\/code><\/div>\n<div class=\"line number108 index107 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">&amp;&amp; it.sending.subscriber.name == <\/code><code class=\"bash string\">\"Amelie\"<\/code> <code class=\"bash plain\">})<\/code><\/div>\n<div class=\"line number109 index108 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number110 index109 alt1\">&nbsp;<\/div>\n<div class=\"line number111 index110 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">@<\/code><code class=\"bash functions\">test<\/code> <code class=\"bash plain\">fun startSequenceWhenFirstEmailReceived() {<\/code><\/div>\n<div class=\"line number112 index111 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">val schedulings = setupSessionAndFireRules(<\/code><\/div>\n<div class=\"line number113 index112 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2019, Month.MARCH, 17),<\/code><\/div>\n<div class=\"line number114 index113 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">listOf(<\/code><code class=\"bash string\">\"Start sequence\"<\/code><code class=\"bash plain\">)) { amelie, bookSeqEmail1 -&gt;<\/code><\/div>\n<div class=\"line number115 index114 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">amelie.emailsReceived.add(<\/code><\/div>\n<div class=\"line number116 index115 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">EmailSending(bookSeqEmail1, amelie,<\/code><\/div>\n<div class=\"line number117 index116 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">LocalDate.of(2018, Month.NOVEMBER, 12)))<\/code><\/div>\n<div class=\"line number118 index117 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number119 index118 alt2\">&nbsp;<\/div>\n<div class=\"line number120 index119 alt1\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">assertEquals(0, schedulings.size)<\/code><\/div>\n<div class=\"line number121 index120 alt2\"><code class=\"bash spaces\">&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"bash plain\">}<\/code><\/div>\n<div class=\"line number122 index121 alt1\">&nbsp;<\/div>\n<div class=\"line number123 index122 alt2\"><code class=\"bash plain\">}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h2 class=\"wp-block-heading\">Conclusions<\/h2>\n<p>Marketers should be able to experiment and try out their strategies and ideas easily: for example, do they want to create a special offer just to be sent at 20 subscribers per day? Do they want to send special offers to subscribers in a certain country? Do they want to consider the birthday or the national holiday of a subscriber to send him a special message? Our domain experts, marketers in this case, should have a tool to pour these ideas into the system and see them applied. Thanks to business rules they could be able to implement most of them by themselves. Not having to go through developers or other \u201cgate keepers\u201d could mean having the freedom to experiment, to try things and in the end to make the business profit.<\/p>\n<p>There are things to consider: giving the possibility to write business rules could not be enough. To make our domain experts confident in the rules they write we should give them the possibility to play with them and try them out in a safe environment: a testing or simulation mechanism should be put in place. In this way they could try things and see if they translated correctly into code the idea that they had in mind.<\/p>\n<p>Of course business rules are much easier to write compared to typical code. This is the case because they have a predefined format. In this way we can pick an existing rule and tune a little bit. Still, it requires some training for the domain experts to get used to them. They need to develop the ability to formalize their thoughts and this could be easy or hard depending on their background. For example, for marketers it could be doable while for other professionals it could require more exercise. What we could do to simplify their life and make domain experts more productive is to put a <a href=\"https:\/\/tomassetti.me\/domain-specific-languages\/\">Domain Specific Language<\/a> in front of our business rules.<\/p>\n<p>By creating a simple DSL we could make things easier for our marketers. This DSL would permit to manipulate the domain model we have seen (subscribers, emails, etc) and perform the two actions marketers are interested into: scheduling and blocking emails. We could provide a simple editor, with auto-completion and error checking, and integrate a testing and simulation environment in it. In this scenario marketers would be fully independent and able to design and verify their rules quickly and with very limited supported needed.<\/p>\n<p><strong>Acknowledgments<\/strong><\/p>\n<p>Mario Fusco (a Java champion) and Luca Molteni, both working on Drools at RedHat, were so very kind to review the article and suggest significant improvements. I am extremely thankful to them.<\/p>\n<p>Thank you!<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>Published on Java Code Geeks with permission by Federico Tomassetti, partner at our <a href=\"\/\/www.javacodegeeks.com\/join-us\/jcg\/\" target=\"_blank\" rel=\"noopener noreferrer\">JCG program<\/a>. See the original article here: <a href=\"https:\/\/tomassetti.me\/a-complete-tutorial-on-the-drools-business-rule-engine\/\" target=\"_blank\" rel=\"noopener noreferrer\">A complete tutorial on the Drools business rule engine<\/a><\/p>\n<p>Opinions expressed by Java Code Geeks contributors are their own.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>As always we share the code presented in the tutorial in a companion repository: EmailSchedulingRules. Business rules work very well to represent the logic for certain domains. They work well because they result intuitive and close to the way of thinking of many types of domain experts. The reason for that it is that they &hellip;<\/p>\n","protected":false},"author":951,"featured_media":152,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[980],"class_list":["post-90780","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-drools"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>A complete tutorial on the Drools business rule engine - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about business rule engine? Check our article discussing one specific example of application written by using business rules.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A complete tutorial on the Drools business rule engine - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about business rule engine? Check our article discussing one specific example of application written by using business rules.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-04-17T07:00:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/jboss-drools-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Federico Tomassetti\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@raindancer\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Federico Tomassetti\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"49 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html\"},\"author\":{\"name\":\"Federico Tomassetti\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/2da976480eeabb37d1f96edc20d63773\"},\"headline\":\"A complete tutorial on the Drools business rule engine\",\"datePublished\":\"2019-04-17T07:00:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html\"},\"wordCount\":3655,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/jboss-drools-logo.jpg\",\"keywords\":[\"Drools\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html\",\"name\":\"A complete tutorial on the Drools business rule engine - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/jboss-drools-logo.jpg\",\"datePublished\":\"2019-04-17T07:00:51+00:00\",\"description\":\"Interested to learn about business rule engine? Check our article discussing one specific example of application written by using business rules.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/jboss-drools-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/jboss-drools-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/04\\\/a-complete-tutorial-on-the-drools-business-rule-engine.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"A complete tutorial on the Drools business rule engine\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/2da976480eeabb37d1f96edc20d63773\",\"name\":\"Federico Tomassetti\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/10d3414571edf95f2255d57c9c02759daba20499f6761de9228c1cbbbd2fab6c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/10d3414571edf95f2255d57c9c02759daba20499f6761de9228c1cbbbd2fab6c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/10d3414571edf95f2255d57c9c02759daba20499f6761de9228c1cbbbd2fab6c?s=96&d=mm&r=g\",\"caption\":\"Federico Tomassetti\"},\"description\":\"Federico has a PhD in Polyglot Software Development. He is fascinated by all forms of software development with a focus on Model-Driven Development and Domain Specific Languages.\",\"sameAs\":[\"http:\\\/\\\/tomassetti.me\\\/\",\"https:\\\/\\\/fr.linkedin.com\\\/in\\\/federicotomassetti\",\"https:\\\/\\\/x.com\\\/raindancer\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/federico-tomassetti\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A complete tutorial on the Drools business rule engine - Java Code Geeks","description":"Interested to learn about business rule engine? Check our article discussing one specific example of application written by using business rules.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html","og_locale":"en_US","og_type":"article","og_title":"A complete tutorial on the Drools business rule engine - Java Code Geeks","og_description":"Interested to learn about business rule engine? Check our article discussing one specific example of application written by using business rules.","og_url":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-04-17T07:00:51+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/jboss-drools-logo.jpg","type":"image\/jpeg"}],"author":"Federico Tomassetti","twitter_card":"summary_large_image","twitter_creator":"@raindancer","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Federico Tomassetti","Est. reading time":"49 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html"},"author":{"name":"Federico Tomassetti","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/2da976480eeabb37d1f96edc20d63773"},"headline":"A complete tutorial on the Drools business rule engine","datePublished":"2019-04-17T07:00:51+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html"},"wordCount":3655,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/jboss-drools-logo.jpg","keywords":["Drools"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html","url":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html","name":"A complete tutorial on the Drools business rule engine - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/jboss-drools-logo.jpg","datePublished":"2019-04-17T07:00:51+00:00","description":"Interested to learn about business rule engine? Check our article discussing one specific example of application written by using business rules.","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/jboss-drools-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/jboss-drools-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2019\/04\/a-complete-tutorial-on-the-drools-business-rule-engine.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"A complete tutorial on the Drools business rule engine"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/2da976480eeabb37d1f96edc20d63773","name":"Federico Tomassetti","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/10d3414571edf95f2255d57c9c02759daba20499f6761de9228c1cbbbd2fab6c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/10d3414571edf95f2255d57c9c02759daba20499f6761de9228c1cbbbd2fab6c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/10d3414571edf95f2255d57c9c02759daba20499f6761de9228c1cbbbd2fab6c?s=96&d=mm&r=g","caption":"Federico Tomassetti"},"description":"Federico has a PhD in Polyglot Software Development. He is fascinated by all forms of software development with a focus on Model-Driven Development and Domain Specific Languages.","sameAs":["http:\/\/tomassetti.me\/","https:\/\/fr.linkedin.com\/in\/federicotomassetti","https:\/\/x.com\/raindancer"],"url":"https:\/\/www.javacodegeeks.com\/author\/federico-tomassetti"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/90780","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/951"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=90780"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/90780\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/152"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=90780"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=90780"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=90780"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}