Embedding and Testing Drools Flow in your Java Project

Drools Flow provides workflow capabilities and can easily integrate rules with processes. You can easily define the series of steps that would be followed in a workflow using the flowchart based approach to get a rule file. All this works like a charm with the drools plugin in eclipse and if you are interested then there is good information here to work with the plugin. This post however talks about a few struggles that I had to face to embed the drools flow in my Java based project.

We use maven for building our projects for a couple of reasons. First, we like it as a build tool and second, a fellow Inphiner is authoring a book on Maven. So we are bound to be biased.

Anyway, one of the problems that I see with the maven way of doing things is that many big projects would host a maven repository on their own rather that put it on maven central. Though, I am not a proponent of this approach as it makes findings libraries difficult for me as a developer, however, as per Spring, there are reasons why they do it that way. JBoss also does it this way.

The repository for Jboss through which you would get the drools file is

[sourcecode language=”xml”]
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>
[/sourcecode]

Then you would need a few dependencies to make Drools work within your project, these are

[sourcecode language=”xml”]
<properties>
<drools.process.version>5.1.1</drools.process.version>
<xstream.version>1.2.2</xstream.version>
</properties>

<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-process-task</artifactId>
<version>${drools.process.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.process.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.process.version}</version>
</dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
[/sourcecode]

notice that I used, 5.1.1, there is 5.2.0.Snapshot as well but when I checked, that does not exist for drools-process-task. The main libraries required are drools-compiler, drools-core and drools-process-task. There is also an xstream requirement.

Once this was done, as a sample, I was able to execute the following code in my project

[sourcecode language=”java”]
public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");

SampleEntity entity = new SampleEntity();
entity.setEntityName("Cars");

Set<SampleAttribute> attributes = new HashSet<SampleAttribute>();
SampleAttribute attribute1 = new SampleAttribute();
attribute1.setAttributeName("color");
attribute1.setAttributeType("red");
SampleAttribute attribute2 = new SampleAttribute();
attribute2.setAttributeName("shape");

entity.setAttributes(attributes );

ksession.insert(entity);
ksession.insert(attribute1);

// start a new process instance
ksession.startProcess("com.sample.ruleflow");
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}

private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("ruleflow.rf"), ResourceType.DRF);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
[/sourcecode]

For acceptance testing, we use fitnesse. I included all the drools jars in my fitnesse library path as

[sourcecode language=”text”]
classpath: /home/vikas/.m2/repository/org/drools/drools-api/5.1.1/drools-api-5.1.1.jar
classpath: /home/vikas/.m2/repository/org/drools/drools-compiler/5.1.1/drools-compiler-5.1.1.jar
classpath: /home/vikas/.m2/repository/org/drools/drools-core/5.1.1/drools-core-5.1.1.jar
classpath: /home/vikas/.m2/repository/org/drools/drools-process-task/5.1.1/drools-process-task-5.1.1.jar
classpath: /home/vikas/.m2/repository/org/drools/drools-workitems/5.1.1/drools-workitems-5.1.1.jar
[/sourcecode]

However, the test would not run for the want to eclipse jdt. Hence I included the following

[sourcecode language=”text”]
classpath: /home/vikas/.m2/repository/org/eclipse/jdt/core/compiler/ecj/3.5.1/ecj-3.5.1.jar
classpath: /home/vikas/.m2/repository/org/antlr/antlr-runtime/3.1.3/antlr-runtime-3.1.3.jar
[/sourcecode]

Now, the functionality of drools flow that I am using right now works like a charm both inside my Java project as well as Fitnesse.

Written by 

Vikas is the CEO and Co-Founder of Knoldus Inc. Knoldus does niche Reactive and Big Data product development on Scala, Spark, and Functional Java. Knoldus has a strong focus on software craftsmanship which ensures high-quality software development. It partners with the best in the industry like Lightbend (Scala Ecosystem), Databricks (Spark Ecosystem), Confluent (Kafka) and Datastax (Cassandra). Vikas has been working in the cutting edge tech industry for 20+ years. He was an ardent fan of Java with multiple high load enterprise systems to boast of till he met Scala. His current passions include utilizing the power of Scala, Akka and Play to make Reactive and Big Data systems for niche startups and enterprises who would like to change the way software is developed. To know more, send a mail to hello@knoldus.com or visit www.knoldus.com

Leave a Reply

%d bloggers like this: