Objective
In this post we are going to create a Drools Stateful Knowledge Session and bind it to a JNDI address.
We will then use Camel to fire all the rules in that session.
This is useful where we wish to have multiple Knowledge Sessions on multiple servers.
This example uses the Drools Grid – the main idea behind Drools Grid is to provide a simple API to be able to interact and create remote and distributed services in multiple machines.
Create the Project
File -> New -> Maven Project
Create a Simple Project
Group Id: com.skills421.drools.examples
Artifact Id: DroolsCamel
Finish
Edit pom.xml
Edit the pom.xml as follows:
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.skills421.drools.examples</groupId> <artifactId>DroolsCamel</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <drools.version>5.6.0.Final</drools.version> <commons-version>1.1.3</commons-version> <camel.version>2.4.0</camel.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 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> <!-- 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>
pom.xml
Create a Simple Rule
In src/main/resources create the folder structure rules/skills421/examples.
In the examples folder create the rules.drl as follows:
package rules.skills421.examples rule "always true" dialect "mvel" when then System.out.println("Woohoo - Rules are running!"); end
rules.drl
Create the RuleRunner
Ideally, I should be creating a JUnit Test, but I want to get something running very quickly here, all in one file, so in src/main/java create the RuleRunner class as follows:
package com.skills421.drools.examples; 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; public class RuleRunner { private StatefulKnowledgeSession createKnowledgeSession() { 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(); return kbase.newStatefulKnowledgeSession(); } private Context createContext(StatefulKnowledgeSession ksession) throws Exception { 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); return context; } private CamelContext createCamelContext(Context context) throws Exception { 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); return camelContext; } public static void main(String[] args) throws Exception { RuleRunner runner = new RuleRunner(); StatefulKnowledgeSession ksession = runner.createKnowledgeSession(); Context context = runner.createContext(ksession); CamelContext camelContext = runner.createCamelContext(context); @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); } }
RuleRunner.java
Run the RuleRunner
If you run RuleRunner you should see the following output:
Woohoo - Rules are running!