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:

<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>

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:

package rules.skills421.examples

rule "always true"
dialect "mvel"
when
then
	System.out.println("Woohoo - Rules are running!");
end

rules.drl

Create the ApplicationContext.xml

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

<?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>

applicationContext.xml

Create drools-context.xml

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

<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>

drools-context.xml

Create the JUnit Tests as follows

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

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());
		}

	}

}

SimpleRuleRunnerTest.java

Run the Tests

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

Woohoo - Rules are running!
Woohoo - Rules are running!
Woohoo - Rules are running!
Woohoo - Rules are running!
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s