Chapter 1. Apache Camel Integration

1.1. Camel

Camel provides a light weight bus framework for getting information
into and out of Drools.

Drools introduces two elements to make easy integration.

Drools Policy

Augments any JAXB or XStream data loaders. For JAXB it adds drools
related paths ot the contextpath, for XStream it adds custom converters
and aliases for Drools classes. It also handles setting the ClassLoader
to the targeted ksession.

Drools Endpoint

Executes the payload against the specified drools session

Drools can be configured like any normal camel component, but notice
the policy that wraps the drools related segments. This will route all
payloads to ksession1

It is possible to not specify the session in the drools endpoint uri,
and instead "multiplex" based on an attribute or header. In this example the
policy will check either the header field "DroolsLookup" for the named
session to execute and if that isn't specified it'll check the "lookup"
attribute on the incoming payload. It then attempts to "lookup" the session
from the execution-node context and execute against it.

2.1.2. Event Listeners

The drools-spring module allows you to configure these listeners
to KnowledgeSessions using XML tags. These tags have identical names as
the actual listener interfaces i.e.,
<drools:agendaEventListener....>,
<drools:workingMemoryEventListener....> and
<drools:processEventListener....>.

drools-spring provides features to define the listeners as
standalone (individual) listeners and also to define them as a
group.

2.1.2.1.3. Empty Tag : Declaration with no 'ref' and without a nested
bean

When a listener is defined without a reference to a
implementing bean and does not contain a nested bean,
<drools:workingMemoryEventListener/> the
underlying implementation adds the Debug version of the listener
defined in the API.

2.1.2.1.5. Defining multiple listeners of the same type

<drools:resourceid="resource1"type="DRL"source="classpath:org/drools/container/spring/testSpring.drl"/><drools:kbaseid="kbase1"><drools:resources><drools:resourceref="resource1"/></drools:resources></drools:kbase><beanid="mock-wm-listener"class="org.drools.container.spring.MockWorkingMemoryEventListener"/><drools:ksessionid="statefulWithMultipleSameType"type="stateful"kbase="kbase1"node="node1"><!-- 2 different implementations of the same listener attached to one ksession --><drools:workingMemoryEventListener><beanclass="org.drools.container.spring.ConsoleWorkingMemoryEventListener"/></drools:workingMemoryEventListener><drools:workingMemoryEventListenerref="mock-wm-listener"/></drools:ksession>

2.1.2.2. Defining a Group of listeners:

drools-spring allows for grouping of listeners. This is
particularly useful when you define a set of listeners and want to
attach them to multiple sessions. The grouping feature is also very
useful, when we define a set of listeners for 'testing' and then want
to switch them for 'production' use.

2.1.2.2.1. Attributes:

Table 2.7.

Attribute

Required

Description

ID

yes

Unique identifier

2.1.2.2.2. Nested Elements:

drools:agendaEventListener...

drools:workingMemoryEventListener...

drools:processEventListener...

Note

The above mentioned child elements can be declared in any order. Only one declaration of each type is allowed in a group.

A TaskService instance is dependent on two other bean types:
a drools SystemEventListener bean as well as a
TaskSessionSpringFactoryImpl bean. The
TaskSessionSpringFactoryImpl bean is howerver not
injected into the TaskService bean because this would cause a
circular dependency. To solve this problem, when the TaskService
bean is injected into the TaskSessionSpringFactoryImpl bean,
the setter method used secretly injects the TaskSessionSpringFactoryImpl
instance back into the TaskService bean and initializes the
TaskService bean as well.

The TaskSessionSpringFactoryImpl bean is responsible for
creating all the internal instances in human task that deal with transactions
and persistence context management. Besides a TaskService instance,
this bean also requires a transaction manager and a persistence context to
be injected. Specifically, it requires an instance of a
HumanTaskSpringTransactionManager bean (as a transaction manager)
and an instance of a SharedEntityManagerBean bean (as a persistence
context instance).

We also use some of the standard Spring beans in order to configure
persistence: there's a bean to hold the EntityManagerFactory
instance as well as the SharedEntityManagerBean instance. The
SharedEntityManagerBean provides a shared, thread-safe proxy
for the actual EntityManager.

The HumanTaskSpringTransactionManager bean serves as a
wrapper around the Spring transaction manager, in this case the
JpaTransactionManager. An instance of a
JpaTransactionManager bean is also instantiated because of this.

