Search code examples
javadrools

Migrating from Drools 6.0.1 to Drools 6.3.0-Final got Unexpected global [log] error


java.lang.RuntimeException: Unexpected global [log]
at org.drools.core.impl.StatefulKnowledgeSessionImpl.setGlobal(StatefulKnowledgeSessionImpl.java:1163)
  1. DRLs are retrieved from a database as list of Strings.
  2. We dont use kmodule.xml Following the comments : The DRL (minimized the setup to try and locate the issue) is loaded without a hitch but somehow the globals defined in it, are not .

KieSession creation code

 KieServices ks = KieServices.Factory.get();
        KieRepository kr = ks.getRepository();
        KieFileSystem kFileSystem = ks.newKieFileSystem();

        int i=0;
        for (String ruleId : drls.keySet()){
            Resource resource = ks.getResources().newByteArrayResource(drls.get(ruleId).getBytes());
            resource.setTargetPath("./out/"+ ruleId +".drl");
            resource.setResourceType(ResourceType.DRL);
            kFileSystem.write(resource);
        }
        KieBuilder kieBuilder = ks.newKieBuilder( kFileSystem );
        kieBuilder.buildAll();
    KieBuilder kieBuilder = ks.newKieBuilder( kFileSystem );
    kieBuilder.buildAll();
    if (kieBuilder.getResults().hasMessages(Message.Level.ERROR)) {
        log.error(PolicyUtils.createMsg("DRL Errors:\n" + kieBuilder.getResults().toString()), context, null, null);
        throw new RuntimeException("DRL Errors:\n" +         kieBuilder.getResults().toString());
    }
    kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
    kContainer.newKieSession();

Solution

  • After reading your chat with @laune in the other answer, I guess that the problem is now identified: Your KieBase doesn't contain the artifacts (rules, globals, etc.) you think it does.

    No idea what could be wrong with your code, but I think a simple workaround could save you from all that boilerplate (and error-prone) code you have there.

    The idea here is to use the KieHelper class instead of using KieRepository, KieFileSystem and KieBuilder. Actually, the KieHelper class was created to avoid this complicated steps (in comparison with Drools 5.x) involved in the creation of a KieBase.

    Using the KieHelper class, you can refactor your code to look similar to this:

    KieHelper kieHelper = new KieHelper();
    for (String ruleId : drls.keySet()) {
        kieHelper.addContent(drls.get(ruleId), ResourceType.DRL);
    }
    Results results = kieHelper.verify();
    for (Message message : results.getMessages()) {
        log.error(">> Message ({}): {}", message.getLevel(), message.getText());
    }
    
    if (results.hasMessages(Message.Level.ERROR)) {
        throw new IllegalStateException("There are errors in the KB.");
    }
    
    KieSession ksession = kieHelper.build().newKieSession();
    

    Hope it helps,