Southeast
Southeast

Reputation: 597

use java.util.Date in a rule's LHS

I'm a rookie of drools, learn about and work on drools for about 10 days. I was faced a problem that a Date() object is to be compared in a rule's LHS part.

    // in Java
    SimpleDateFormat format = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss");
    session.setGlobal("currentDate", format.format(new Date()));       

    # in drl file
    global java.lang.String currentDate ;
    #global java.util.Date currentDate; both tested
    when
    $united : LotteryUnitedDO(lotteryTypeId == LotteryTypeEnum.SSQ, 
        totalFee >= 1000, 
        shareCnt >= (0.1 * totalShare),
        #unitedEndTime is a java.util.Date Object
            unitedEndTime > currentDate     
        )

the value of currentDate is the current date, I've seen some examples and articles doing this but they used only the "yyyy-mm-dd" part of the date. Yet I have to compare the "hh:mm:ss" part. like this:

    $dateInputBox : DateInputBox(verifyDate > "12-Oct-2005")        

I tried to change the "drools.dateformat" property and format the date inserted into knowledge base only to get various of compilation error.So How can I deal with this or drools is just unable to deal with the hour part of a date in LHS?

Thanks in advance, all your suggestions are appreciated.

Upvotes: 1

Views: 11975

Answers (1)

mike9322
mike9322

Reputation: 634

To compare dates, you can simply use Drools Fusion's temporal operators (after, before, etc.):

when
  MyClass( myDate after $someOtherDate )
then
  ...

However, there is another problem with your approach: you should not reason against a global in a condition. See the Expert manual section on globals.

The notion of "now" is a bit problematic in Drools. Actually, maybe "problematic" isn't the right word; let's go with "tricky". How you represent it depends heavily on your use case. I'll try to summarize:

  • If you are executing within a stateless session, then your approach will work in combination with the Fusion operators. It is still not a recommended practice, however. A better approach is to define a fact, call it Now, which contains a single Date field. Initialize and insert it along with your other facts then reason against it instead of a global.
  • If you have a stateful session, it gets more tricky because real time is passing even while the session is idle, meaning your Now fact is getting more and more out of date. The way we have solved this is via the use of a WorkingMemoryEventListener. We use the objectInserted, objectRetracted, and objectUpdated methods of this listener to keep our Now fact current (we do not care about precision less than one minute so we check whether a minute has passed from the last update to avoid unnecessary overhead). Rules won't evaluate if working memory isn't changing, so using this listener is sufficient to ensure that Now is updated when it needs to be (unless you have queries that depend on the current value of Now, but that's another topic).
  • You could also look into using Drools Fusion in STREAM mode, which has a notion of "now", but also imposes a few other requirements. See the Fusion docs for more information.

Upvotes: 9

Related Questions