Example 2.11. Configuring Human Task with Spring

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:jbpm="http://drools.org/schema/drools-spring"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://drools.org/schema/drools-spring org/drools/container/spring/drools-spring-1.2.0.xsd"><!-- persistence & transactions--><beanid="htEmf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><propertyname="persistenceUnitName"value="org.jbpm.task"/></bean><beanid="htEm"class="org.springframework.orm.jpa.support.SharedEntityManagerBean"><propertyname="entityManagerFactory"ref="htEmf"/></bean><beanid="jpaTxMgr"class="org.springframework.orm.jpa.JpaTransactionManager"><propertyname="entityManagerFactory"ref="htEmf"/><!-- this must be true if using the SharedEntityManagerBean, and false otherwise --><propertyname="nestedTransactionAllowed"value="true"/></bean><beanid="htTxMgr"class="org.drools.container.spring.beans.persistence.HumanTaskSpringTransactionManager"><constructor-argref="jpaTxMgr"/></bean><!-- human-task beans --><beanid="systemEventListener"class="org.drools.SystemEventListenerFactory"factory-method="getSystemEventListener"/><beanid="taskService"class="org.jbpm.task.service.TaskService"><propertyname="systemEventListener"ref="systemEventListener"/></bean><beanid="springTaskSessionFactory"class="org.jbpm.task.service.persistence.TaskSessionSpringFactoryImpl"init-method="initialize"depends-on="taskService"><!-- if using the SharedEntityManagerBean, make sure to enable nested transactions --><propertyname="entityManager"ref="htEm"/><propertyname="transactionManager"ref="htTxMgr"/><propertyname="useJTA"value="false"/><propertyname="taskService"ref="taskService"/></bean></beans>

When using the SharedEntityManagerBean instance, it's important
to configure the Spring transaction manager to use nested transactions. This is
because the SharedEntityManagerBean is a transactional
persistence context and will close the persistence context after every operation.
However, the human task server needs to be able to access (persisted) entities
after operations. Nested transactions allow us to still have access to entities
that otherwise would have been detached and are no longer accessible, especially
when using an ORM framework that uses lazy-initialization of entities.

Also, while the TaskSessionSpringFactoryImpl bean takes
an “useJTA” parameter, at the moment, JTA transactions with
Spring have not yet been fully tested.

Chapter 3. Drools Camel Server

3.1. Introduction

The drools camel server (drools-camel-server) module is a war which you
can deploy to execute KnowledgeBases remotely for any sort of client
application. This is not limited to JVM application clients, but any
technology that can use HTTP, through a REST interface. This version of the
execution server supports stateless and stateful sessions in a native
way.

3.2. Deployment

Drools Camel Server is a war file, which can be deployed in a application
server (such as JBoss AS). As the service is stateless, it is possible to
have have as many of these services deployed as you need to serve the client
load. Deploy on JBoss AS 4.x / Tomcat 6.x works out-of-the-box, instead some
external dependencies must be added and the configuration must be changed to
be deployed in JBoss AS 5

3.3. Configuration

Inside the war file you will find a few XML configuration
files.

beans.xml

Skeleton xml that imports knowledge-services.xml and
camel-server.xml

camel-server.xml

Configures CXF endpoints with Camel Routes

Came Routes pipeline messages to various configured knowledge
services

knowledge-services.xml

Various Knowledge Bases and Sessions

camel-client.xml

Sample camel client showing how to send and receive a
message

Used by "out of the box" test.jsp

3.3.1. REST/Camel Services configuration

The next step is configure the services that are going to be exposed
through drools-server. You can modify this configuration in
camel-server.xml file.

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:cxf="http://camel.apache.org/schema/cxf"xmlns:jaxrs="http://cxf.apache.org/jaxrs"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"><importresource="classpath:META-INF/cxf/cxf.xml"/><importresource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/><importresource="classpath:META-INF/cxf/cxf-servlet.xml"/><!-- ! If you are running on JBoss you will need to copy a camel-jboss.jar into the lib and set this ClassLoader configuration ! http://camel.apache.org/camel-jboss.html ! <bean id="jbossResolver" class="org.apache.camel.jboss.JBossPackageScanClassResolver"/> --><!-- ! Define the server end point. ! Copy and paste this element, changing id and the address, to expose services on different urls. ! Different Camel routes can handle different end point paths. --><cxf:rsServerid="rsServer"address="/kservice/rest"serviceClass="org.drools.jax.rs.CommandExecutorImpl"><cxf:providers><beanclass="org.drools.jax.rs.CommandMessageBodyReader"/></cxf:providers></cxf:rsServer><!-- Leave this, as it's needed to make Camel "drools" aware --><beanid="droolsPolicy"class="org.drools.camel.component.DroolsPolicy"/><camelContextid="camel"xmlns="http://camel.apache.org/schema/spring"><!-- ! Routes incoming messages from end point id="rsServer". ! Example route unmarshals the messages with xstream and executes against ksession1. ! Copy and paste this element, changing marshallers and the 'to' uri, to target different sessions, as needed. !--><route><fromuri="cxfrs://bean://rsServer"/><policyref="droolsPolicy"><unmarshalref="xstream"/><touri="drools:node1/ksession1"/><marshalref="xstream"/></policy></route></camelContext></beans>

3.3.1.1. RESTful service endpoint creation

In the next xml snippet code we are creating a RESTful (JAX-RS)
endpoint bound to /kservice/rest address and using
org.drools.jax.rs.CommandExecutorImpl as the service implementer. This
class is only used to instantiate the service endpoint because all the
internal implementation is managed by Camel, and you can see in the
source file that the exposed execute service must be never
called.

Also a JAX-RS Provider is provided to determine if the message
transported can be processed in this service endpoint.

Ideally this configuration doesn't need to be modified, at least
the Service Class and the JAX-RS Provider, but you can add more
endpoints associated to different addresses to use them in other
Camel Routes.

