Red Hat
Mar 14, 2012
by devdude

I want to share some more tips and more realistic data and rules scenarios.

  • Netbeans : If you run the java file (Run File)with the sample code instead of running the whole application, the resources and NOT rebuild, means any changes made to the rules would not be reflected. So rither Cleand and Build or run the application then resources are rebuild automatically.
  • Threads: In the first sample we did not use a separate thread to fire the rules. If you update or insert facts after the initial ksession.fireAllRules() you will not see any output from the engine, only if you call it again. I recommend the thread approach with ksession.fireUntilHalt() as shown in the last tutorial .
  • Container : A simple java application might be good enough for the first steps, but more realistic is the execution in a web application running in a container. I will post a separate tutorial how to run the rule engine inside a singleton EJB on Glassfish.

Rule samples and code snippets:  Managing Flights and Times

The previous samples with message instances are not close to anything realistic, so I create a little airport scenario. It wont be able to run an airport’s operations but gives an idea. I skip the basic initialization etc. We will use the pseudo clock.

  • We operate an airport with arriving and departing flights.
  • Our simplified data model

    Flights with attributes: Flightnumber, airlinecode, aircrafttype, origin, destination, number of pax.  + internal primary key

    Flight times with attributes:   Timestamp, type. + foreign key to Flights
  • Arriving flights usually have this or similar sequence of events: Scheduled Time (STOA) – Estimated (ETOA) – Landed/Touchdown (LAND) – OnBlock Time (ONBL)

    (in real operations you will have more events, also from different sources)
  • Rule 1 : Alert me if the ETOA (often coming from automated interfaces like ATC or IATA Telex messages from the origin airport of the flight) is more than 30min after scheduled arrival time  STOA (maybe to inform public at the airport)
  • Rule 2 : Alert me if the time between LAND and ONBL is more than 5min .
  • The rule does not make much operational sense, because you want to warn someone that the aircraft is still not at the position after minutes on the ground, means it is still taxiing and you want to inform the ground crew about it

    Rule 2b : Alert me if there is no ONBL 5min after the LAND event.
  • The Flight class

    public class Flight {
    
        private String flightKey;
        private String flightNumber;
        private String airline2lc;
        private String origin;
        private String destination;
        ... more attributes, getter-setter etc.
    }
    
  • The Flight Time class

    public class FlightTime {
    
        private Date flighttime;
        private long flighttimestamp;
        private String type;
        private String flightkey;
        ... constructor,getter-setter etc.
    }
    
  • For the simple comparison of times (Rule 1 and 2) we can ignore the session clock and use this simple rule

    rule "RULE 5"
    when
        time1:FlightTime(key:flightkey,type=='STOA') from entry-point entryone
        time2:FlightTime(flightkey == key, type=='ETOA', this after[ 30m ] time1) from entry-point entryone
    then
        System.out.println("More than 30min between STOA and ETOA: " + time1.getFlightkey() );
    end
    

    Insert facts (flight times), rules get fired by the separate thread (see previous sample )

    ..
    entrypoint1.insert(new FlightTime(new SimpleDateFormat("MM/dd/yy HH:mm").parse("03/08/12 12:00"), "STOA", "1"));
    entrypoint1.insert(new FlightTime(new SimpleDateFormat("MM/dd/yy HH:mm").parse("03/08/12 12:40"), "ETOA", "1"));
    ..
    
  • For Rule 2b we need to use the session clock

    rule "RULE 6"
    when
        time1:FlightTime(key:flightkey,type=='LAND') from entry-point entryone
        not (
            FlightTime(flightkey == key, type=='ONBL', this after[ 0,5m ] time1) from entry-point entryone
            )
    then
        System.out.println("Missing ONBL after 5min LAND: " + time1.getFlightkey() );
        System.out.println("Session Time at rule trigger: " + (drools.getWorkingMemory().getSessionClock().getCurrentTime())/60000);
    end
    

    Note: We cant use the separate thread like previously, but we must fire ksession.fireAllRules(); everytime we advance the clock !

         SessionPseudoClock clock = ksession.getSessionClock();
    
         clock.advanceTime(2, TimeUnit.MINUTES);
         entryPoint1.insert(new FlightTime((clock.getCurrentTime()), "LAND", "1"));
    
         clock.advanceTime(10, TimeUnit.MINUTES);
    
         ksession.fireAllRules();
         ..
    
  • Run with Rule 2b

    Missing ONBL after 5min

  • Challenge for now: The engine looks at the timestamp of fact insertion, so I cant backdate my timestamps, which would be necessary if you get delayed updates from an interface.

    Eg. at 02:00 you get LAND with timestamp 01:00 you would expect the rule to be triggered at 06:00 (01:00 + 5min) but it gets triggered at 07:00

    Will explore Fusion further to cover this situation.