4 Drools JBPM Integration
4 Drools JBPM Integration
Version 5.5.0.Beta1
by The JBoss Drools team [http://www.jboss.org/drools/team.html]
......................................................................................................................................... v 1. Apache Camel Integration ........................................................................................... 1 1.1. Camel ................................................................................................................ 1 2. Spring Integration ........................................................................................................ 5 2.1. Integration with Drools Expert .............................................................................. 5 2.1.1. Define a Resource ................................................................................... 5 2.1.2. Event Listeners ...................................................................................... 10 2.2. Integration with jBPM Human Task .................................................................... 16 2.2.1. How to configure Spring with jBPM Human task ....................................... 16 3. Drools Camel Server ................................................................................................. 19 3.1. Introduction ....................................................................................................... 19 3.2. Deployment ...................................................................................................... 19 3.3. Configuration .................................................................................................... 19 3.3.1. REST/Camel Services configuration ........................................................ 19 4. Drools Commands ..................................................................................................... 25 4.1. API ................................................................................................................... 25 4.1.1. XStream ................................................................................................ 25 4.1.2. JSON .................................................................................................... 4.1.3. JAXB ..................................................................................................... 4.2. Commands supported ....................................................................................... 4.2.1. BatchExecutionCommand ....................................................................... 4.2.2. InsertObjectCommand ............................................................................ 4.2.3. RetractCommand ................................................................................... 4.2.4. ModifyCommand .................................................................................... 4.2.5. GetObjectCommand ............................................................................... 4.2.6. InsertElementsCommand ........................................................................ 4.2.7. FireAllRulesCommand ............................................................................ 4.2.8. StartProcessCommand ........................................................................... 4.2.9. SignalEventCommand ............................................................................ 4.2.10. CompleteWorkItemCommand ................................................................ 4.2.11. AbortWorkItemCommand ...................................................................... 4.2.12. QueryCommand ................................................................................... 4.2.13. SetGlobalCommand .............................................................................. 4.2.14. GetGlobalCommand ............................................................................. 4.2.15. GetObjectsCommand ............................................................................ 5. OSGi Integration ........................................................................................................ 6. JMX monitoring with RHQ/JON ................................................................................. 6.1. Introduction ....................................................................................................... 6.1.1. Enabling JMX monitoring in a Drools application ...................................... 6.1.2. Installing and running the RHQ/JON plugin .............................................. 25 25 26 28 29 31 32 33 34 36 38 39 40 41 42 43 45 46 49 53 53 53 53
iii
iv
vi
Chapter 1.
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
<bean id="droolsPolicy" class="org.drools.camel.component.DroolsPolicy" /> <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="cxfrs://bean://rsServer"/> <policy ref="droolsPolicy"> <unmarshal ref="xstream" /> <to uri="drools:node1/ksession1" /> <marshal ref="xstream" /> </policy> </route>
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.
<bean id="droolsPolicy" class="org.drools.camel.component.DroolsPolicy" /> <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="cxfrs://bean://rsServer"/> <policy ref="droolsPolicy"> <unmarshal ref="xstream" /> <to uri="drools:node1" /> <marshal ref="xstream" /> </policy> </route>
Example 1.3. Java Code to execute against Route from a Spring and Camel Context
public class MyTest extends CamelSpringTestSupport { @Override protected AbstractXmlApplicationContext createApplicationContext() { return new ClassPathXmlApplicationContext("org/drools/camel/component/ CxfRsSpring.xml"); } public void test1() throws Exception { String cmd = ""; cmd += "<batch-execution lookup=\"ksession1\">\n"; cmd += " <insert out-identifier=\"salaboy\">\n"; cmd += " <org.drools.pipeline.camel.Person>\n"; cmd += " <name>salaboy</name>\n"; cmd += " </org.drools.pipeline.camel.Person>\n"; cmd += " </insert>\n"; cmd += " <fire-all-rules/>\n"; cmd += "</batch-execution>\n"; Object object this.context.createProducerTemplate().requestBody("direct://client", cmd); System.out.println( object ); } =
The following urls show sample script examples for jaxb, xstream and json marshalling using: http://fisheye.jboss.org/browse/JBossRules/trunk/drools-camel/src/test/resources/org/drools/ camel/component/jaxb.mvt?r=HEAD
Camel
Chapter 2.
Required Yes, but can be omitted when this tag is nested. Yes No, default to DRL
Table 2.3.
Attribute input-type worksheet-name Description Decision Table input type: XLS or CSV The worksheet name to be used in the when using an XLS No No Required
<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>
Define a Resource
<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
<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>
Define a Resource
</drools:ksession>
keep-reference enabled = true : false clock-type type = REALTIME : PSEUDO jpa-persistence transaction-manager ref = String entity-manager-factory ref = String
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) 9
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
/>
<!--
provides
KnowledgeStoreService
<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" <drools:configuration> <drools:jpa-persistence> <drools:transaction-manager ref="txManager" /> <drools:entity-manager-factory ref="myEmf" /> </drools:jpa-persistence> </drools:configuration> </drools:ksession>
kbase="kbProcessWorkItems
10
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.
type="DRL"
source="classpath:org/drools/
<drools:kbase id="kbase1"> <drools:resources> <drools:resource ref="resource1"/> </drools:resources> </drools:kbase> <bean id="mock-agendalistener" class="org.drools.container.spring.MockAgendaEventListener" /> <bean id="mock-wmlistener" class="org.drools.container.spring.MockWorkingMemoryEventListener" /> <bean id="mock-processlistener" 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>
11
type="DRL"
source="classpath:org/drools/
<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>
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. 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 .
type="DRL"
source="classpath:org/drools/
12
Event Listeners
<drools:resources> <drools:resource ref="resource1"/> </drools:resources> </drools:kbase> <drools:ksession id="statefulWithDefault" type="stateful" kbase="kbase1" node="node1"> <drools:agendaEventListener/> <!-org.drools.event.rule.DebugAgendaEventListener --> <drools:workingMemoryEventListener/> <!-org.drools.event.rule.DebugWorkingMemoryEventListener --> <drools:processEventListener/> <!-org.drools.event.DebugProcessEventListener --> </drools:ksession> attaches attaches attaches the the the
Example 2.8. Listener configuration example - mix and match of 'ref'/nestedbean/empty styles.
type="DRL"
source="classpath:org/drools/
<drools:kbase id="kbase1"> <drools:resources> <drools:resource ref="resource1"/> </drools:resources> </drools:kbase> <bean id="mock-agendalistener" class="org.drools.container.spring.MockAgendaEventListener" />
<drools:ksession id="statefulWithMixAndMatchOfStyles" type="stateful" kbase="kbase1" node="no <drools:workingMemoryEventListener> <bean class="org.drools.container.spring.MockWorkingMemoryEventListener"/> </drools:workingMemoryEventListener> <drools:agendaEventListener ref="mock-agenda-listener"/> <drools:processEventListener/> org.drools.event.DebugProcessEventListener --> <!-attaches the
13
</drools:ksession>
Example 2.9. Listener configuration example - multiple listeners of the same type.
type="DRL"
source="classpath:org/drools/
<drools:kbase id="kbase1"> <drools:resources> <drools:resource ref="resource1"/> </drools:resources> </drools:kbase> <bean id="mock-wmlistener" 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>
14
Event Listeners
Note
The above mentioned child elements can be declared in any order. Only one declaration of each type is allowed in a group.
type="DRL"
source="classpath:org/drools/
<drools:kbase id="kbase1"> <drools:resources> <drools:resource ref="resource1"/> </drools:resources> </drools:kbase> <bean id="mock-wmlistener" class="org.drools.container.spring.MockWorkingMemoryEventListener" /> <drools:ksession id="statelessWithGroupedListeners" type="stateless" node="node1" kbase="kbase1" 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>
15
instance
is
dependent
on
two
other
bean
types:
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
16
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.
<?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/droolsspring-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.HumanTaskSpringTransa <constructor-arg ref="jpaTxMgr" /> </bean> <!-- human-task beans --> <bean id="systemEventListener" class="org.drools.SystemEventListenerFactory" factorymethod="getSystemEventListener" />
17
<bean id="springTaskSessionFactory" class="org.jbpm.task.service.persistence.TaskSessionSprin 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 lazyinitialization of entities. Also, while the TaskSessionSpringFactoryImpl bean takes an useJTA parameter, at the moment, JTA transactions with Spring have not yet been fully tested.
18
Chapter 3.
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
19
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/camelcxf.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"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml"/> <import resource="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:rsServer id="rsServer" address="/kservice/rest" serviceClass="org.drools.jax.rs.CommandExecutorImpl"> <cxf:providers> <bean class="org.drools.jax.rs.CommandMessageBodyReader"/> </cxf:providers> </cxf:rsServer> <!-- Leave this, as it's needed to make Camel "drools" aware --> <bean id="droolsPolicy" class="org.drools.camel.component.DroolsPolicy" /> <camelContext id="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. !-->
20
<route> <from uri="cxfrs://bean://rsServer"/> <policy ref="droolsPolicy"> <unmarshal ref="xstream" /> <to uri="drools:node1/ksession1" /> <marshal ref="xstream" /> </policy> </route> </camelContext> </beans>
Ideally this configuration doesn't need to be modified, at least the Service Class and the JAXRS 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.
21
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
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="cxfrs://bean://rsServer"/> <policy ref="droolsPolicy"> <unmarshal ref="xstream" /> <to uri="drools:node1/ksession1" /> <marshal ref="xstream" /> </policy> </route> </camelContext>
1. Execution Node identifier that is registered in the CamelContext 2. Knowledge Session identifier that was registered in the Execution Node with identifier {1} Both parameters are configured in knowledge-services.xml file.
<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" xsi:schemaLocation="http://www.springframework.org/schema/beans http:// www.springframework.org/schema/beans/spring-beans-2.0.xsd http://drools.org/schema/drools-spring http:// drools.org/schema/drools-spring.xsd"> <drools:execution-node id="node1" />
22
<drools:kbase id="kbase1" node="node1"> <drools:resources> <drools:resource type="XSD" source="classpath:model.xsd"/> <drools:resource type="DRL" source="classpath:test.drl"/> </drools:resources> </drools:kbase> <drools:ksession id="ksession1" type="stateless" kbase="kbase1" node="node1"/> </beans>
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:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="direct://kservice"/> <policy ref="droolsPolicy"> <to uri="cxfrs://http://localhost:8080/drools-server-app/kservice/ rest"/> </policy> </route> </camelContext>
"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.
23
rule "echo" dialect "mvel" when $m : Message(); then $m.text = "echo:" + $m.text; end
24
Chapter 4.
4.1.1. XStream
To use the XStream commands marshaller you need to use the DroolsHelperProvider to obtain an XStream instance. We need to use this because it has the commands converters registered. Marshalling BatchExecutionHelperProviderImpl.newXStreamMarshaller().toXML(command); Unmarshalling BatchExecutionHelperProviderImpl.newXStreamMarshaller().fromXML(xml)
4.1.2. JSON
JSON API to marshalling/unmarshalling is similar to XStream API: Marshalling BatchExecutionHelper.newJSonMarshaller().toXML(command); Unmarshalling BatchExecutionHelper.newJSonMarshaller().fromXML(xml)
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.
25
Options xjcOpts = new Options(); xjcOpts.setSchemaLanguage(Language.XMLSCHEMA); JaxbConfiguration jaxbConfiguration = KnowledgeBuilderFactory.newJaxbConfiguration( xjcOpts, "x kbuilder.add(ResourceFactory.newClassPathResource("person.xsd", getClass()), ResourceType.XSD, KnowledgeBase kbase = kbuilder.newKnowledgeBase(); List<String> classesName = new ArrayList<String>(); classesName.add("org.drools.test.Person");
1. classNames: A List with the canonical name of the classes that you want to use in the marshalling/unmarshalling process. 2. properties: JAXB custom properties
List<String> classNames = new ArrayList<String>(); classNames.add("org.drools.test.Person"); JAXBContext jaxbContext = DroolsJaxbHelperProviderImpl.createDroolsJaxbContext(classNames, null Marshaller marshaller = jaxbContext.createMarshaller();
26
Commands supported
ModifyCommand GetObjectCommand InsertElementsCommand FireAllRulesCommand StartProcessCommand SignalEventCommand CompleteWorkItemCommand AbortWorkItemCommand QueryCommand SetGlobalCommand GetGlobalCommand GetObjectsCommand
Note
In the next snippets code we are going to use a POJO org.drools.test.Person that has two fields name: String age: Integer
Note
In the next examples, to marshall the commands we have used the next snippet codes: XStream
JSON
27
JAXB
Marshaller marshaller = jaxbContext.createMarshaller(); StringWriter xml = new StringWriter(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(command, xml);
4.2.1. BatchExecutionCommand
Description: The command that contains a list of commands, which will be sent and executed. Attributes
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); InsertObjectCommand insertObjectCommand = new InsertObjectCommand(new Person("john", 25)); FireAllRulesCommand fireAllRulesCommand = new FireAllRulesCommand(); command.getCommands().add(insertObjectCommand); command.getCommands().add(fireAllRulesCommand);
28
InsertObjectCommand
JSON
{"batch-execution":{"lookup":"ksession1","commands":[{"insert":{"object": {"org.drools.test.Person":{"name":"john","age":25}}}},{"fire-allrules":""}]}}
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <insert> <object xsi:type="person" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"> <age>25</age> <name>john</name> </object> </insert> <fire-all-rules max="-1"/> </batch-execution>
4.2.2. InsertObjectCommand
Id to identify the FactHandle false created in the object insertion and added to the execution results
29
Name returnObject
Description Boolean to establish if the false object must be returned in the execution results. Default value: true
required
false
Command insertObjectCommand = CommandFactory.newInsert(new Person("john", 25), "john", false, cmds.add( insertObjectCommand ); BatchExecutionCommand command = CommandFactory.createBatchExecution(cmds, "ksession1" );
<batch-execution lookup="ksession1"> <insert out-identifier="john" object="false"> <org.drools.test.Person> <name>john</name> <age>25</age> </org.drools.test.Person> </insert> </batch-execution>
entry-point="my
stream"
return-
JSON
JAXB
30
RetractCommand
<insert out-identifier="john" entry-point="my stream" > <object xsi:type="person" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"> <age>25</age> <name>john</name> </object> </insert> </batch-execution>
4.2.3. RetractCommand
Command creation: we have two options, with the same output result: 1. Create the Fact Handle from a string
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); RetractCommand retractCommand = new RetractCommand(); retractCommand.setFactHandleFromString("123:234:345:456:567"); command.getCommands().add(retractCommand);
2. Set the Fact Handle that you received when the object was inserted
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); RetractCommand retractCommand = new RetractCommand(factHandle); command.getCommands().add(retractCommand);
31
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"retract":{"facthandle":"0:234:345:456:567"}}}}
JAXB
4.2.4. ModifyCommand
Description: Allows you to modify a previously inserted object in the knowledge session. Attributes
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); ModifyCommand modifyCommand = new ModifyCommand(); modifyCommand.setFactHandleFromString("123:234:345:456:567"); List<Setter> setters = new ArrayList<Setter>(); setters.add(new SetterImpl("age", "30")); modifyCommand.setSetters(setters);
32
GetObjectCommand
command.getCommands().add(modifyCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"modify":{"facthandle":"0:234:345:456:567","setters":{"accessor":"age","value":30}}}}}
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <modify fact-handle="0:234:345:456:567"> <set value="30" accessor="age"/> </modify> </batch-execution>
4.2.5. GetObjectCommand
Description: Used to get an object from a knowledge session Attributes
33
Name
required
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); GetObjectCommand getObjectCommand = new GetObjectCommand(); getObjectCommand.setFactHandleFromString("123:234:345:456:567"); getObjectCommand.setOutIdentifier("john"); command.getCommands().add(getObjectCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"get-object":{"facthandle":"0:234:345:456:567","out-identifier":"john"}}}}
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <get-object out-identifier="john" fact-handle="0:234:345:456:567"/> </batch-execution>
4.2.6. InsertElementsCommand
34
InsertElementsCommand
Attributes
List<Command> cmds = ArrayList<Command>(); List<Object> objects = new ArrayList<Object>(); objects.add(new Person("john", 25)); objects.add(new Person("sarah", 35)); Command insertElementsCommand = CommandFactory.newInsertElements( objects ); cmds.add( insertElementsCommand ); BatchExecutionCommand command = CommandFactory.createBatchExecution(cmds, "ksession1" );
<batch-execution lookup="ksession1"> <insert-elements> <org.drools.test.Person> <name>john</name> <age>25</age> </org.drools.test.Person> <org.drools.test.Person> <name>sarah</name> <age>35</age>
35
JSON
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <insert-elements return-objects="true"> <list> <element xsi:type="person" xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance"> <age>25</age> <name>john</name> </element> <element xsi:type="person" xmlns:xsi="http://www.w3.org/2001/ XMLSchema-instance"> <age>35</age> <name>sarah</name> </element> <list> </insert-elements> </batch-execution>
4.2.7. FireAllRulesCommand
36
FireAllRulesCommand
Name
required
outIdentifier
Add the number of rules false activations fired on the execution results Allow the rules execution false using an Agenda Filter
agendaFilter
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); FireAllRulesCommand fireAllRulesCommand = new FireAllRulesCommand(); fireAllRulesCommand.setMax(10); fireAllRulesCommand.setOutIdentifier("firedActivations"); command.getCommands().add(fireAllRulesCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"fire-all-rules": {"max":10,"out-identifier":"firedActivations"}}}}
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <fire-all-rules out-identifier="firedActivations" max="10"/> </batch-execution>
37
4.2.8. StartProcessCommand
Description: Allows you to start a process using the ID. Also you can pass parameters and initial data to be inserted. Attributes
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); StartProcessCommand startProcessCommand = new StartProcessCommand(); startProcessCommand.setProcessId("org.drools.task.processOne"); command.getCommands().add(startProcessCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"start-process": {"process-id":"org.drools.task.processOne"}}}}
JAXB
38
SignalEventCommand
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <start-process processId="org.drools.task.processOne"> <parameter/> </start-process> </batch-execution>
4.2.9. SignalEventCommand
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); SignalEventCommand signalEventCommand = new SignalEventCommand(); signalEventCommand.setProcessInstanceId(1001); signalEventCommand.setEventType("start"); signalEventCommand.setEvent(new Person("john", 25)); command.getCommands().add(signalEventCommand);
<batch-execution lookup="ksession1"> <signal-event process-instance-id="1001" event-type="start"> <org.drools.pipeline.camel.Person> <name>john</name> <age>25</age> </org.drools.pipeline.camel.Person> </signal-event>
39
</batch-execution>
JSON
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <signal-event event-type="start" process-instance-id="1001"> <event xsi:type="person" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"> <age>25</age> <name>john</name> </event> </signal-event> </batch-execution>
4.2.10. CompleteWorkItemCommand
40
AbortWorkItemCommand
completeWorkItemCommand.setWorkItemId(1001); command.getCommands().add(completeWorkItemCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"complete-work-item": {"id":1001}}}}
JAXB
4.2.11. AbortWorkItemCommand
The
same
as
Command creation
41
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); AbortWorkItemCommand abortWorkItemCommand = new AbortWorkItemCommand(); abortWorkItemCommand.setWorkItemId(1001); command.getCommands().add(abortWorkItemCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"abort-work-item": {"id":1001}}}}
JAXB
4.2.12. QueryCommand
42
SetGlobalCommand
Name outIdentifier
Description The identifier of the query false results. The query results are going to be added in the execution results with this identifier
required
arguments
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); QueryCommand queryCommand = new QueryCommand(); queryCommand.setName("persons"); queryCommand.setOutIdentifier("persons"); command.getCommands().add(queryCommand);
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"query":{"outidentifier":"persons","name":"persons"}}}}
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <query name="persons" out-identifier="persons"/> </batch-execution>
4.2.13. SetGlobalCommand
43
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); SetGlobalCommand setGlobalCommand = new SetGlobalCommand(); setGlobalCommand.setIdentifier("helper"); setGlobalCommand.setObject(new Person("kyle", 30)); setGlobalCommand.setOut(true); setGlobalCommand.setOutIdentifier("output"); command.getCommands().add(setGlobalCommand);
<batch-execution lookup="ksession1"> <set-global identifier="helper" out-identifier="output"> <org.drools.test.Person> <name>kyle</name> <age>30</age> </org.drools.test.Person> </set-global> </batch-execution>
JSON
44
GetGlobalCommand
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <set-global out="true" out-identifier="output" identifier="helper"> <object xsi:type="person" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"> <age>30</age> <name>kyle</name> </object> </set-global> </batch-execution>
4.2.14. GetGlobalCommand
Description: Allows you to get a global previously defined. Attributes
Command creation
BatchExecutionCommand command = new BatchExecutionCommand(); command.setLookup("ksession1"); GetGlobalCommand getGlobalCommand = new GetGlobalCommand(); getGlobalCommand.setIdentifier("helper"); getGlobalCommand.setOutIdentifier("helperOutput"); command.getCommands().add(getGlobalCommand);
45
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"get-global": {"identifier":"helper","out-identifier":"helperOutput"}}}}
JAXB
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <batch-execution lookup="ksession1"> <get-global out-identifier="helperOutput" identifier="helper"/> </batch-execution>
4.2.15. GetObjectsCommand
Description: Returns all the objects from the current session as a Collection. Attributes
Command creation
46
GetObjectsCommand
JSON
{"batch-execution":{"lookup":"ksession1","commands":{"get-objects":{"outidentifier":"objects"}}}}
JAXB
47
48
Chapter 5.
49
unbind="unsetKnowledgeBaseFactoryService" interface="org.drools.KnowledgeBaseFactoryService" /> <reference bind="setResourceFactoryService" unbind="unsetResourceFactoryService" interface="org.drools.io.ResourceFactoryService" /> <reference bind="setKnowledgeBuilderFactoryService" unbind="unsetKnowledgeBuilderFactoryService" interface="org.drools.builder.KnowledgeBuilderFactoryService" target="(org.drools.compiler.DecisionTableProvider=true)" /> </scr:component>
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 :)
ServiceReference serviceRef = bundleContext.getServiceReference( ServiceRegistry.class.getName() ); ServiceRegistry registry = (ServiceRegistry) bundleContext.getService( serviceRef ); KnowledgeBuilderFactoryService knowledgeBuilderFactoryService registry.get( KnowledgeBuilderFactoryService.class ); KnowledgeBaseFactoryService knowledgeBaseFactoryService registry.get( KnowledgeBaseFactoryService.class ); ResourceFactoryService resourceFactoryService registry.get( ResourceFactoryService.class ); KnowledgeBuilderConfiguration kbConf knowledgeBuilderFactoryService.newKnowledgeBuilderConfiguration( null, getClass().getClassLoader() ); KnowledgeBuilder kbuilder knowledgeBuilderFactoryService.newKnowledgeBuilder( kbConf ); ResourceFactoryService resource = resourceFactoryService; kbuilder.add( resource.newByteArrayResource( string.getBytes() ), = =
= =
50
ResourceType.DRL ); if ( kbuilder.hasErrors() ) { System.out.println( kbuilder.getErrors() ); throw new RuntimeException( kbuilder.getErrors().toString() ); } KnowledgeBaseConfiguration kbaseConf knowledgeBaseFactoryService.newKnowledgeBaseConfiguration( null, getClass().getClassLoader() ); KnowledgeBase kbase = knowledgeBaseFactoryService.newKnowledgeBase( kbaseConf ); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); =
ServiceReference serviceRef = bundleContext.getServiceReference( ServiceRegistry.class.getName() ); ServiceRegistry registry = (ServiceRegistry) bundleContext.getService( serviceRef ); KnowledgeBuilderFactoryService knowledgeBuilderFactoryService registry.get( KnowledgeBuilderFactoryService.class ); KnowledgeBaseFactoryService knowledgeBaseFactoryService registry.get( KnowledgeBaseFactoryService.class ); ResourceFactoryService resourceFactoryService registry.get( ResourceFactoryService.class ); KnowledgeBaseConfiguration kbaseConf knowledgeBaseFactoryService.newKnowledgeBaseConfiguration( null, getClass().getClassLoader() ); KnowledgeBuilderConfiguration kbConf knowledgeBuilderFactoryService.newKnowledgeBuilderConfiguration( null, = = = =
getClass().getClassLoader() ); KnowledgeBuilder kbuilder = knowledgeBuilderFactoryService.newKnowledgeBuilder( kbConf ); kbuilder.add( resourceFactoryService.newClassPathResource( "changeset1Test.xml", Dummy.class ), ResourceType.CHANGE_SET ); kbaseConf = knowledgeBaseFactoryService.newKnowledgeBaseConfiguration( null,
51
getClass().getClassLoader() ); KnowledgeBase kbase = knowledgeBaseFactoryService.newKnowledgeBase( kbaseConf ); kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() ); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
52
Chapter 6.
The second step is to enable the Drools MBeans. As any Drools configuration, that can be done by setting a system property, or adding the property to a configuration file, or using the API. To enable it in the command line, use:
-Ddrools.mbeans=enabled
53
1. Download the JON server and agent. 2. Download Drools plugin included in the "Drools and jBPM tools" bundle (http://www.jboss.org/ drools/downloads.html). 3. Install server, agent, and the plugin. 4. Check that the server is running, agent is running and plugin is installed. 5. Execute the drools application [see details in the previous section]. 6. On the agent console, type "discovery" command for the agent to find the drools application, which it will find on port 19988. 7. On JON console, click on auto-discovery queue. 8. Select the JMX Server process that is showing there, running on port 19988. 9. Click import. 10.Click on Resources->servers. 11.Click on the JMX Server. 12.Under JMXServer on the left hand side, you have Drools Service.
54