After all this initial configuration, you can start config your
own Knowledge Services.

3.3.1.2. Camel Drools Policy & Context creation

DroolsPolicy is used to add Drools support in Camel, basically
what it does is to add interceptors into the camel route to create Camel
Processors on the fly and modify the internal navigation route. If you
want to have SOAP support you need to create your custom Drools Policy,
but it's going to be added in the next release.

But you don’t need to know more internal details, only instantiate
this bean:

The next is create the camel route that will have the
responsibility to execute the commands sent through JAX-RS. Basically we
create a route definition associated with the JAX-RS definition as the
data input, the camel policy to be used and inside the “execution route”
or ProcessorDefinitions. As you can see, we set XStream as the
marshaller/unmarshaller and the drools execution route definition

The execution-node is a context or registered kbases and
ksessions, here kbase1 and ksession1 are planed in the node1 context.
The kbase itself consists of 2 knowledge definitions, a drl and an xsd.
The Spring documentation contains a lot more information on configuring
these knowledge services.

3.3.1.4. Test

With drools-server war unzipped you should be able to see a
test.jsp and run it. This example just executes a simple "echo" type
application. It sends a message to the rule server that pre-appends the
word "echo" to the front and sends it back. By default the message is
"Hello World", different messages can be passed using the url parameter
msg - test.jsp?msg="My Custom Message".

Under the hood the jsp invokes the Test.java class, this then
calls out to Camel which is where the meet happens. The camel-client.xml
defines the client with just a few lines of xml:

"direct://kservice" is just a named hook, allowing java to grab a
reference and push data into it. In this example the data is already in
xml, so we don't need to add any DataFormat's to do the marshalling. The
DroolsPolicy adds some smarts to the route and you'll see it used on the
server side too. If JAXB or XStream were used, it would inject custom
paths and converters, it can also set the ClassLoader too on the server
side, on the client side it automatically unwraps the Response
object.

The rule itself can be found here: test.drl. Notice the type
Message is declared part of the drl and is thus not present on the
Classpath.

4.1.2. JSON

4.1.3. JAXB

There are two options for using JAXB, you can define your model in
an XSD file or you can have a POJO model. In both cases you have to
declare your model inside JAXBContext, and in order to do that you need to
use Drools Helper classes. Once you have the JAXBContext you need to
create the Unmarshaller/Marshaller as needed.

4.1.3.1. Using an XSD file to define the model

With your model defined in a XSD file you need to have a
KnowledgeBase that has your XSD model added as a resource.

To do this, the XSD file must be added as a XSD ResourceType into
the KnowledgeBuilder. Finally you can create the JAXBContext using the
KnowledgeBase created with the KnowledgeBuilder

Chapter 5. OSGi Integration

OSGi is a dynamic module system for declarative services. So what does
that mean? Each jar in OSGi is called a bundle and has it's own ClassLoader.
Each bundle specifies the packages it exports (makes publicly available) and
which packages it imports (external dependencies). OSGi will use this
information to wire the ClassLoaders of different bundles together; the key
distinction is you don't specify what bundle you depend on, or have a single
monolithic classpath, instead you specify your package import and version
and OSGi attempts to satisfy this from available bundles.

It also supports side by side versioning, so you can have multiple
versions of a bundle installed and it'll wire up the correct one. Further to
this Bundles can register services for other bundles to use. These services
need initialisation, which can cause ordering problems - how do you make
sure you don't consume a service before its registered? OSGi has a number of
features to help with service composition and ordering. The two main ones
are the programmatic ServiceTracker and the xml based Declarative Services.
There are also other projects that help with this; Spring DM, iPOJO,
Gravity.

Each of the Drools factories is now also available as a FactoryService
interface. You can either have OSGi inject those into a pojo, or retrieve
them yourself from OSGi.

The TestComponent will only be activated when all of the referenced
services are available and injected into the pojo. You'll also notice the
"target" attribute for the KnowledgeBuilderFactoryService. The reason for
this is that OSGi DS has no built in way to declaratively say which optional
services must be present to satisfy your component. As a work around I made
any Drools service that has optional services set a property if/when the
optional service is available. Filters can then be applied, via the target
attribute, to make sure the Service is in a desired state before consuming
it. And that is pretty much it :)

Chapter 6. JMX monitoring with RHQ/JON

6.1. Introduction

The Drools engine supports runtime monitoring through JMX standard
MBeans. These MBeans expose configuration and metrics data, from live
knowledge bases and sessions, to internal details like rule execution times.
Any JMX compatible console can be used to access that data. This chapter
details how to use RHQ/JON to do it, but similar steps can be used for any
other console.

6.1.1. Enabling JMX monitoring in a Drools application

To enable JMX monitoring in a Drools application, it is necessary to
enable remote monitoring in the JVM. There are several tutorials on how to
do that in the internet, but we recommend that you check the documentation
of your specific JVM. Using the Oracle/Sun JVM, it can be as simple as
running the engine with a few command line system properties.

For instance, to enable remote monitoring on port 19988 with
disabled authentication (should be only used for tests/demos, as in
production authentication should be enabled), just run the application
with the following command line parameters: