0

I'm currently inserting an object into Drools working memory and running rules on it (creating a new object rather than updating the old one since I'm using Scala immutables...). From what I've understood, typically you would say something like update(myobject) and that would update the original variable inserted, letting you use the updated myObject in the main scope once the rules have been fired.

Since the objects I'm using (and inserting to memory) are immutable I can't simply modify them, and I'm having to create copies of them with slight tweaks.

Is there a way to return an object created within a rule's RHS? Perhaps by calling its FactHandle? Also open to other workarounds...

Alternatively, can I create a new object (newObject) and assign it the original's (myObject) FactHandle? Would that give me the access I need?

(Once again, I'm looking for a workaround to get Scala and Drools to work together.)

GroomedGorilla
  • 920
  • 2
  • 10
  • 30
  • 1
    "Alternatively, can I...FactHandle?" Read your own SO questions. You have an update statement where the FactHandle is used in combination with a (new) fact. – laune Feb 19 '15 at 17:56
  • Well, crap...you're right! Forgot all about that! I think that should work out...*shame* Thanks for pointing that out @laune. Someone needs some sleep... FYI referenced question is: http://stackoverflow.com/questions/28323507/creating-new-scala-object-in-drools-right-hand-side – GroomedGorilla Feb 20 '15 at 10:00
  • That actually worked. Used `update(kcontext.getKieRuntime().getFactHandle($b), $newB)` and managed to update the object as expected. Only flaw in it is that its going into an infinite loop despite the no-loop setting. Once that's sorted should be fine :) Thanks @laune – GroomedGorilla Feb 20 '15 at 13:22
  • You can easily construct loops going over two or more rules, which is where no-loop won't help. – laune Feb 20 '15 at 14:16
  • Care to elaborate? I'm having a go with lock-on-active too now. I'm seeing (via println) that the facts are being updated, but keep getting NullPointerExceptions when trying to call the original object by its FactHandle. Are FactHandles transferred when using `update` too? – GroomedGorilla Feb 23 '15 at 09:37
  • Loop: rule A modifies F on propX, triggers rule B modifies F on propY, triggers rule A,... – laune Feb 23 '15 at 09:53
  • FactHandle/update: This is where **you** start reading the Drools sources. You are navigating in unchartered waters, so take the lead... – laune Feb 23 '15 at 09:55
  • Thanks @laune. Granted, it's uncharted territory but the Drools documentation isn't helping much either. Finding clear descriptions of modify(), update() and other functionality together with their parameters in the new Kie model (even in the official Documentation) is proving tricky. Will keep up the search. – GroomedGorilla Feb 23 '15 at 10:06

2 Answers2

1

As far as I understand you problem, you could create a copy of the object with the tweaks you need and then you retract the old object and insert the new one. Something similar to:

val newObject = myObject.copy(foo = "bar");
retract(myObject);
insert(newObject);

I hope, it helps

Josep Prat
  • 493
  • 5
  • 11
  • Thanks @Josep , that is part of what I'm looking for. From what I've seen, if I 'insert(myObject)' before firing the rules, then once they have finished myObject should have been updated by the rules. My question is whether I can retrieve a different object (newObject in your example) instead. Perhaps by assigning it the FactHandle of the original object? – GroomedGorilla Feb 19 '15 at 15:45
  • 1
    I definetely do something like this in my tests, never tried in the RHS. `final FactHandle handle = knowledgeSession.getFactHandle(fact); knowledgeSession.update(handle, newFact);` – Josep Prat Feb 19 '15 at 15:51
  • Of course you can do that on the RHS as well - it's Java. And OP did just than in one of his earlier posts. – laune Feb 19 '15 at 17:57
  • @laune Not saying it's not possible, just said I never used it :) – Josep Prat Feb 20 '15 at 11:52
0

After looking around and some prolonged trial and error I realised that FactHandles didn't quite work the way I expected. I was under the impression that they were an ID assigned to an object and that updating the object would mean that it kept its FactHandle (apparently not).

I went about this by creating a new (Scala) object and running update in the RHS of the rule as follows:

update(kcontext.getKieRuntime().getFactHandle(myObject), newObject)

While this worked fine within the rule-firing process, it was tedious to retrieve the object from the Main app afterwards. Calling ksession.getFactHandle(myObject) on the original object returned null after the rules had been fired and, as it turns out, the FactHandle of this object had indeed changed when checked by printing it out from within a rule.

The workaround for this was to save the original object's FactHandle before firing the rules (i.e. val objectFH = ksession.insert(myObject)) and to call .getObject using that FactHandle after the rules were fired (even though the FactHandle saved in this variable had changed).

In all honesty, I'm still unsure about why this works since the FactHandle changes on update, however I'm pretty sure this stems from my lack of understanding on how FactHandles work. If anyone would care to elaborate in the comments I'd be more than happy to add it in the answer for future reference.

(Thanks to @laune for helping point me back to my previous questions)

GroomedGorilla
  • 920
  • 2
  • 10
  • 30