Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add facts to working memory at runtime in the Drools DRL and retrieve them in the execution results of a stateless session?

Tags:

java

drools

Background:

I'm working on an application that transforms an input object into one of two output objects based upon a set of drools rules. The output object is not known until runtime and it is created in the first rule to execute.

Here is the rule that creates the output object and an example transformation rule:

rule "Initialization"
    dialect "java"
    salience 1000
    no-loop true
    when
        t : Trade()
    then 
        if(t.getTran().getInsType().equalsIgnoreCase("EEO") ||
           t.getTran().getInsType().equalsIgnoreCase("EEF"))
        {
            insert(new Option());
        }
        else
        {
            insert(new Swap());
        }
end

rule "Example Rule"
    dialect "java"
    when
        t : Trade()
        opt : Option()
    then
        opt.setCounterpartyName(t.getTran().getCParty());
end

Here is the code that is calling the rules:

private void test(){
    for(File xmlFile : getXmlFilesFromDirectory(XML_DIRECTORY))
    {
        Trade trade = (Trade)unmarshall(xmlFile, Trade.class);

        KnowledgeBase kbase = readKnowledgeBase();

        StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
        KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newConsoleLogger(ksession);

        List<Command> commands = new ArrayList<Command>();
        commands.add(CommandFactory.newInsert(trade, "trade"));
        commands.add(CommandFactory.newFireAllRules());

        ExecutionResults results = ksession.execute(CommandFactory.newBatchExecution(commands));
        logger.close();
    }
 }

private static KnowledgeBase readKnowledgeBase() throws Exception 
{
    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource("security-transformation.drl"), ResourceType.DRL);
    KnowledgeBuilderErrors errors = kbuilder.getErrors();
    if (errors.size() > 0) 
    {
        for (KnowledgeBuilderError error: errors) 
        {
            System.err.println(error);
        }

        throw new IllegalArgumentException("Could not parse knowledge.");
    }

    KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
    kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
    return kbase;
}

Problem:

When I execute the rules I am not receiving the output object in my returned facts. I receive the trade object back but I do not get back the Option or the Swap object depending on which was added to working memory by the first rule.

Question:

How do I add facts to working memory at runtime in the drl and retrieve them in the execution results of a stateless session?

EDIT: Do I need to use a drools query?

like image 442
gregwhitaker Avatar asked May 03 '11 15:05

gregwhitaker


People also ask

What is working memory in drools?

Working Memory – a storage with Facts, where they are used for pattern matching and can be modified, inserted and removed. Rule – represents a single rule which associates Facts with matching actions. It can be written in Drools Rule Language in the . drl files or as Decision Table in an excel spreadsheet.

What is DRL file in drools?

DRL (Drools Rule Language) rules are business rules that you define directly in . drl text files. These DRL files are the source in which all other rule assets in Business Central are ultimately rendered.


1 Answers

I went ahead and used a drools query. I'll post the code for anyone else who comes along.

Query added to the rules above (The objects extend BaseTrade):

query "GetOutputObj"
    baseTrade: BaseTrade()
end

Code to retrieve the query results from the execution results:

    StatelessKnowledgeSession ksession = this.kbase.newStatelessKnowledgeSession();

    KnowledgeRuntimeLogger klogger = configureKnowledgeRuntimeLogger(ksession);

    List<Command> commands = new ArrayList<Command>();
    commands.add(CommandFactory.newInsert(inputObj, "inputObj"));
    commands.add(CommandFactory.newFireAllRules());
    commands.add(CommandFactory.newQuery("outputObj", "GetOutputObj"));

    ExecutionResults results = ksession.execute(CommandFactory.newBatchExecution(commands));

    QueryResults queryResults = ((NativeQueryResults)results.getValue("baseTrade")).getResults();

    try
    {
        Iterator iter = queryResults.iterator();
        while(iter.hasNext())
        {
            QueryResult result = iter.next();

            //There can be only one... just like Highlander
            //Could switch this up and return a list, but we only expect one thing from here.
            return (BaseTrade) result.get("baseTrade");
        }
    }
    finally
    {
        if(klogger != null)
        {
            klogger.close();
        }
    }
like image 169
gregwhitaker Avatar answered Sep 23 '22 06:09

gregwhitaker