JBoss.org Community Documentation

- Prev
- Next

## Chapter 11. Integration with Spring

## 11.1. Important Changes for Drools 6.0

Drools Spring integration has undergone a complete makeover inline with the changes for Drools 6.0. The following are some of the major changes

- The recommended prefix for the Drools Spring has changed from 'drools:' to 'kie:'

- New Top Level Tags in 6.0

  - kie:kmodule

  - kie:import (from version 6.2)

  - kie:releaseId (from version 6.2)

- The following tags are no longer valid as top level tags.

  - kie:kbase - A child of the kie:kmodule tag.

  - kie:ksession - A child of the kie:kbase tag.

- Removed Tags from previous versions Drools 5.x

  - drools:resources

  - drools:resource

  - drools:grid

  - drools:grid-node

## 11.2. Integration with Drools Expert

In this section we will explain the kie namespace.

### 11.2.1. KieModule

The <kie:kmodule> defines a collection of KieBase and associated KieSession's. The kmodule tag has one MANDATORY parameter 'id'.

Table 11.1. Sample

Attribute | Description | Required
--- | --- | ---
id | Bean's id is the name to be referenced from other beans. Standard Spring ID semantics apply. | Yes

A kmodule tag can contain only the following tags as children.

- kie:kbase

Refer to the documentation of kmodule.xml in the Drools Expert documentation for detailed explanation of the need for kmodule.

### 11.2.2. KieBase

#### 11.2.2.1. <kie:kbase>'s parameters as attributes:

Table 11.2. Sample

Attribute | Description | Required
--- | --- | ---
name | Name of the KieBase | Yes
packages | Comma separated list of resource packages to be included in this kbase | No
includes | kbase names to be included. All resources from the corresponding kbase are included in this kbase. | No
default | Default kbase | No
default | Boolean (TRUE/FALSE). Default kbase, if not provided, it is assumed to be FALSE | No
scope | prototype | singleton. If not provided assumed to be singleton (default) | No
eventProcessingMode | Event Processing Mode. Valid options are STREAM, CLOUD | No
equalsBehavior | Valid options are IDENTITY, EQUALITY | No
declarativeAgenda | Valid options are enabled, disabled, true, false | No

#### 11.2.2.2. A kbase tag can contain only the following tags as children.

- kie:ksession

#### 11.2.2.3. <kie:kbase>'s definition example

A kmodule can contain multiple (1..n) kbase elements.

Example 11.1. kbase definition example

    <kie:kmodule id="sample_module">
       <kie:kbase name="kbase1" packages="org.drools.spring.sample">
         ...
       </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

#### 11.2.2.4. Spring Bean Scope (for KieBase and KieSession)

When defining a KieBase or a KieSession, you have the option of declaring a scope for that bean. For example, To force Spring to produce a new bean instance each time one is needed, you should declare the bean's scope attribute to be 'prototype'. Similar way if you want Spring to return the same bean instance each time one is needed, you should declare the bean's scope attribute to be 'singleton'.

### 11.2.3. IMPORTANT NOTE

For proper initialization of the kmodule objects (kbase/ksession), it is mandatory for a bean of type `org.kie.spring.KModuleBeanFactoryPostProcessor` or `org.kie.spring.annotations.KModuleAnnotationPostProcessor` be defined.

Example 11.2. Regular kie-spring post processorbean definition

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

Example 11.3. kie-spring post processorbean definition when annotations are used

    <bean id="kiePostProcessor"
              class="org.kie.spring.annotations.KModuleAnnotationPostProcessor"/>

## Note

Without the org.kie.spring.KModuleBeanFactoryPostProcessor or org.kie.spring.annotations.KModuleAnnotationPostProcessor bean definition, the kie-spring integration will fail to work.

### 11.2.4. KieSessions

<kie:ksession> element defines KieSessions. The same tag is used to define both Stateful (org.kie.api.runtime.KieSession) and Stateless (org.kie.api.runtime.StatelessKieSession) sessions.

#### 11.2.4.1. <kie:ksession>'s parameters as attributes:

Table 11.3. Sample

Attribute | Description | Required
--- | --- | ---
name | ksession's name. | Yes
type | is the session stateful or stateless?. If this attribute is empty or missing, the session is assumed to be of type Stateful. | No
default | Is this the default session? | no
scope | prototype | singleton. If not provided assumed to be singleton (default) | no
clockType | REALTIME or PSEUDO | no
listeners-ref | Specifies the reference to the event listeners group (see 'Defining a Group of listeners' section below). | no

Example 11.4. ksession definition example

    <kie:kmodule id="sample-kmodule">
      <kie:kbase name="drl_kiesample3" packages="drl_kiesample3">
        <kie:ksession name="ksession1" type="stateless"/>
        <kie:ksession name="ksession2"/>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

#### 11.2.4.2. Spring Bean Scope (for KieBase and KieSession)

When defining a KieBase or a KieSession, you have the option of declaring a scope for that bean. For example, To force Spring to produce a new bean instance each time one is needed, you should declare the bean's scope attribute to be 'prototype'. Similar way if you want Spring to return the same bean instance each time one is needed, you should declare the bean's scope attribute to be 'singleton'.

### 11.2.5. Kie:ReleaseId

#### 11.2.5.1. <kie:releaseId>'s parameters as attributes:

Table 11.4. Sample

Attribute | Description | Required
--- | --- | ---
id | Bean's id is the name to be referenced from other beans. Standard Spring ID semantics apply. | Yes
groupId | groupId from Maven GAV | Yes
artifactId | artifactId from Maven GAV | Yes
version | version from Maven GAV | Yes

Example 11.5. releaseId definition example

    <kie:releaseId id="beanId" groupId="org.kie.spring"
                artifactId="named-artifactId" version="1.0.0-SNAPSHOT"/>

### 11.2.6. Kie:Import

Starting with version 6.2, kie-spring allows for importing of kie objects from kjars found on the classpath. Two modes of importing the kie objects are currently supported.

Table 11.5.

Attribute | Description | Required
--- | --- | ---
releaseId | Reference to a Bean ID. Standard Spring ID semantics apply. | No
enableScanner | Enable Scanner. This attribute is used only if 'releaseId' is specified. | No
scannerInterval | Scanning Interval in milli seconds. This attribute is used only if 'releaseId' is specified. | No

#### 11.2.6.1. Global Import

The import tag will force the automatic scan of all the jars on the classpath, initialize the Kie Objects (Kbase/KSessions) and import these objects into the spring context.

Figure 11.1. Global Import

    <kie:import />

#### 11.2.6.2. Specific Import - ReleaseId

Using the releaseId-ref attribute on the import tag will initialize the specific Kie Objects (Kbase/KSessions) and import these objects into the spring context.

Figure 11.2. Import Kie Objects using a releaseId

    <kie:import releaseId-ref="namedKieSession"/>
    <kie:releaseId id="namedKieSession" groupId="org.drools"
                artifactId="named-kiesession" version="6.3.0-SNAPSHOT"/>

Kie Scanning feature can be enabled for KieBase's imported with a specific releaseId. This feature is currently not available for global imports.

Figure 11.3. Import Kie Objects using a releaseId - Enable Scanner

    <kie:import releaseId-ref="namedKieSession"
                enableScanner="true" scannerInterval="1000"/>

    <kie:releaseId id="namedKieSession" groupId="org.drools"
                artifactId="named-kiesession" version="6.3.0-SNAPSHOT"/>

If the scanner is defined and enabled, an implicit KieScanner object is created and inserted into the spring context. It can be retrived from the spring context.

Figure 11.4. Retriving the KieScanner from Spring Context

    // the implicit name would be releaseId#scanner
    KieScanner releaseIdScanner = context.getBean("namedKieSession#scanner", KieScanner.class);
    releaseIdScanner.scanNow();

## Note

kie-ci must be available on the classpath for the releaseId importing feature to work.

### 11.2.7. Annotations

@KContainer, @KBase and @KSession all support an optional 'name' attribute. Spring typically does "get" when it injects, all injections receive the same instance for the same set of annotations. the 'name' annotation forces a unique instance for each name, although all instance for that name will be identity equals.

#### 11.2.7.1. @KReleaseId

Used to bind an instance to a specific version of a KieModule. If kie-ci is on the classpath this will resolve dependencies automatically, downloading from remote repositories.

#### 11.2.7.2. @KContainer

Figure 11.5. Injects Classpath KieContainer

    @KContainer
    private KieContainer kContainer;

Figure 11.6. Injects KieContainer for Dynamic KieModule

    @KContainer
    @KReleaseId(groupId = "jar1", artifactId = "art1", version = "1.1")
    private KieContainer kContainer;

Figure 11.7. Injects named KieContainer for Dynamic KieModule

    @KContainer(name = "kc1")
    @KReleaseId(groupId = "jar1", artifactId = "art1", version = "1.1")
    private KieContainer kContainer;

#### 11.2.7.3. @KBase

The default argument, if given, maps to the value attribute and specifies the name of the KieBase from the spring xml file.

Figure 11.8. Injects the Default KieBase from the Classpath KieContainer

    @KBase
    private KieBase kbase;

Figure 11.9. Injects the Default KieBase from a Dynamic KieModule

    @KBase
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieBase kbase;

