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.)
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
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)
Related
What does = do here?
List<Segment> totalSegments = flight.departureFlight.segments;
Do both, totalSegments and flight.departureFlight.segments point to the same memory reference or totalSegments has the same data as flight.departureFlight.segments but points to a different memory location?
My understanding was that the latter should happen since dart is pass by value and not reference. However, a very annoying bug occurred when I added this line below that one:
totalSegments.addAll(flight.returnFlight.segments);
This above line actually modified the flight variable which in turn somehow modified the AsyncSnapshot from the StreamBuilder. Although, I wasn't using the variable anywhere else and not modifying other variables mentioned.
This all happened inside build function of a Stateless Widget. Maybe that has to do something with it.
I tried reading dart documentation for it, but either I couldn't find what I am looking for or the information is simply missing there. Read this too, but according to this, my use case shouldn't happen.
When it comes to objects as in your case, you are assigning a reference to an existing object (memory location) to a new variable. While acting upon that reference, you change the same object.
If this is not what you intend, check out answers related to (deep) copying of the objects
You were mistaken by the fact that Dart passes by value, and not by reference. Actually, it is exactly the opposite: (Almost) everything is always passed by reference (Which is usually a good thing!) Therefore, it is quite logical that because you edited totalSegments your departureflight.segments got edited too. It is a synonym. One of the ways to solve your problem would be:
List<Segment> totalSegments = List();
totalSegments.addAll(flight.departureFlight.segments.toList());
List<Segment> totalSegments = flight.departureFlight.segments;
This expression does the following.
Assigns the value of the expression flight.departureFlight.segments to variable totalSegments.
This and only this and nothing more.
There is no need to know what is really happening, because this is what happens.
P.S.
What value will be obtained as a result of executing the expression flight.departureFlight.segments is another question, because it depends on the implementation of the members of the operands of the expression flight.departureFlight.segments.
I've been working with Stateful Sessions (KieSession) so far and have managed to get my project running as desired using Scala with a few Java wrappers. I am now trying to switch over to StatelessKieSessions. Based on the documentation I found, I've managed to run the following to insert objects/collections into the session, fire the rules on them and update the facts:
val cmd = CommandFactory.newInsert(myObject, "myObject")
val result = ksession.execute(cmd)
When I print result (which is of class org.drools.core.common.DefaultFactHandle), it shows the structure of the desired fact, updated as expected, preceded by something of the sort "fact 0:1:2050275256:1971742898:2:DEFAULT:NON_TRAIT:"
The documentation says that I should be able to write something like result.getValue("myObject") however this option doesn't seem to be available in Scala. (https://docs.jboss.org/drools/release/6.0.0.Beta1/kie-api-javadoc/org/kie/api/runtime/StatelessKieSession.html)
I understand that Scala-Drools interoperability hasn't been provided in full, however does anyone know of a way to extract updated facts from within a StatelessKieSession or a DefaultFactHandle containing it?
What you get from this execute command is the fact handle of the newly inserted fact. The object therein would still be the one you have inserted, updated or not. You'll have to investigate whether this is something you can use in Scala or not.
There is no command to retrieve all facts that have been changed during the execution of a session. You'll have to monitor this, using some of the available technique.
There's not much to be gained by running a "Stateless Session". If you can achieve what you want using a regular (stateful) session, leave it at that. The stateless session may have its advantages, but don't grapple with it from Scala.
I'm using the current version of the TypeSafe Scala/eclipse IDE. I have an object (which I called PositionObj to give it a unique name). PositionObj contains a main method. Yet when I try Run as > Scala application I get a pop-up message saying:
PositionObj needs to be an 'object' (it is currently a 'class').
In fact it's not a class, and there is no class with that name. Any thoughts about why this is happening and how I can get around it?
Here is the relevant code.
object PositionObj { ...
def main(args: Array[String] = Array[String]()): Unit = {
// This is just to see if anything happens.
println(position(3).p1Rqmts.keys.head)
}
...
Thanks.
Based on your answered-to code, try removing the default argument, since this might be creating a different code signature
I should have done this before, but now I notice that there is a compiler error message that says that the compiler couldn't handle the code because it was too big for a method. That's consistent with my experience with the problem. When I comment out a large table of data, everything works fine. So I'm now convinced that the problem was simply that the program was organized in a way that pieces of it were too large to be handled by the compiler.
I got around the problem by chopping my data table into multiple parts and including each one in a separate object. That worked even though all the objects were then included in the overall program. It was not the size of the program overall; it was the size of large chunks.
The compiler error message was somewhat misleading in that it said the problem was that a method was too large. In fact, my data table was a val in an object and not within a method. But as I said, chopping it up into separate objects and combing them with software solved the problem.
I'm using the #Check annotation in order to validate my dsl. my dsl is for json.
at first the method was invoked for a specific object and once per change
but it suddenly doesn't work in the same way anymore (and i'm not sure what i've done that effected it)
the method signature is:
#Check
public void validateJson(ObjectValue object) {...}
now its entering this method for each node in the gui although i'm editing only one node
The validator works normally in this case. When Xtext re-parses your model, it cannot always avoid re-creating the EMF model that is validated in the Check expression - in other words, the model is practically re-created every time, thus warranting a full validation.
However, in some cases, it is possible that only a partial re-creation of the model is necessary - in these cases it is possible that not all elements are re-validated (however, I am not sure whether this optimization was included).
I'm trying to build a system that can purge and regenerate URLs as required for a particular system. I previously was having issues with purging when the system located the object by hash but missed the variant as I didn't have a "purge;" in my vcl_miss (only in my vcl_hit, some guides/example vcl files do not mention this need but the main documentation does here).
What I'm trying to figure-out is if I need to do something similar for a REGEN call. From my understanding, "set req.hash_always_miss = true;" will mean that the old hash is missed and a new hash object is generated. Subsequent calls will find the new hash, but may still miss that object if there is not an appropriate variant in the cache.
Could someone confirm for me whether a subsequent request missing the variant in the new object will lead directly to a cache miss and fetch, rather than finding any of the variants from the previous object?
hash_always_miss will only influence the current/ongoing request and the cache contents that it replaces. A fetch will always happen, and the object will be put into the cache using the same rules as any other miss/fetch sequence.
The "old" other variants of the same hash are still valid objects and will be served to a client indicating request headers matching the varied headers.
hash_always_miss will replace the current variant, and nothing else.
To answer your question, the second part of your sentence is most correct.