Order of objects retrieved from working memory in Drools - drools

We have been coding a rule that changes the status of billed items that are repeated on the same day and that should only be billed once a day. All items have a status of 2 or 3 to begin with.
If a duplicated code is detected on an item with status 2 or 3, the item will get status 4 and the item in the working memory is updated.
When realising unit testing we can see the results are correct, but once we retrieve the objects from the working memory it seems the order of the items has changed to pretty much random.
Is this normal and why does it happen? (Obviously, the anomaly, if any, could be corrected by just reordering the list again).
Objects are inserted this way:
Iterator<Object> it = objects.iterator();
while (it.hasNext()) {
sessionStatefull.insert(it.next());
}
Its log is achieved by adding a logger to the KieSession:
public static KieSession getStatefulKnowledgeSessionWithCallback(KieContainer kieContainer, String sessionName) {
KieSession kieSession = null;
try {
kieSession = getStatefulKnowledgeSession(kieContainer, sessionName);
kieSession.addEventListener(new RuleRuntimeEventListener() {
OutputDisplay outputDisplay = new OutputDisplay();
#Override
public void objectInserted(ObjectInsertedEvent objectInsertedEvent) {
outputDisplay.showText("getStatefulKnowledgeSessionWithCallback.INSERT", objectInsertedEvent.getObject().toString());
}
The input is always the same:
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169800, units=1.0, code=1 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169801, units=1.0, code=1 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169802, units=1.0, code=2 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169803, units=1.0, code=2 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169804, units=1.0, code=6358]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169805, units=1.0, code=6007]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169806, units=1.0, code=6007]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169807, units=1.0, code=6385]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169808, units=1.0, code=6005]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169809, units=1.0, code=6225]
The output is obtained this way:
List<Object> list = new ArrayList<Object>((Collection<Object>) sessionStatefull.getObjects());
Its log is obtained with an Iterator:
Iterator<Object> it2 = list.iterator();
while (it2.hasNext()) {
Object object = it2.next();
outputDisplay.showText("Result: ", object.toString());
}
The printed output always seems to have a random order:
Example 1:
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169809, units=1.0, code=6225]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=4, id=150107315169801, units=1.0, code=1 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169800, units=1.0, code=1 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=4, id=150107315169803, units=1.0, code=2 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169802, units=1.0, code=2 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169807, units=1.0, code=6385]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169805, units=1.0, code=6007]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169804, units=1.0, code=6358]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=4, id=150107315169806, units=1.0, code=6007]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169808, units=1.0, code=6005]
Example 2:
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169804, units=1.0, code=6358]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=4, id=150107315169803, units=1.0, code=2 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=4, id=150107315169806, units=1.0, code=6007]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169805, units=1.0, code=6007]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=4, id=150107315169801, units=1.0, code=1 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169808, units=1.0, code=6005]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169807, units=1.0, code=6385]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169800, units=1.0, code=1 ]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169809, units=1.0, code=6225]
Item [date=Tue Jul 25 00:00:00 CEST 2017, status=2, id=150107315169802, units=1.0, code=2 ]
The logger class is defined like this:
public class OutputDisplay {
public void showText(String source, String text) {
try {
long time = System.currentTimeMillis();
Date date = new Date(time);
writeLog(time+" "+date.toString()+" A message from "+source+": "+text);
} catch (Exception exception) {
exception.printStackTrace();
}
}
writeLog opens a file and adds the line. We haven't paid any attention yet to some more sophisticated logging (i.e. logback...).

Drools doesn't internally keep the order of the inserted objects. The getObjects() method you are using states this by returning a Collection instead of a List.
The logger is showing the objects in order because it is invoked as soon as a new object is inserted into the working memory.
If you want to give some logical order to your objects I would suggest you to order them after you retrieve them from the working memory.
Hope it helps,

Related

Single planning calendar with fullday off

I have a problem with Single planning calendar.
I set fullday to false and set a startHour (8h) and endHour (17h).
But when i want to resize an appointment the startDate is not correct.
handleAppointmentResize: function (oEvent) {
var oAppointment = oEvent.getParameter("appointment"),
oStartDate = oEvent.getParameter("startDate"),
oEndDate = oEvent.getParameter("endDate"),
sAppointmentTitle = oAppointment.getTitle();
console.log(oStartDate);
console.log(oEndDate);
For exemple :
I have an appointment :
Wed Apr 06 2022 09:00:00 to Wed Apr 06 2022 13:00:00
I reduce them to 09:00 - 10:00
The result is
Mon Apr 04 2022 19:30:00 GMT+0200 (heure d’été d’Europe centrale)
Wed Apr 06 2022 09:00:00 GMT+0200 (heure d’été d’Europe centrale)
If i switch fullday to true, the result is ok !
Thanks for help
Resolve with upgrade of Sapui5 version

Returns the value in the next empty rows

Input
Here is an example of my input.
Number
Date
Motore
1
Fri Jan 01 00:00:00 CET 2021
Motore 1
2
Motore 2
3
Motore 3
4
Motore 4
5
Fri Feb 01 00:00:00 CET 2021
Motore 1
6
Motore 2
7
Motore 3
8
Motore 4
Expected Output
Number
Date
Motore
1
Fri Jan 01 00:00:00 CET 2021
Motore 1
2
Fri Jan 01 00:00:00 CET 2021
Motore 2
3
Fri Jan 01 00:00:00 CET 2021
Motore 3
4
Fri Jan 01 00:00:00 CET 2021
Motore 4
5
Fri Feb 01 00:00:00 CET 2021
Motore 1
6
Fri Feb 01 00:00:00 CET 2021
Motore 2
7
Fri Feb 01 00:00:00 CET 2021
Motore 3
8
Fri Feb 01 00:00:00 CET 2021
Motore 4
I tried to use the TmemorizeRows component but without any result, the second line is valorized but the others are not. Could you kindly help me.
You can solve this with a simple tMap with 2 inner variables (using the "var" array in the middle of the tMap)
Create two variables :
currentValue : you put in it the value of your input column date (in my example "row1.data").
updateValue : check whether currentValue is null or not : if null then you do not modify updateValue field . If not null then you update the field value. This way "updateValue" always contains not null data.
In output, just use "updateValue" variable.

Search data field by year in Janusgraph

I have a 'Date' property on my 'Patent' node class that is formatted like this:
==>Sun Jan 28 00:08:00 UTC 2007
==>Tue Jan 27 00:10:00 UTC 1987
==>Wed Jan 10 00:04:00 UTC 2001
==>Sun Jan 17 00:08:00 UTC 2010
==>Tue Jan 05 00:10:00 UTC 2010
==>Thu Jan 28 00:09:00 UTC 2010
==>Wed Jan 04 00:09:00 UTC 2012
==>Wed Jan 09 00:12:00 UTC 2008
==>Wed Jan 24 00:04:00 UTC 2018
And is stored as class java.util.Date in the database.
Is there a way to search this field to return all the 'Patents' for a particular year?
I tried variations of g.V().has("Patent", "date", 2000).values(). However, it doesn't return any results or an error message.
Is there a way to search this property field by year or do I need to create a separate property that just contains year?
You do not need to create a separate property for the year. JanusGraph recognizes the Date data type and can filter by date values.
gremlin> dateOfBirth1 = new GregorianCalendar(2000, 5, 6).getTime()
==>Tue Jun 06 00:00:00 MDT 2000
gremlin> g.addV("person").property("name", "Person 1").property("dateOfBirth", dateOfBirth1)
==>v[4144]
gremlin> dateOfBirth2 = new GregorianCalendar(2001, 5, 6).getTime()
==>Wed Jun 06 00:00:00 MDT 2001
gremlin> g.addV("person").property("name", "Person 2").property("dateOfBirth", dateOfBirth2)
==>v[4328]
gremlin> dateOfBirthFrom = new GregorianCalendar(2000, 0, 1).getTime()
==>Sat Jan 01 00:00:00 MST 2000
gremlin> dateOfBirthTo = new GregorianCalendar(2001, 0, 1).getTime()
==>Mon Jan 01 00:00:00 MST 2001
gremlin> g.V().hasLabel("person").
......1> has("dateOfBirth", gte(dateOfBirthFrom)).
......2> has("dateOfBirth", lt(dateOfBirthTo)).
......3> values("name")
==>Person 1

in RDD how do you get apply function like MIN/MAX for an Iterable class

I would like to find out the efficient way to apply function to an RDD:
Here is what I am trying to do :
I have defined the following class:
case class Type(Key: String, category: String, event: String, date: java.util.Date, value: Double)
case class Type2(Key: String, Mdate: java.util.Date, label: Double)
then a loaded an RDD:
val TypeRDD: RDD[Type] = types.map(s=>s.split(",")).map(s=>Type(s(0), s(1), s(2),dateFormat.parse(s(3).asInstanceOf[String]), s(4).toDouble))
val Type2RDD: RDD[Type2] = types2.map(s=>s.split(",")).map(s=>Type2(s(0), dateFormat.parse(s(1).asInstanceOf[String]), s(2).toDouble))
Then I try to create two new RDD - one that has Type.Key = Type2.Key and another one that has Type.Key not in Type2
val grpType = TypeRDD.groupBy(_.Key1)
vl grpType2 = Type2RDD.groupBy(_.Key1)
//get data where they Key1 does not exists in Type2 and return the values in grpType1
val tempresult = grpType fullOuterJoin grpType2
val result = tempresult.filter(_._2._2.isEmpty).map(_._2._1)
//get data where Type.Key == Type2.Key
val result2 = grpType.join.grpType2.map(_._2)
UPDATED:
typeRDD =
(19,EVENT1,TEST1,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT1,TEST1,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT2,TEST2,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(21,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(21,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(24,EVENT2,TEST2,Sun Aug 21 00:00:00 EDT 3396,1.0)
(24,EVENT2,TEST2,Sun Aug 21 00:00:00 EDT 3396,1.0)
(40,EVENT1,TEST1,Sun Aug 21 00:00:00 EDT 3396,1.0)
type2RDD =
(24,Wed Dec 22 00:00:00 EST 3080,1.0)
(40,Wed Jan 22 00:00:00 EST 3080,1.0)
SO FOR THE RESULT 1 : I would like to get the following
(19,EVENT1,TEST1,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT1,TEST1,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT2,TEST2,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(19,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(21,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
(21,EVENT3,TEST3,Sun Aug 21 00:00:00 EDT 3396,1.0)
FOR RESULT 2 :
(24,EVENT2,TEST2,Sun Aug 21 00:00:00 EDT 3396,1.0)
(24,EVENT2,TEST2,Sun Aug 21 00:00:00 EDT 3396,1.0)
(40,EVENT1,TEST1,Sun Aug 21 00:00:00 EDT 3396,1.0)
AND I THEN WANT TO COUNT THE NUMBER OF EVENTS PER KEY
RESULT :
19 EVENT1 2
19 EVENT2 1
19 EVENT3 2
21 EVENT3 2
RESULT2:
24 EVENT2 2
40 EVENT1 1
THEN I WANT TO GET THE MIN/MAX/AVG FOR THE EVENTS
1. RESULT1 MIN EVENT COUNT = 1
RESULT1 MAX EVENT COUNT = 5
RESULT1 AVG EVENT COUNT = 10/4 = 2.5

Maybe a bug in temporal reasoning on drools?

I want to test a scenario with temporal reasoning on drools. I have a Message class with timestamp field. when each event of this class received by drools, inserted into working memory and called fireAllRules(). in every firing I want to print timestamp of paired message ml and mo, that is ml after[0s,160s] mo. when I write my rule like below every things is Ok.
rule "Rule 1"
when
ml: Message()
mo: Message(ml after[0s,160s] this)
then
System.out.println("ml:"+new Date(ml.timestamp));
System.out.println("mo:"+new Date(mo.timestamp));
end
output:
Message received{"timestamp":"Feb 8 19:39:45", ... }
ml:Sun Feb 08 19:39:45 IRST 1970
mo:Sun Feb 08 19:39:45 IRST 1970
Message received{"timestamp":"Feb 8 19:40:04", ... }
ml:Sun Feb 08 19:40:04 IRST 1970
mo:Sun Feb 08 19:39:45 IRST 1970
ml:Sun Feb 08 19:40:04 IRST 1970
mo:Sun Feb 08 19:40:04 IRST 1970
Message received{"timestamp":"Feb 8 19:40:15", ... }
ml:Sun Feb 08 19:40:15 IRST 1970
mo:Sun Feb 08 19:40:04 IRST 1970
ml:Sun Feb 08 19:40:15 IRST 1970
mo:Sun Feb 08 19:39:45 IRST 1970
ml:Sun Feb 08 19:40:15 IRST 1970
mo:Sun Feb 08 19:40:15 IRST 1970
But when I rewrite rule in this form the output is not good.
rule "Rule 1"
when
ml: Message()
mo: Message(this before[0s,160s] ml)
then
System.out.println("ml:"+new Date(ml.timestamp));
System.out.println("mo:"+new Date(mo.timestamp));
end
output:
Message received{"timestamp":"Feb 8 19:41:40", ... }
ml:Sun Feb 08 19:41:40 IRST 1970
mo:Sun Feb 08 19:41:40 IRST 1970
Message received{"timestamp":"Feb 8 19:41:57", ... }
ml:Sun Feb 08 19:41:57 IRST 1970
mo:Sun Feb 08 19:41:57 IRST 1970
Message received{"timestamp":"Feb 8 19:42:02", ... }
ml:Sun Feb 08 19:42:02 IRST 1970
mo:Sun Feb 08 19:42:02 IRST 1970
Why in second form the output is not good? this problem observed when I used two parameters for temporal operators and "this" is the first operand.
Is "this before[0s,160s] ml" equals to "ml after[0s,160s] this"?
The second form is a bug?