JBoss.orgCommunity Documentation
In this section we will explain the drools namespace.
Execution nodes are a context to register ksessions and kbases against for lookup.
Table 2.2.
Attribute | Description | Required |
---|---|---|
id | Bean's id is the name to be reference from other beans. | Yes, but can be omitted when this tag is nested. |
source | The path to the file containing the actual resource. | Yes |
type | Type of the Resource as is defined in class
ResourceType . | No, default to DRL |
When configuring a decision table resource you can nest a <drools:decisiontable-conf> tag to configure the resource.
Table 2.3.
Attribute | Description | Required |
---|---|---|
input-type | Decision Table input type: XLS or CSV | No |
worksheet-name | The worksheet name to be used in the when using an XLS | No |
Example 2.1. resource definition example
<drools:resource source="classpath:org/drools/IntegrationExampleTest.xls"
type="DTABLE">
<drools:decisiontable-conf input-type="XLS" worksheet-name="Tables_2" />
</drools:resource>
Table 2.4.
Attribute | Description | Required |
---|---|---|
id | Bean's id is the name to be referenced from other beans. | Yes |
node | Execution-Node context to register the kbase with | no |
A Knowledge Base has a 0..n resources. Has two nested elements, resources and configurations. Those resources can be inner elements or references, using the "ref" attribute.
Example 2.2. kbase definition example
<drools:kbase id="kbase1" node="node1">
<drools:resources>
<drools:resource source="classpath:org/drools/spring/IntegrationExampleTest.xls"
type="DTABLE">
<drools:decisiontable-conf input-type="XLS" worksheet-name="Table_2" />
</drools:resource>
<drools:resource ref="resource1"/>
<drools:resource source="classpath:org/drools/container/spring/model.xsd" />
</drools:resources>
<drools:configuration>
<drools:mbeans enabled="true" />
<drools:accumulate-functions>
<drools:accumulate-function name="func1" ref="func1Instance" />
<drools:accumulate-function name="func1" ref="func2Instance" />
</drools:accumulate-functions>
</drools:configuration>
</drools:kbase>
advanced-process-rule-integration
enabled = true : false
multithread
enabled = true : false
max-threads = 1..n
mbeans
enabled = true : false
event-processing-mode
mode = STREAM : CLOUD
accumulate-functions
accumulate-function 0..n
name = String
ref = String
evaluators
evaluator 0..n
name = String
ref = String
assert-behavior
mode = IDENTITY : EQUALITY
Figure 2.1. Knowledge Base Configuration Options
Table 2.5.
Attribute | Description | Required |
---|---|---|
id | Bean's id is the name to be referenced from other beans. | Yes |
type | is the session stateful or stateless? | Yes |
name | No; defaults to id when omitted. | |
node | Execution-Node context to register the ksession with | no |
listeners | Specifies the reference to the event listeners group (see 'Defining a Group of listeners' section below). | no |
Example 2.3. ksession definition example
<drools:ksession id="ksession1" type="stateless"
name="stateless1" kbase="kbase1"/>
<drools:ksession id="ksession2" type="stateful" kbase="kbase1"/>
<drools:ksession id="ksession3" type="stateful" kbase="kbase2>
<drools:batch>
<drools:insert-object ref="person" />
<drools:set-global identifier="list1">
<bean class="java.util.ArrayList" />
</drools:set-global>
<drools:startProcess process-id="start fire">
</drools:batch>
<drools:configurations>
<drools:keep-reference enabled="false" />
<drools:clock-type type="PSEUDO" />
</drools:configurations>
</drools:ksession>
keep-reference
enabled = true : false
clock-type
type = REALTIME : PSEUDO
jpa-persistence
transaction-manager
ref = String
entity-manager-factory
ref = String
Figure 2.2. Knowledge Session Configuration Options
insert-object
ref = String (optional)
Anonymous bean
set-global
identifier = String (required)
reg = String (optiona)
Anonymous bean
fire-all-rules
max : n
fire-until-halt
start-process
parameter
identifier = String (required)
ref = String (optional)
Anonymous bean
signal-event
ref = String (optional)
event-type = String (required)
process-instance-id =n (optional)
Figure 2.3. Initialization Batch Commands
Example 2.4. ksession JPA configuration example
<drools:kstore id="kstore" /> <!-- provides KnowledgeStoreService implementation -->
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="ds" />
<property name="persistenceUnitName" value="org.drools.persistence.jpa.local" />
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<drools:ksession id="jpaSingleSessionCommandService" type="stateful" kbase="kbProcessWorkItems">
<drools:configuration>
<drools:jpa-persistence>
<drools:transaction-manager ref="txManager" />
<drools:entity-manager-factory ref="myEmf" />
</drools:jpa-persistence>
</drools:configuration>
</drools:ksession>
Drools supports adding 3 types of listeners to KnowledgeSessions - AgendaListener, WorkingMemoryListener, ProcessEventListener
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.
Example 2.5. Listener configuration example - using a bean:ref.
<drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource ref="resource1"/>
</drools:resources>
</drools:kbase>
<bean id="mock-agenda-listener" class="org.drools.container.spring.MockAgendaEventListener" />
<bean id="mock-wm-listener" class="org.drools.container.spring.MockWorkingMemoryEventListener" />
<bean id="mock-process-listener" class="org.drools.container.spring.MockProcessEventListener" />
<drools:ksession id="statefulSession" type="stateful" kbase="kbase1" node="node1">
<drools:agendaEventListener ref="mock-agenda-listener"/>
<drools:processEventListener ref="mock-process-listener"/>
<drools:workingMemoryEventListener ref="mock-wm-listener"/>
</drools:ksession>
bean
class = String
name = String (optional)
Example 2.6. Listener configuration example - using nested bean.
<drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource ref="resource1"/>
</drools:resources>
</drools:kbase>
<drools:ksession id="statefulWithNestedBean" type="stateful" kbase="kbase1" node="node1">
<drools:agendaEventListener>
<bean class="org.drools.container.spring.MockAgendaEventListener"/>
</drools:agendaEventListener>
<drools:workingMemoryEventListener>
<bean class="org.drools.container.spring.MockWorkingMemoryEventListener"/>
</drools:workingMemoryEventListener>
<drools:processEventListener>
<bean class="org.drools.container.spring.MockProcessEventListener"/>
</drools:processEventListener>
</drools:ksession>
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.
The debug listeners print the corresponding Event toString message to System.err.
Example 2.7. Listener configuration example - defaulting to the debug versions provided by the Knowledge-API .
<drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource ref="resource1"/>
</drools:resources>
</drools:kbase>
<drools:ksession id="statefulWithDefault" type="stateful" kbase="kbase1" node="node1">
<drools:agendaEventListener/> <!-- attaches the org.drools.core.event.rule.DebugAgendaEventListener -->
<drools:workingMemoryEventListener/> <!-- attaches the org.drools.core.event.rule.DebugWorkingMemoryEventListener -->
<drools:processEventListener/> <!-- attaches the org.drools.core.event.DebugProcessEventListener -->
</drools:ksession>
The drools-spring module allows you to mix and match the different declarative styles within the same KnowledgeSession. The below sample provides more clarity.
Example 2.8. Listener configuration example - mix and match of 'ref'/nested-bean/empty styles.
<drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource ref="resource1"/>
</drools:resources>
</drools:kbase>
<bean id="mock-agenda-listener" class="org.drools.container.spring.MockAgendaEventListener" />
<drools:ksession id="statefulWithMixAndMatchOfStyles" type="stateful" kbase="kbase1" node="node1">
<drools:workingMemoryEventListener>
<bean class="org.drools.container.spring.MockWorkingMemoryEventListener"/>
</drools:workingMemoryEventListener>
<drools:agendaEventListener ref="mock-agenda-listener"/>
<drools:processEventListener/> <!-- attaches the org.drools.core.event.DebugProcessEventListener -->
</drools:ksession>
It is also valid to define multiple beans of the same event listener types for a KnowledgeSession.
Example 2.9. Listener configuration example - multiple listeners of the same type.
<drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource ref="resource1"/>
</drools:resources>
</drools:kbase>
<bean id="mock-wm-listener" class="org.drools.container.spring.MockWorkingMemoryEventListener" />
<drools:ksession id="statefulWithMultipleSameType" type="stateful" kbase="kbase1" node="node1">
<!-- 2 different implementations of the same listener attached to one ksession -->
<drools:workingMemoryEventListener>
<bean class="org.drools.container.spring.ConsoleWorkingMemoryEventListener"/>
</drools:workingMemoryEventListener>
<drools:workingMemoryEventListener ref="mock-wm-listener"/>
</drools:ksession>
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.
drools:agendaEventListener...
drools:workingMemoryEventListener...
drools:processEventListener...
Example 2.10. Group of listeners - example
<drools:resource id="resource1" type="DRL" source="classpath:org/drools/container/spring/testSpring.drl"/>
<drools:kbase id="kbase1">
<drools:resources>
<drools:resource ref="resource1"/>
</drools:resources>
</drools:kbase>
<bean id="mock-wm-listener" class="org.drools.container.spring.MockWorkingMemoryEventListener" />
<drools:ksession id="statelessWithGroupedListeners" type="stateless" kbase="kbase1" node="node1" listeners="
mockListeners "/>
<drools:eventListeners id="mockListeners">
<drools:agendaEventListener ref="mock-agenda-listener"/>
<drools:processEventListener ref="mock-process-listener"/>
<drools:workingMemoryEventListener ref="mock-wm-listener"/>
</drools:eventListeners>
<drools:eventListeners id="debugListeners">
<drools:agendaEventListener/>
<drools:processEventListener/>
<drools:workingMemoryEventListener/>
</drools:eventListeners>
This chapter describes the infrastructure used when configuring a human task server with Spring as well as a little bit about the infrastructure used when doing this.
The jBPM human task server can be configured to use Spring persistence. Example 2.11, “Configuring Human Task with Spring” is an example of this which uses local transactions and Spring's thread-safe EntityManager proxy.
The following diagram shows the dependency graph used in Example 2.11, “Configuring Human Task with Spring”.
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"?>
<beans xmlns="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-->
<bean id="htEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="org.jbpm.task" />
</bean>
<bean id="htEm" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="htEmf"/>
</bean>
<bean id="jpaTxMgr" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="htEmf" />
<!-- this must be true if using the SharedEntityManagerBean, and false otherwise -->
<property name="nestedTransactionAllowed" value="true"/>
</bean>
<bean id="htTxMgr" class="org.drools.container.spring.beans.persistence.HumanTaskSpringTransactionManager">
<constructor-arg ref="jpaTxMgr" />
</bean>
<!-- human-task beans -->
<bean id="systemEventListener" class="org.drools.SystemEventListenerFactory" factory-method="getSystemEventListener" />
<bean id="taskService" class="org.jbpm.task.service.TaskService" >
<property name="systemEventListener" ref="systemEventListener" />
</bean>
<bean id="springTaskSessionFactory" class="org.jbpm.task.service.persistence.TaskSessionSpringFactoryImpl"
init-method="initialize" depends-on="taskService" >
<!-- if using the SharedEntityManagerBean, make sure to enable nested transactions -->
<property name="entityManager" ref="htEm" />
<property name="transactionManager" ref="htTxMgr" />
<property name="useJTA" value="false" />
<property name="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.