Extracting facts/objects from DefaultFactHandle in Drools StatelessKieSession (via Scala) - scala

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.

Related

#karate How to pass parameter to a feature file in gatling simulation class?

Let's consider a scenario, we have to run the performance test for "create an account api" which takes input as header/path param "Auth token" and input data like user account name . So for above scenario we have 2 feature file as,
to run performance test for POST http://baseUrl/auth_param/create/input_data
1. One feature(e.g: generateAuth.feature) file which will have the auth
token
2. Second feature(createAccount.feature) file which take parameter as a
auth token, input data.
Here is my simulation class,
class <MyClass> extends Simulation {
before {
println("Simulation is about to start!")
}
val generateAuthTest = scenario("generateAuth").exec(karateFeature("classpath:path/generateAuth.feature"))
val createAccountTest = scenario("test").exec(karateFeature("classpath:path/createAccount.feature"))
setUp(
createAccountTest.inject(rampUsers(1) over (10 seconds))).maxDuration(1 minutes)
after {
println("Simulation is finished!")
}
}
Here, can i read auth from generateAuth.feature file which is input for createAccount.feature file, so that i can pass as a parameter?
Please suggest me how to pass parameters to createAccount.feature while calling in karateFeature method.
Let me put a requirement here,
let's say we have some feature files for CRUD operations on a particular data. Here how i go to write functional scenario,
I will create new feature file to write a scenario
just use CRUD files to test a SINGLE flow.
Now if i go for Performance test cases on individual operation, i feel there are 2 ways,
Create new 4 performance test feature files (one for each CRUD
method) and call these CRUD feature files in the respective test
feature file. Finally we just call test feature files in the
respective gatling simulation class.
**(In this case, I will end up with creating more test feature files as well simulation classes for
performance, which I want to avoid) **
Just call CRUD files in the respective gatling simulation class and
pass the required parameters to them.(In this case , we just need to create only 4 simulation
classes and run them on the basic of operation like create,read,delete and so on)
Here just wanted to know 2nd way of performance test, is it achievable or not in karate and if yes please let me know how?
Summary- I think its achievable using 3rd feature file (extra) for
individual use case but I do not want to make an extra feature file
for each case so that I can avoid maintenance work and can take
advantage of re-usability of existing feature file from functional
test to performance test.
Just use the normal Karate concepts such as karate-config.js
You can easily switch environments by setting the karate.env system property.
For example:
mvn test -DargLine="-Dkarate.env=e2e"
EDIT: after you edited your question, it is clear you have a SINGLE flow you want to test. please use a SINGLE feature. I suggest you move the generateAuth into the Background of the feature. Also refer to the docs on callSingle() for advanced options.
If you are expecting 2 feature files to magically share data that is not possible and not needed if you structure your tests correctly.
If you really really need this, please create a Java singleton and access it from each feature. Totally don't recommend this though.
EDIT: In Karate 0.9.0 onwards, you can call a single scenario within a feature if it has a tag:
classpath:animals/cats/create.feature#sometagname

Workflow Foundation: Error when resuming a persistent workflow after activity changes

the context of the problem is like this: we create workflows, we save it and after a while a new implementation request comes and we change an activity. After this the workflow instances that were saved cannot run anymore. We get this error:
StateMachine Error : Cannot convert object 'True' to type 'System.String'.
It seems that the new argument added brakes the serialization order?
You'll have to implement Dynamic Update in some fashion.
We are currently in the process of getting some infrastructure set up to update existing instances, and having lots of issues. Hopefully your scenario is easier to solve than ours!
Start here: https://msdn.microsoft.com/en-us/library/hh314052(v=vs.110).aspx
Word of caution: I've found various issues with Microsoft's provided code that required a lot of investigation to fix.

main/delta split marker with sphinx using xmlpipe2?

we are going to have sphinx running main+delta with nosql source. So we're going to use xmlpipe2. To implement main+delta strategy we have to maintain a marker to distinguish "main rows" from "new rows".
The problem is that, unlike sql sources, with xmlpipe2 we can't tell (at least don't know how) if the indexing was successful or not. If we simply update the marker at the end of the main feed generator, and indexing fails for whatever reason, the setup is going to be in inconsistent state.
For SQL sources we have sql_query_post_index hook, how can we achieve similar thing with xmlpipe2?
You could have a wrapper around indexer. that wrapper runs indexer, captures the output, and if the index worked, then it updates your 'marker'.
Call this wrapper from cron, rather can calling indexer directly

Retrieving Drools fact from main scope (Scala)

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)

Why does the Function Module name of a Smartform change (sometimes)?

Not really critical question, but i'm curious
I am working on a form and sometimes the generated function name is /1BCDWB/SF00000473, and sometimes /1BCDWB/SF00000472. This goes back and forth.
Does anyone know what's the idea behind this? Cuz i'm quite sure it's not a bug (or i might be wrong on that).
It is not a bug. You always have to use SSF_FUNCTION_MODULE_NAME to determine the actual function module name and call it dynamically using CALL FUNCTION l_function_module.
Smartform FMs are tracked by internal numbering and thats saved in the table STXFADMI. You would always notice the different number in Development System if you have deleted any existing Form. Similarly, you would also notice the different number in your Quality system based on the sequence the forms are imported in QAS and the forms as well (as test forms are not migrated to QAS.
Similar behavior is also true for Adobe Form generated FMs.
You need to understand that every smartform has a different interface and hence the automatically generated function module needs to have different import parameters.
Due to this reason the 'SSF*' FMs generate a FM specific for your smartform. The name of the 'generated' FM changes when you migrate from one system to another. And that's the reason why you should use a variable while calling the 'generated' fm and not hardcode it.
The same goes with Adobe form as someone has rightly said in this thread.