Drools, Camel and Spring

Objectives

In this example we will integrate Drools, Spring and Camel.

  • We will first execute a test to show that our Rules are firing using just Drools
  • Next we will test our Spring / Drools integration is working by loading a Drools Stateful Session bean and firing the rules associated with it.
  • We will then execute a program to bind our Stateful Session to JNDI and use Camel to access the session and fire the rules.
  • Finally, we will use Spring to bind our Stateful Session to JNDI and use Camel to load the CamelContext bean and fire the rules associated with the session.

Create the Project

File -> New -> Maven Project

Create a Simple Project

Group Id: com.skills421.drools.examples

Artifact Id: DroolsCamelSpring

Finish

Edit pom.xml

Edit the pom.xml file as follows:

[code language=”xml”]
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.skills421.examples.drools</groupId>
<artifactId>DroolsCamelSpring</artifactId>
<version>0.0.1-SNAPSHOT</version>

<properties>
<drools.version>5.6.0.Final</drools.version>
<commons-version>1.1.3</commons-version>
<junit.version>4.11</junit.version>
</properties>

<dependencies>
<!– Drools dependencies –>
<dependency>
<groupId>org.drools</groupId>
<artifactId>knowledge-api</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>

<!– Drools Spring –>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-spring</artifactId>
<version>${drools.version}</version>
</dependency>

<!– Drools Grid –>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-grid-impl</artifactId>
<version>5.6.0.Final</version>
</dependency>

<!– Drools Camel –>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-camel</artifactId>
<version>${drools.version}</version>
</dependency>

<!– Logging –>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>${commons-version}</version>
</dependency>

<!– test dependencies –>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>

</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
[/code]

pom.xml

Create a Simple Rule

In both src/main/resources and src/test/resources create the directory structure rules/skills421/examples.
In the examples folder create the file rules.drl as follows:

[code language=”java”]
package rules.skills421.examples

rule "always true"
dialect "mvel"
when
then
System.out.println("Woohoo – Rules are running!");
end
[/code]

rules.drl

Create the ApplicationContext.xml

In src/main/resources create the file applicationContext.xml as follows:

[code language=”xml”]
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<import resource="classpath:drools-context.xml"/>
<!– Show Spring where to search for the beans (in which packages) –>
<!– <context:component-scan base-package="com.skills421.examples.drools.model" /> –>

</beans>
[/code]

applicationContext.xml

Create drools-context.xml

In src/main/resources create the file drools-context.xml as follows:

[code language=”xml”]
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:drools="http://drools.org/schema/drools-spring"
xmlns:camel="http://camel.apache.org/schema/spring"

xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd

http://drools.org/schema/drools-spring
http://drools.org/schema/drools-spring.xsd">

<bean id="droolsPolicy" class="org.drools.camel.component.DroolsPolicy" />

<drools:grid-node id="node1" />

<drools:resource id="resource1" type="DRL"
source="classpath:rules/skills421/examples/rules.drl" />

<drools:kbase id="kbase1" node="node1">
<drools:resources>
<drools:resource ref="resource1" />
</drools:resources>
</drools:kbase>

<drools:ksession id="ksession1" type="stateful" kbase="kbase1" node="node1" />

<camel:camelContext id="camelContext">
<camel:route>
<camel:from uri="direct:test-session2" />
<camel:policy ref="droolsPolicy">
<camel:unmarshal ref="xstream" />
<camel:to uri="drools:node1/ksession1" />
<camel:marshal ref="xstream" />
</camel:policy>
</camel:route>
</camel:camelContext>

</beans>
[/code]

drools-context.xml

Create the JUnit Tests as follows

In src/test/java create the class SimpleRuleRunnerTest as follows:

[code language=”java”]
package com.skills421.drools.examples;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;

import javax.naming.Context;

