Ben Ben - 4 months ago 142
Java Question

How to get Drools (Kie Session) running in a Netbeans Web-Project (No Maven)?

For several days I'm trying to run Drools in Netbeans but it just doesn't work like I want it to. I even tried to get it working as a maven project but that didn't work as well. I describe what I do to create the project, hopefully someone can give me a hint.

First of i need it to work without maven because I'm restricted to not use it. But before I put it in the real project I want to test it.

So first I create a new project


  1. File>New Project.. Wizard

  2. Chose "Java Web" Categorie and use Projecttype "Webapplication"

  3. Selection a tomcat 8 webserver and Java EE 7 Web

  4. No Frameworks for now (later hibernate)

  5. Create lib folder in project and putting following jars in it:


    • drools-compiler-6.4.0.Final.jar

    • drools-core-6.4.0.Final.jar

    • drools-decisiontables-6.4.0.Final.jar

    • drools-jsr94-6.4.0.Final.jar

    • drools-reteoo-6.4.0.Final.jar

    • knowledge-api-6.4.0.Final.jar

    • kie-api-6.4.0.Final.jar

    • kie-internal-6.4.0.Final.jar

    • kie-ci-6.4.0.Final.jar

    • mvel2-2.2.6.Final.jar

    • antlr-runtime-3.5.Final.jar




With this Setup I create classes (both in package: Drools)
DroolsMain (test without webserver and gui for faster debugging)

public class DroolsMain {

private static KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
private static Collection<KnowledgePackage> pkgs;
private static KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
private static StatefulKnowledgeSession ksession;

public static void main(final String[] args) {
init();
initMessageObject();
fireRules();
}

private static void init() {
String myRule = "import Drools.Message rule \"Hello World 2\" when message:Message (type==\"Test\") then System.out.println(\"Test, Drools!\"); end";
Resource myResource = ResourceFactory.newReaderResource((Reader) new StringReader(myRule));
kbuilder.add(myResource, ResourceType.DRL);

if(kbuilder.hasErrors()) {
System.out.println(kbuilder.getErrors().toString());
throw new RuntimeException("unable to compile dlr");
}

pkgs = kbuilder.getKnowledgePackages();

kbase.addKnowledgePackages(pkgs);

ksession = kbase.newStatefulKnowledgeSession();
}

private static void fireRules() {
ksession.fireAllRules();
}

private static void initMessageObject() {
Message msg = new Message();
msg.setType("Test");
ksession.insert(msg);
}
}


and the above used Message class

public class Message {
private String type;
private String message;

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}


}


I now can run that code and have a the message returned.

Now i wanted to try it with Kie...

i just comment the methods in DroolsMain main() method.
and put a Kie method in like current Drools documentation p. 172-174 there:

private static void kieTest() {
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

StatelessKieSession kSession = kContainer.newStatelessKieSession();
Applicant bob = new Applicant("Mr. Bob", 16);
//assertTrue(bob.isValid());
kSession.execute(bob);
//assertFalse(bob.isValid());
}


I didn't put the Applicant.class in here becaus its just a bean with 3 attributes.
Also I create DRL applicant.drl file:

package Drools "Is of valid age"
import Drools.Applicant

when
$a : Applicant(age < 18)
then
$a.setValid(false);
end;


So this obviously does not work because Kie has maven dependencies so i tried this:
1. Add directories:
- DroolsTest/resources/
- DroolsTest/resources/META-INF
- DroolsTest/resources/META-INF/maven
- DroolsTest/resources/Drools
2. Create DroolsTest/resources/META-INFkmodule.xml

Content:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="Drools" packages="Drools">
<ksession name="ksession-drools" />
</kbase>
</kmodule>



  1. Create DroolsTest/resources/META-INF/maven/pom.properties
    Content: (groupId my package name), (artifactId my project name)

    groupId=Drools
    artifactId=DroolsTest
    version=1

  2. put drl file here: DroolsTest/resources/Drools/applicant.drl



Compiling this throws a RuntimeException:

Exception in thread "main" java.lang.RuntimeException: Cannot find a default KieSession
at org.drools.compiler.kie.builder.impl.KieContainerImpl.findKieSessionModel(KieContainerImpl.java:555)
at org.drools.compiler.kie.builder.impl.KieContainerImpl.newKieSession(KieContainerImpl.java:548)
at org.drools.compiler.kie.builder.impl.KieContainerImpl.newKieSession(KieContainerImpl.java:531)
at Drools.DroolsMain.kieTest(DroolsMain.java:43)
at Drools.DroolsMain.main(DroolsMain.java:52)
C:\Users\...\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 3 seconds)


Is there a solution to get Kiew working without maven or can I read in a file without it?




UPDATE:

I tried launes solution:

import java.io.File;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Results;
import org.kie.api.io.Resource;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class DroolsMain {
private void ntry() {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();

File rule = new File("src/main/resources/Drools/applicant.drl");
Resource res = kieServices.getResources().newFileSystemResource(rule);
kfs.write(res);
KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
Results results = kieBuilder.getResults();

System.out.println("---Messages---");
System.out.println(results.getMessages());

KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
KieBase kieBase = kieContainer.getKieBase();
KieSession kieSession = kieBase.newKieSession();
}

public static void main(final String[] args) {
DroolsMain dm = new DroolsMain();
dm.ntry();
}
}


I also added all jars from the drools distribution. Now it compiles and has no errors

Answer

That's how I do it, no maven, no XML:

public void build() throws Exception {
    KieServices kieServices = KieServices.Factory.get();
    KieFileSystem kfs = kieServices.newKieFileSystem();
    //...
    Resource res = ...; 
    kfs.write( "src/main/resources/simple.drl", res );
    KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
    Results results = kieBuilder.getResults();
    if( results.hasMessages( Message.Level.ERROR ) ){
        System.out.println( results.getMessages() );
        throw new IllegalStateException( "### errors ###" );
    }

    KieContainer kieContainer =
        kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );

    KieBase kieBase = kieContainer.getKieBase();
    kieSession = kieBase.newKieSession();
}

I usually use a Resource such as

kieServices.getResources().newInputStreamResource( fis )

since reading from a file is more flexible.

Comments