Search code examples
javadroolsdecision-model-notation

Drools: Evaluation of DMN 1.2 FEEL-functions does not work


I want to evaluate in Drools 7.21 FEEL-funtions that are new in DMN 1.2, like sqrt() or modulo(), but the method

dmnRuntime.evaluateAll(dmnModel,context)

is allways returning the value 'null' (just for the new functions) with status 'SUCCESS'. What do I do wrong or what is missing?

The DMN-File looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<semantic:definitions xmlns:semantic="http://www.omg.org/spec/DMN/20180521/MODEL/" xmlns="http://www.trisotech.com/definitions/_56fd6445-ff6a-4c28-8206-71fce7f80436" xmlns:feel="http://www.omg.org/spec/FEEL/20140401" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exporter="DMN Modeler" exporterVersion="6.0.1" id="_56fd6445-ff6a-4c28-8206-71fce7f80436" name="Sqrt-Function" namespace="http://www.trisotech.com/definitions/_56fd6445-ff6a-4c28-8206-71fce7f80436" >
  <semantic:decision id="_cf6124bd-9907-4ac0-b4fd-59a962dbc502" name="square_root">
    <semantic:variable id="_edaf978e-3634-4e52-8244-5fd4e16fd257" name="square_root" typeRef="feel:number"/>
    <semantic:literalExpression id="_c990c3b2-e322-4ef9-931d-79bcdac99686">
      <semantic:text>sqrt(81)</semantic:text>
    </semantic:literalExpression>
  </semantic:decision>
</semantic:definitions>

After importing the file in "dmnModel":

DMNMarshaller marshaller = new org.kie.dmn.backend.marshalling.v1x.XStreamMarshaller();
FileInputStream fis = new FileInputStream( dmnFile );
Definitions unmarshal = marshaller.unmarshal( new InputStreamReader( fis ) );
DMNCompiler compiler = DMNFactory.newCompiler();
DMNModel dmnModel = compiler.compile(unmarshal);

I call the Drools-evaluation like this:

KieContainer kieContainer = KieHelper.getKieContainer(ks.newReleaseId("org.kie", "dmn-test-"+UUID.randomUUID(), "1.2"));
DMNRuntime dmnRuntime = kieContainer.newKieSession().getKieRuntime(DMNRuntime.class);
((DMNRuntimeImpl) dmnRuntime).setOption(new RuntimeTypeCheckOption(true));
DMNResult result = dmnRuntime.evaluateAll(dmnModel, context);

Solution

  • It would be best advised not to (un)marshall and not to having to compile the DMN file manually; instead to use the standard means of standard build of KieContainer from the KJAR; as detailed by the user guide in the documentation.

    In other words, this works correctly with your DMN file:

    KieServices kieServices = KieServices.Factory.get();
    KieContainer kieContainer = kieServices.getKieClasspathContainer();
    DMNRuntime dmnRuntime = KieRuntimeFactory.of(kieContainer.getKieBase()).get(DMNRuntime.class);
    DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName);
    DMNContext context = dmnRuntime.newContext();
    ((DMNRuntimeImpl) dmnRuntime).setOption(new RuntimeTypeCheckOption(true));
    DMNResult result = dmnRuntime.evaluateAll(dmnModel, context);
    

    producing 9 as a result.

    If you really want to use the KieHelper anyway, it is best advised to pass in the DMN file as a KieResource, to the call of KieHelper.getKieContainer(...), for example this:

    KieContainer kieContainer = KieHelper.getKieContainer(ks.newReleaseId("org.kie", "dmn-test-" + UUID.randomUUID(), "1.2"),
                                                          ks.getResources().newFileSystemResource(new File(dmnFile)));
    DMNRuntime dmnRuntime = KieRuntimeFactory.of(kieContainer.getKieBase()).get(DMNRuntime.class);
    ((DMNRuntimeImpl) dmnRuntime).setOption(new RuntimeTypeCheckOption(true));
    DMNModel dmnModel = dmnRuntime.getModel(namespace, modelName);
    DMNContext context = dmnRuntime.newContext();
    DMNResult result = dmnRuntime.evaluateAll(dmnModel, context);
    System.out.println(result);
    

    you can change the call ks.getResources().newFileSystemResource(...) to a URL, ClassPath, Byte, ... -based resource as needed, based on your use-case. This way the KieHelper will be in charge of unmarshalling

    Also this second snippet works for me with your DMN file, producing 9 as a result.

    The problem in your code is the initialisation of the DMNCompiler is not really meant to be invoked manually by the user, and in fact nowhere in the documentation there is a requirement to manage this manually; both the above methods would delegate this to the internals of the KieContainer/KieHelper, which would be the standard way.

    I would advice to follow the KieContainer build as detailed in the documentation as in the former example, but I hope this answer help you resolve for you either way --locally both working for me.

    Hope this helps!