import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.util.jndi.JndiContext;
import org.drools.KnowledgeBase;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.command.BatchExecutionCommand;
import org.drools.command.Command;
import org.drools.command.CommandFactory;
import org.drools.command.runtime.rule.FireAllRulesCommand;
import org.drools.grid.GridNode;
import org.drools.grid.impl.GridImpl;
import org.drools.grid.service.directory.WhitePages;
import org.drools.grid.service.directory.impl.WhitePagesImpl;
import org.drools.io.impl.ClassPathResource;
import org.drools.runtime.ExecutionResults;
import org.drools.runtime.StatefulKnowledgeSession;
import org.hibernate.mapping.Array;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SimpleRuleRunnerTest
{
@Test
public void testDrools()
{
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(new ClassPathResource("rules/skills421/examples/rules.drl", getClass()),ResourceType.DRL);

if (kbuilder.hasErrors())
{
if (kbuilder.getErrors().size() > 0)
{
for (KnowledgeBuilderError kerror : kbuilder.getErrors())
{
System.err.println(kerror);
}
}
}

KnowledgeBase kbase = kbuilder.newKnowledgeBase();

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

ksession.fireAllRules();
}

@Test
public void testWithSpring()
{
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
applicationContext.start();

StatefulKnowledgeSession ksession1 = (StatefulKnowledgeSession) applicationContext.getBean("ksession1");

ksession1.fireAllRules();
applicationContext.stop();

applicationContext.close();
}

@Test
public void testWithCamel()
{
try
{
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(new ClassPathResource("rules/skills421/examples/rules.drl", getClass()),ResourceType.DRL);

if (kbuilder.hasErrors())
{
if (kbuilder.getErrors().size() > 0)
{
for (KnowledgeBuilderError kerror : kbuilder.getErrors())
{
System.err.println(kerror);
}
}
}

KnowledgeBase kbase = kbuilder.newKnowledgeBase();

StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

GridImpl grid = new GridImpl();
grid.addService(WhitePages.class, new WhitePagesImpl());
GridNode node = grid.createGridNode("node");
Context context = new JndiContext();
context.bind("node", node);
node.set("ksession1", ksession);

CamelContext camelContext = new DefaultCamelContext(context);
RouteBuilder rb = new RouteBuilder()
{
public void configure() throws Exception
{
from("direct:test-session1").to("drools://node/ksession1");
}
};
camelContext.addRoutes(rb);

@SuppressWarnings("rawtypes")
List<Command> commands = new ArrayList<Command>();

FireAllRulesCommand fireAllRulesCommand = (FireAllRulesCommand) CommandFactory.newFireAllRules("executed-rules");

commands.add(fireAllRulesCommand);

BatchExecutionCommand batchExecutionCommand = CommandFactory.newBatchExecution(commands, "ksession1");

camelContext.start();

ProducerTemplate template = camelContext.createProducerTemplate();
ExecutionResults response = (ExecutionResults) template.requestBody("direct:test-session1", batchExecutionCommand);
}
catch (Exception e)
{
fail(e.getMessage());
}
}

@Test
public void testWithSpringAndCamel()
{
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
applicationContext.start();

CamelContext camelContext = (CamelContext) applicationContext
.getBean("camelContext");

@SuppressWarnings("rawtypes")
List<Command> commands = new ArrayList<Command>();

FireAllRulesCommand fireAllRulesCommand = (FireAllRulesCommand) CommandFactory
.newFireAllRules("executed-rules");

commands.add(fireAllRulesCommand);

BatchExecutionCommand batchExecutionCommand = CommandFactory
.newBatchExecution(commands, "ksession1");

try
{
camelContext.start();

ProducerTemplate template = camelContext.createProducerTemplate();
ExecutionResults response = (ExecutionResults) template
.requestBody("direct:test-session2", batchExecutionCommand);

applicationContext.stop();

applicationContext.close();
}
catch (Exception e)
{
fail(e.getMessage());
}

}

}
[/code]

SimpleRuleRunnerTest.java

Run the Tests

Run the JUnit Tests and you should see the following output:

[code language=”java”]
Woohoo – Rules are running!
Woohoo – Rules are running!
Woohoo – Rules are running!
Woohoo – Rules are running!
[/code]

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.