Friday, May 15, 2015

How to use Drools 6.2 in .Net using IKVM?



I have seen many posts asking about how to use or convert drools 6.2 in .net. I found few posts where someone had converted an older version of drools to .net but a lot has changed since then. In this post, I will show you how to use IKVM to convert Drools 6.2 jar files to .Net dll and use it in C#.


IKVM


IKVM.NET is an implementation of Java for Mono and the Microsoft .NET Framework. IKVM comes with IKVMC utility which is a Java bytecode to .NET IL translator. We will be using IKVMC to convert jar files to .net dll.


You can read more about IKVM at http://www.ikvm.net

  • Before you start, make sure that you have already installed java and drools on you machine.
  • Make sure JAVA_HOME variable is already set.


Convert Jar files to Dll


The simplest way to convert drools is to convert all jar files present in the binaries folder of drools installation. This will give you one big dll but you will save your self with class loading issues. It is a tedious task to find complete dependency tree of each jar and then convert them to dlls in correct order. This post will only focus on converting all jars to one dll solution but if you want to convert only required jars to a dll then you can read about jar2ikvmc and jaranalyzer
  • Open command prompt and change your path to drools installation e.g. C:\drools\6.2\drools-distribution-6.2.0.Final
  • Run following command: 
                 ikvmc -target:library -recurse:binaries/*.jar -out:mydrools.dll

Ignore all exceptions that you see on your command prompt and make sure you have mydrools.dll generated under your main drools directory outside binaries folder.

Using .Net dll in C#

  • Open Visual Studio and create a test console or windows application. 
  • Add a reference to following dlls
    • mydrools.dll (This is the dll that you just generated using ikvmc)
    • ikvm.runtime
    • ikvm.openjdk.core
Depending on how you have written your rules and code, you might also need to add references to ikvm.openjdk.jdbc and ikvm.openjdk.xml.parse
  • Here is the typical code that you would write in order to dynamically build KieBase, build your Rules and fire them.
            KieServices ks = KieServices.Factory.get();
            Resource rs = ks.getResources().newFileSystemResource(@"c:\drools\myrules.drl");
            KieFileSystem kfs = ks.newKieFileSystem();

            kfs.write("src/main/resources/some.drl", rs);
            KieBuilder kb = ks.newKieBuilder(kfs).buildAll();
            Results results = kb.getResults();
            if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR))
                Console.WriteLine(results.getMessages(Message.Level.ERROR));

            KieContainer kc = ks.newKieContainer(ks.getRepository().getDefaultReleaseId());
            KieBase kBase = kc.getKieBase();
            KieSession session = kBase.newKieSession();
    session.fireAllRules();
            session.dispose();


Potential Issues

I ran into few issues during this process and I will document them here with the solutions in case anyone encounter them.

  • If you are trying to convert java code compiled with the latest version of jdk (1.8.*), you might get class format error "51.0" from ikvmc. SOLUTION: This happens because class format has changed in jdk 1.8.*. You can fix this issue by compiling your java source code with an earlier version of jdk or try compiling ikvm source code against latest jdk.
  • After converting the drools to .Net, I noticed that the performance was a bit slower and also found the memory leak issues. The whole process of reloading the knowledge base with new rules was slower as it seemed that previous objects were not being cleared. After trying different workarounds and solutions, I found out that IKVM version available for download was compiled against .Net framework 2.0, which didn't offer code garbage collection back then. SOLUTION: Download the source for for IKVM and compile it against .Net framework 4.0. it comes with a read me file that has instructions on how to compile the code with nant.

Alternative to IKVM

While I was running into issues with IKVM, I also tried JNBride (http://jnbridge.com), which is a licensed software and unlike IKVM you will have to spend $$$ to use it. This is basically a bridge between .Net and Java and use proxy classes to communicate with JVM. I found it to be much faster than IKVM and basically performance was as good as running it directly in java. We are talking about milliseconds here when it comes to firing the rules. Building the knowledge base and your rules is an expensive operation that usually takes seconds. With IKVM it took 21 sec to build a drool file with 1,000 rules whereas JNBridge only took 9 secs.

I hope it helps.