Call overloaded method from Drools: `unable to resolve method using strict-mode`

Alain Tanguay picture Alain Tanguay · May 5, 2015 · Viewed 18.3k times · Source

I'm newbie with java and drools and I have to build a java RESTful Web Services / rules engine. We already have Genesys Rule Authoring (GRAT) and Genesys Rule Engine (GRE) (version 8.1.2) who run drools version 5.2. We have the need to take the source of GRAT packages and use them in a "lite rule engine" for our development environments. For my POC, I have install drools 5.2 and create a project who can digest my package and fire rules just like I want. But for some package I have this kind of error :

BuildError: Unable to Analyse Expression $routingparams.priority = obtenirValeurParametre($routingparams.priority,"100");
$routingparams.target1 = obtenirValeurParametre($routingparams.target1, "AVGRP_GPAP_AEP_TA_MDP_E");:
[Error: unable to resolve method using strict-mode: com.desjardins.gtd.dpsccc.routage.gpap.routingparams.ObtenirValeurParametre.obtenirValeurParametre(java.lang.Integer, java.lang.String)]
[Near : {... ngparams.priority = obtenirValeurParametre($routin ....}]

If you look at package at the end, you'll see that the function obtenirValeurParametre(String, String). You'll also see this function call with (Integer, String) and the error is on this line. In drools package I can't have the same function with different params. I have try to use "drools.dialect.mvel.strict" = false, but it doesn't change anything.

KnowledgeBuilderConfiguration kbConfig =KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
kbConfig.setProperty("drools.dialect.mvel.strict", "false");
System.setProperty("drools.dialect.mvel.strict", "false");
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder( kbConfig );

As GRE run drools 5.2 like me and it work for GRE, I think that it must exist a solution other then add .toString() or something like this. Considering that we have a lot of package and some of them have thousand of rules, I don't want to make adjustments on each rule.

Someone have an idea to solve that issues? He/She will be my hero!

package com.desjardins.gtd.dpsccc.routage.gpap.routingparams

import java.util.*;

function String obtenirValeurParametre(String valeurActuelle, String parametre){
    if(parametreEstVide(parametre)) return "";  
    if("*".equals(parametre)) return valeurActuelle;
    else return parametre;
}

function boolean parametreEstVide(String parametre){
    if(parametre.startsWith("{") && parametre.endsWith("}")) return true;
    else return false;
}

declare RoutingParams
    target1: String
    priority: Integer
end 

declare ContexteInteraction
    destination: String
end 

#from row number: 1
rule "Row 1 DT-6249 UNIT_Test Alain"
salience 99000 
    agenda-group "level1"
    dialect "mvel"
    when
        ContexteInteraction( destination == 'GPAP_AEP_TA_MDP')
        $routingparams:RoutingParams(); 
        $contexteInteraction:ContexteInteraction();
    then
        $routingparams.priority = obtenirValeurParametre($routingparams.priority,'100')
        $routingparams.target1 = obtenirValeurParametre($routingparams.target1, 'AVGRP_GPAP_AEP_TA_MDP_E')
end

Thanks

Alain

Answer

laune picture laune · May 6, 2015

Overloading a DRL function isn't possible in any Drools version.

The usual workaround for problems with functions (there are more restrictions) is to use and import static Java methods from a class such as:

public class Utils {
    public static String 
    obtenirValeurParametre(String valeurActuelle, String parametre){
        if(parametreEstVide(parametre)) return "";  
        return "*".equals(parametre) ? valeurActuelle : parametre;
    }

    public static String 
    obtenirValeurParametre(Integer valeurActuelle, String parametre){
        if(parametreEstVide(parametre)) return "";  
        return "*".equals(parametre) ?
               valeurActuelle.toString() : parametre;
    }

    public static boolean
    parametreEstVide(String parametre){
        return parametre.startsWith("{") && parametre.endsWith("}");
    }
}

You need one change per DRL file:

import static the.package.name.Utils.*;

That was the good news.

I have tested this using versions 5.3, and it fails with dialect MVEL, and it's safe to assume that it won't work with 5.2 (which is too old for me to have around). MVEL was full of bugs when being integrated into Drools during the 5.x-development. Plenty of hard work has improved matters, though.

And so it works, even with dialect MVEL in versions 5.5 and 6.2. You'll have to upgrade to 5.5, 5.6 or 6.2. The latter will mean some changes to the Java code for compiling and executing.