Figure 11.10. Side by side version loading for 'jar1.KBase1' KieBase

    @KBase("kbase1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieBase kbase1v10;

    @KBase("kbase1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.1")
    private KieBase kbase1v11;

Figure 11.11. Side by side version loading for 'jar1.ksession1' KieSession

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieSession ksession11kb2;

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.1")
    private KieSession ksession11kb2;

#### 11.2.7.4. @KSession for KieSession

The default argument, if given, maps to the value attribute and specifies the name of the KieSession from the kmodule.xml or spring xml file

Figure 11.12. Injects the Default KieSession from the Classpath KieContainer

    @KSession
    private KieSession ksession;

Figure 11.13. Injects the Default KieSession from a Dynamic KieModule

    @KSession
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieSession ksession;

Figure 11.14. Side by side version loading for 'jar1.KBase1' KieBase

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieSession ksessionv10;

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.1")
    private KieSession ksessionv11;

Figure 11.15. Use 'name' attribute to force new Instance for 'jar1.KBase1' KieSession

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieSession ksession1ks1

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private KieSession ksession1ks2

#### 11.2.7.5. @KSession for StatelessKieSession

The default argument, if given, maps to the value attribute and specifies the name of the KieSession from the kmodule.xml or spring xml file.

Figure 11.16. Injects the Default StatelessKieSession from the Classpath KieContainer

    @KSession
    private StatelessKieSession ksession;

Figure 11.17. Injects the Default StatelessKieSession from a Dynamic KieModule

    @KSession
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private StatelessKieSession ksession;

Figure 11.18. Side by side version loading for 'jar1.KBase1' KieBase

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", rtifactId = "art1", version = "1.0")
    private StatelessKieSession ksessionv10;

    @KSession("ksession1")
    @KReleaseId( groupId = "jar1", rtifactId = "art1", version = "1.1")
    private StatelessKieSession ksessionv11;

Figure 11.19.

    @KSession(value="ksession1", name="ks1")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private StatelessKieSession ksession1ks1

    @KSession(value="ksession1", name="ks2")
    @KReleaseId( groupId = "jar1", artifactId = "art1", version = "1.0")
    private StatelessKieSession ksession1ks2

#### 11.2.7.6. IMPORTANT NOTE

When annotations are used, For proper initialization of the kmodule objects (kbase/ksession), it is mandatory for either a bean of type `org.kie.spring.annotations.KModuleAnnotationPostProcessor` be defined

or spring component-scan be enabled. One of the code snippets as shown below is required.

Example 11.6. kie-spring annotations post processor bean definition

    <bean id="kiePostProcessor"
                class="org.kie.spring.annotations.KModuleAnnotationPostProcessor"/>

Example 11.7. kie-spring annotations - Component Scanning

    <context:component-scan base-package="org.kie.spring.annotations"/>

## Note

The post processor is different when annotations are used.

### 11.2.8. Event Listeners

Drools supports adding 3 types of listeners to KieSessions - AgendaListener, WorkingMemoryListener, ProcessEventListener

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

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

#### 11.2.8.1. Defining Stand alone Listeners:

##### 11.2.8.1.1. Attributes:

Table 11.6. Sample

Attribute | Required | Description
--- | --- | ---
ref | No | A reference to another declared bean.

Example 11.8. Listener configuration example - using a bean:ref.

    <bean id="mock-agenda-listener" class="mocks.MockAgendaEventListener"/>
    <bean id="mock-rr-listener" class="mocks.MockRuleRuntimeEventListener"/>
    <bean id="mock-process-listener" class="mocks.MockProcessEventListener"/>

    <kie:kmodule id="listeners_kmodule">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ksession2">
          <kie:agendaEventListener ref="mock-agenda-listener"/>
          <kie:processEventListener ref="mock-process-listener"/>
          <kie:ruleRuntimeEventListener ref="mock-rr-listener"/>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

##### 11.2.8.1.2. Nested Elements:

- bean

  - class = String

  - name = String (optional)

Example 11.9. Listener configuration example - using nested bean.

    <kie:kmodule id="listeners_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
       <kie:ksession name="ksession1">
    	  <kie:agendaEventListener>
          <bean class="mocks.MockAgendaEventListener"/>
          </kie:agendaEventListener>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

##### 11.2.8.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:ruleRuntimeEventListener/> 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 11.10. Listener configuration example - defaulting to the debug versions provided by the Knowledge-API .

    <bean id="mock-agenda-listener" class="mocks.MockAgendaEventListener"/>
    <bean id="mock-rr-listener" class="mocks.MockRuleRuntimeEventListener"/>
    <bean id="mock-process-listener" class="mocks.MockProcessEventListener"/>

    <kie:kmodule id="listeners_module">
     <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ksession2">
          <kie:agendaEventListener />
          <kie:processEventListener />
          <kie:ruleRuntimeEventListener />
        </kie:ksession>
     </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

##### 11.2.8.1.4. Mix and Match of different declaration styles

The drools-spring module allows you to mix and match the different declarative styles within the same KieSession. The below sample provides more clarity.

Example 11.11. Listener configuration example - mix and match of 'ref'/nested-bean/empty styles.

    <bean id="mock-agenda-listener" class="mocks.MockAgendaEventListener"/>
    <bean id="mock-rr-listener" class="mocks.MockRuleRuntimeEventListener"/>
    <bean id="mock-process-listener" class="mocks.MockProcessEventListener"/>

    <kie:kmodule id="listeners_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ksession1">
          <kie:agendaEventListener>
              <bean class="org.kie.spring.mocks.MockAgendaEventListener"/>
          </kie:agendaEventListener>
        </kie:ksession>
        <kie:ksession name="ksession2">
          <kie:agendaEventListener ref="mock-agenda-listener"/>
          <kie:processEventListener ref="mock-process-listener"/>
          <kie:ruleRuntimeEventListener ref="mock-rr-listener"/>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

##### 11.2.8.1.5. Defining multiple listeners of the same type

It is also valid to define multiple beans of the same event listener types for a KieSession.

Example 11.12. Listener configuration example - multiple listeners of the same type.

    <bean id="mock-agenda-listener" class="mocks.MockAgendaEventListener"/>

    <kie:kmodule id="listeners_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ksession1">
          <kie:agendaEventListener ref="mock-agenda-listener"/>
          <kie:agendaEventListener>
              <bean class="org.kie.spring.mocks.MockAgendaEventListener"/>
          </kie:agendaEventListener>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

#### 11.2.8.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.

##### 11.2.8.2.1. Attributes:

Table 11.7. Sample

Attribute | Required | Description
--- | --- | ---
ID | yes | Unique identifier

##### 11.2.8.2.2. Nested Elements:

- kie:agendaEventListener...

- kie:ruleRuntimeEventListener...

- kie:processEventListener...

## Note

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

##### 11.2.8.2.3. Example:

Example 11.13. Group of listeners - example

    <bean id="mock-agenda-listener" class="mocks.MockAgendaEventListener"/>
    <bean id="mock-rr-listener" class="mocks.MockRuleRuntimeEventListener"/>
    <bean id="mock-process-listener" class="mocks.MockProcessEventListener"/>

    <kie:kmodule id="listeners_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="statelessWithGroupedListeners" type="stateless"
                 listeners-ref="debugListeners"/>
      </kie:kbase>
    </kie:kmodule>

      <kie:eventListeners id="debugListeners">
      <kie:agendaEventListener ref="mock-agenda-listener"/>
      <kie:processEventListener ref="mock-process-listener"/>
      <kie:ruleRuntimeEventListener ref="mock-rr-listener"/>
    </kie:eventListeners>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

### 11.2.9. Loggers

Drools supports adding 2 types of loggers to KieSessions - ConsoleLogger, FileLogger.

The kie-spring module allows you to configure these loggers to KieSessions using XML tags. These tags have identical names as the actual logger interfaces i.e., <kie:consoleLogger....> and <kie:fileLogger....>.

#### 11.2.9.1. Defining a console logger:

A console logger can be attached to a KieSession by using the <kie:consoleLogger/> tag. This tag has no attributes and must be present directly under a <kie:ksession....> element.

Example 11.14. Defining a console logger - example

    <kie:kmodule id="loggers_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ConsoleLogger-statefulSession" type="stateful">
          <kie:consoleLogger/>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

#### 11.2.9.2. Defining a file logger:

A file logger can be attached to a KieSession by using the <kie:fileLogger/> tag. This tag has the following attributes and must be present directly under a <kie:ksession....> element.

Table 11.8. Sample

Attribute | Required | Description
--- | --- | ---
ID | yes | Unique identifier
file | yes | Path to the actual file on the disk
threaded | no | Defaults to false. Valid values are 'true'or 'false'
interval | no | Integer. Specifies the interval for flushing the contents from memory to the disk.

Example 11.15. Defining a file logger - example

    <kie:kmodule id="loggers_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ConsoleLogger-statefulSession" type="stateful">
          <kie:fileLogger id="fl_logger" file="#{ systemProperties['java.io.tmpdir'] }/log1"/>
          <kie:fileLogger id="tfl_logger" file="#{ systemProperties['java.io.tmpdir'] }/log2"
                              threaded="true" interval="5"/>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

##### 11.2.9.2.1. Closing a FileLogger

To prevent leaks, it is advised to close the <kie:fileLogger ...> programmatically.

    LoggerAdaptor adaptor = (LoggerAdaptor) context.getBean("fl_logger");
    adaptor.close();

### 11.2.10. Defining Batch Commands

A <kie:batch> element can be used to define a set of batch commands for a given ksession.This tag has no attributes and must be present directly under a <kie:ksession....> element. The commands supported are

Figure 11.20. Initialization Batch Commands

- insert-object

  - ref = String (optional)

  - Anonymous bean

- set-global

  - identifier = String (required)

  - reg = String (optional)

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

Example 11.16. Batch commands - example

    <kie:kmodule id="batch_commands_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ksessionForCommands" type="stateful">
          <kie:batch>
            <kie:insert-object ref="person2"/>
            <kie:set-global identifier="persons" ref="personsList"/>
            <kie:fire-all-rules max="10"/>
          </kie:batch>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

### 11.2.11. Persistence

Figure 11.21. Persistence Configuration Options

- jpa-persistence

  - transaction-manager

    - ref = String

  - entity-manager-factory

    - ref = String

Example 11.17. ksession JPA configuration example

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

    <kie:kmodule id="persistence_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="jpaSingleSessionCommandService">
          <kie:configuration>
             <kie:jpa-persistence>
               <kie:transaction-manager ref="txManager"/>
               <kie:entity-manager-factory ref="myEmf"/>
             </kie:jpa-persistence>
          </kie:configuration>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
              class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

### 11.2.12. Leveraging Other Spring Features

This section provides details on leveraging other standard spring features when integrating with Drools Expert.

#### 11.2.12.1. Using Spring Expressions (Spel)

    <kie:kmodule id="batch_commands_module">
      <kie:kbase name="drl_kiesample" packages="#{packageRepository.packages}">
        <kie:ksession name="ksessionForCommands" type="stateful"/>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
          class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

    <bean id="packageRepository" class="sample.package.class.PackageRepo">
      <property name="packages" value="drl_kiesample3">
    </bean>

    <kie:kmodule id="loggers_module">
      <kie:kbase name="drl_kiesample" packages="drl_kiesample">
        <kie:ksession name="ConsoleLogger-statefulSession" type="stateful">
          <kie:fileLogger id="fl" file="#{ systemProperties['java.io.tmpdir'] }/log1"/>
          <kie:fileLogger id="tfl" file="#{ systemProperties['java.io.tmpdir'] }/log2"
                threaded="true" interval="5"/>
        </kie:ksession>
      </kie:kbase>
    </kie:kmodule>

    <bean id="kiePostProcessor"
                class="org.kie.spring.KModuleBeanFactoryPostProcessor"/>

#### 11.2.12.2. Using Spring Profiles

Spring 3.1 introduces a new profile attribute to the beans element of the spring-beans schema. This attribute acts as a switch when enabling and disabling profiles in different environments. One potential use of this attribute can be to have the same kbase defined with debug loggers in 'dev' environment and without loggers in 'prod' environment.

The below code snippet illustrates the concept of 'profiles'.

    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:kie="http://drools.org/schema/kie-spring"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://drools.org/schema/kie-spring http://drools.org/schema/kie-spring.xsd">
      <beans profile="development">
        <kie:kmodule id="test-kmodule">
          <kie:kbase name="drl_kiesample" packages="drl_kiesample">
            <kie:ksession name="ksession1" type="stateless">
                <kie:consoleLogger />
            </kie:ksession>
          </kie:kbase>
        </kie:kmodule>
        ...
      </beans>

      <beans profile="production">
        <kie:kmodule id="test-kmodule">
          <kie:kbase name="drl_kiesample" packages="drl_kiesample">
            <kie:ksession name="ksession1" type="stateless"/>
          </kie:kbase>
        </kie:kmodule>
        ...
      </beans>
    </beans>

As shown above, the Spring XML contains the definition of the profiles. While loading the ApplicationContext you have to tell Spring which profile you’re loading.

There are several ways of selecting your profile and the most useful is by using the "spring.profiles.active" system property.

    System.setProperty("spring.profiles.active", "development");
    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

Obviously, it is not a good practice to hard code things as shown above and the recommended practice is to keep the system properties definitions independent of the application.

    -Dspring.profiles.active="development"

The profiles can also be loaded and enabled programmtically

    ...
    GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("beans.xml");
    ConfigurableEnvironment env = ctx.getEnvironment();
    env.setActiveProfiles("development");
    ctx.refresh();
    ...

## 11.3. Integration with jBPM Human Task

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.

### 11.3.1. How to configure Spring with jBPM Human task

The jBPM human task server can be configured to use Spring persistence. Example 11.18, “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 11.18, “Configuring Human Task with Spring”.

Figure 11.22. Spring Human Task integration injection dependencies

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

- PrevChapter 10. CDI
- Up
- Home
- NextChapter 12. Apache Camel Integration