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.