问题
I am evaluating Drools 6 in a proof of concept application. I am either misunderstanding how the queries in Drools work or I have not implemented something properly. Could someone explain this behavior to me:
I have a rule that is supposed to act on validated records like this:
rule "Patient Intake: Valid new Patients without a Medical History require a Review"
ruleflow-group "Patient Intake"
when
$patient : Patient( status == PatientStatus.NEW )
not Invalid( value == $patient )
then
modify( $patient ){
setStatus( PatientStatus.PENDING_REVIEW )
};
insert( new Valid( $patient ) );
end
query "Intake Results"
Valid( $patients : value )
end
The Valid/Invalid objects are used like one would use a trait, however the documentation indicated that the trait feature was still experimental/subject to change, so I chose this alternative for the time being. The query is straightforward enough I think. I am using a stateless session and invoking the engine like a decision service. The following snippet of code shows how the engine is invoked (some values are hardcoded at the moment):
StatelessKieSession kSession = kContainer.newStatelessKieSession( "TestKSession" );
KieRuntimeLogger auditLog = KieServices.Factory.get().getLoggers().newFileLogger( kSession, "audit" );
kSession.setGlobal( "logger", logger );
List<Command> commands = new ArrayList<Command>();
commands.add( CommandFactory.newInsertElements( request.getAllFacts() ) );
commands.add( CommandFactory.newQuery( "$patients", "Intake Results" ) );
commands.add( CommandFactory.newStartProcess( "x.y.z.intake" );
ExecutionResults results = kSession.execute( CommandFactory.newBatchExecution( commands ) );
auditLog.close();
And I process the results like this:
private void processResults( ExecutionResults results ) {
QueryResults qr = (QueryResults) results.getValue( "$patients" );
for ( QueryResultsRow row : qr ) {
// ... this code is never executed
}
}
In the console I see the println statement that the QueryResult size is 0. However, if I change the query to just collect $patients : Object() the QueryResult size is the number of objects inserted via the CommandFactory and does not include the objects inserted as part of the RHS of the rule. When I check the audit log i see that an object of type Valid is indeed inserted.
Why is my query not returning the intended results? Did I implement something wrong or am I just misunderstanding how queries work?
Thanks, James
回答1:
The order that the commands are added matters. Adding the query command is a signal to the engine to execute that query, therefore the facts were being inserted and the query run BEFORE the process was started.
Reversing the lines where the queries were added and the process started was the key. It should now read:
List<Command> commands = new ArrayList<Command>();
commands.add( CommandFactory.newInsertElements( request.getAllFacts() ) );
commands.add( CommandFactory.newStartProcess( "x.y.z.intake" );
commands.add( CommandFactory.newQuery( "$patients", "Intake Results" ) );
来源:https://stackoverflow.com/questions/30060305/drools-queries-how-are-they-evaluated-and-executed