capcom923 capcom923 - 1 month ago 19
Java Question

Drools timer based rule session always resides in memory and cause memory leak

I'm a newbie to Drools. I want to delay 5s after I fired the rule (and just for one time). So, I use timer(int:5s) to do that. But I found that after the rule executed, my console application will never be terminated and its javaw.exe process still exist in my task manager. The only one way is to call ksession.dispose(). But it's not acceptable because it's hard to find this ksession in our clustering architect.

So, is there any way to make the ksession automatically disposed after the rule executed?

Here are my simple test case:


  1. main class

    public class App {
    public static void main( String[] args ) {
    System.out.println("Started...");

    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(new ClassPathResource("Timer.drl", App.class), ResourceType.DRL);
    KnowledgeBase kbase = kbuilder.newKnowledgeBase();
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    ksession.fireAllRules();

    System.out.println("Ended");
    }
    }

  2. drl file

    package myDrools.TimerTest1

    rule "Your First Rule"

    timer(int:5s)

    when
    eval(true)
    then
    System.out.println("Finished");
    end


    The output will be:

    Started...
    Ended
    Finished



But my console application will never be terminated. Is there something wrong? I tested it both in Drools 5.6.0 Final and 6.4.0 Final. However, both of them has the same issue. I think the ksession should be disposed since timer(int:5s) is not an interval timer.

Answer

Timers run in parallel to the thread hosting the session and keep the session alive. In a way, they are meant to be used in sessions running indeterminate, i.e., not started calling fireAllRules.

The following scenario should give you a clean shutdown:

rule  "Your First Rule"
  timer( int:5s )
when
then
  System.out.println("Finished");
  drools.halt();
end

And your session is started like this:

kieSession.fireUntilHalt();
System.out.println( "return from fireUntilHalt" );
kieSession.dispose();
Comments