How to create time based rules

In this tutorial we will learn how to create time based rules using Drools rules engine. When combined with a timer, a Drools rule can be an useful option, to monitor some attributes and perform some actions accordingly. 

Let’s see at first an example of Drools rules  which can be activated on a timer configuration:

rule "Send SMS every 15 minutes"
    timer (cron:* 0/15 * * * ?)
when
    $a : Alarm( on == true )
then
    channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on" );
end

As you can see the timer configuration is equivalent to the well-known cron expression and will re-evaluate the  this rule every 15 minutes. Now let’s build an example application which will show how you can monitor an attribute (f.e. the amount of memory of a Server) using a Drool rule,

The following rule, will be evaluated every 5 seconds and will monitor the “memory” attribute of the Server fact. If the value drops below a certain amount (f.e. 1000 MB) a warning is printed, and the event is added to the “global” Event class:

package com.sample
import java.util.Date
import java.util.List
import com.sample.app.Server

global com.sample.app.Event event


rule "Server memory"
dialect "mvel"
timer (cron:0/5 * * * * ?)


when
$server : Server(memory < 1000)
then
System.out.println("Warning low memory detected!");
event.add(new java.util.Date() + " - WARNING: Server " + $server.name + " has low memory " + $server.memory);


end

And here’s the JUnit test class which is going to execute this rule:

package com.sample.app;

import java.util.Date;

import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.impl.ClassPathResource;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
import org.junit.Test;
 
public class DBRulesTest {

    private FactHandle serverHandle;

    @Test
    public void memoryTest() throws InterruptedException {

        final StatefulKnowledgeSession ksession = createKnowledgeSession();
        Event myevent = new Event();
        ksession.setGlobal("event", myevent);

        final Server node1 = new Server(1500,"server1");
         

        new Thread(new Runnable() {
            public void run() {
                ksession.fireUntilHalt();
            }
        }).start();

        serverHandle = ksession.insert(node1);
        
        int memory = 1500;
        for (int i=0;i<5;i++){
            Thread.sleep(6000);
            memory = memory - 200;
       
            node1.setMemory(memory);
            ksession.update(serverHandle, node1);
            
        }

        ksession.halt();
        System.out.println(myevent.getEvents());
    }

    private StatefulKnowledgeSession createKnowledgeSession() {
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add(new ClassPathResource("myrule.drl", getClass()), ResourceType.DRL);

        if (kbuilder.hasErrors()) {
            if (kbuilder.getErrors().size() > 0) {
                for (KnowledgeBuilderError kerror : kbuilder.getErrors()) {
                    System.err.println(kerror);
                }
            }
        }

        KnowledgeBase kbase = kbuilder.newKnowledgeBase();
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        return ksession;
    }

}

As you can see, this example uses the org.drools.runtime.StatefulKnowledgeSession which is the main interface for interacting with the Drools engine. It has methods for inserting, updating, and retracting facts. StatefulKnowledgeSession is also used to set the session’s global variables. Probably, the most interesting part of its API is the fireAllRules method, which is used to execute all rules. In our example, since we want to complete the cron timer’s functionality, it is necessary to maintain the working memory continually checking if there are activations created to automatically fire them. To implement it we have used the fireUntilHalt() method, which will keep firing the activations created until none remains in the agenda.

Here’s the expected output on the console, which should be triggered, once the memory of the server is set to a value under 1000:

Warning low memory detected!
Warning low memory detected!
Warning low memory detected!

And here’s what has been recorded into the Event class:
[Wed May 01 22:36:15 CEST 2013> WARNING: Server server1 has low memory 900, Wed May 01 22:36:20 CEST 2013> WARNING: Server server1 has low memory 900, Wed May 01 22:36:25 CEST 2013> WARNING: Server server1 has low memory 700]

The Event class contains barely a static ArrayList where we record events:

package com.sample.app;

import java.util.ArrayList;
import java.util.List;

public class Event {

    static List<String> events = new ArrayList();

    public static List<String> getEvents() {
        return events;
    }

    public static void add(String log) {
        events.add(log);
    }
}

Recommended Articles

Get Started with JBoss Drools: Core Concepts & Tools

Discover how to bootstrap a Drools project, code simple rules, and run Drools in your Java environment. #Java #Drools #KIE #BusinessRules #AIExpertSystem

Mastering JBoss Drools: A Comprehensive Guide to Rules Engines and Decision Management

Learn the basics of JBoss Drools, a powerful rules engine for Enterprise Java applications, including its architecture, API, and decision management capabilities.

Drools Guvnor Repository Tutorial: Uploading and Using Rules in WildFly 31

Learn how to use Drools Guvnor repository with JBoss AS and upload rules for business rule management in this tutorial.

Create a Drools Project with kie-drools-archetype in WildFly 31

Learn how to create a Drools project using Maven's kie-drools-archetype and deploy it on WildFly 31. This tutorial covers the basics of creating a Drools project, including rule files, KieSession, and more.