[jboss-svn-commits] JBL Code SVN: r34270 - in labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US: Chapter-API and 4 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Wed Jul 28 20:09:29 EDT 2010
Author: KrisVerlaenen
Date: 2010-07-28 20:09:29 -0400 (Wed, 28 Jul 2010)
New Revision: 34270
Added:
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Installer/
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Installer/Chapter-Installer.xml
Modified:
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-API/Chapter-API.xml
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-BPMN2/Chapter-BPMN2.xml
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Console/Chapter-Console.xml
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Flow/Chapter-RuleFlow.xml
labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/master.xml
Log:
- updating Drools Flow docs
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-API/Chapter-API.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-API/Chapter-API.xml 2010-07-28 21:11:40 UTC (rev 34269)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-API/Chapter-API.xml 2010-07-29 00:09:29 UTC (rev 34270)
@@ -1,144 +1,140 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter version="5.0"
- xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
- xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
-
- <title>Drools Flow API</title>
-
- <section>
- <title>Knowledge Base</title>
-
- <para>Our knowledge-based API allows you to first create a Knowledge Base
- that contains all the necessary knowledge. This includes all the
- relevant process definitions and other knowledge types like rules. The
- following code snippet shows how to create a Knowledge Base consisting of only
- one process definition, using a Knowledge Builder to add a resource, checking
- for errors and, finally, creating the Knowledge Base.</para>
-
-<programlisting role="JAVA">
-KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-kbuilder.add(ResourceFactory.newClassPathResource("ruleflow.rf"), ResourceType.DRF);
-KnowledgeBuilderErrors errors = kbuilder.getErrors();
-if (errors.size() > 0) {
- for (KnowledgeBuilderError error: errors) {
- System.err.println(error);
- }
- throw new IllegalArgumentException("Could not parse knowledge.");
-}
-KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
-kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
-</programlisting>
-
- <para>Note that the knowledge-based API allows users to add different types of
- resources, such as rules and processes, in almost identical ways into the same
- Knowledge Base. This enables a user who knows how to use Drools Flow to start
- using Drools Fusion almost instantaneously, and even to integrate these
- different types of Knowledge.</para>
-
- </section>
-
- <section>
- <title>Session</title>
-
- <para>Next, you should create a session to interact with the engine. Again, the
- API is knowledge-based, supporting different types of Knowledge, with a specific
- extension for each Knowledge Type. The following code snippet shows how easy it
- is to create a session based on the earlier created Knowledge Base, and to start a
- process.</para>
-
-<programlisting role="JAVA">
-StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
-ProcessInstance processInstance = ksession.startProcess("com.sample.ruleflow");
-</programlisting>
-
- <para>The <code>ProcessRuntime</code> interface defines all the session methods
- for interacting with processes, as shown below. Consult the Javadocs to get
- a detailed explanation for each of the methods.</para>
-
-<programlisting role="JAVA">
-ProcessInstance startProcess(String processId);
-ProcessInstance startProcess(String processId, Map<String, Object> parameters);
-void signalEvent(String type, Object event);
-Collection<ProcessInstance> getProcessInstances();
-ProcessInstance getProcessInstance(long id);
-WorkItemManager getWorkItemManager();
-</programlisting>
-
- </section>
-
- <section>
- <title>Events</title>
-
- <para>Both the Stateful and Stateless Knowledge Session provide methods for
- registering and removing listeners. <code>ProcessEventListener</code> objects
- can be used to listen to process-related events, like starting or completing
- a process, and entering and leaving a node. Below, the different methods of a
- <code>ProcessEventListener</code> are shown. An event object provides access
- to related information, like the process instance and node instance linked to
- the event.</para>
-
-<programlisting role="JAVA">
-public interface ProcessEventListener {
-
- void beforeProcessStarted( ProcessStartedEvent event );
- void afterProcessStarted( ProcessStartedEvent event );
- void beforeProcessCompleted( ProcessCompletedEvent event );
- void afterProcessCompleted( ProcessCompletedEvent event );
- void beforeNodeTriggered( ProcessNodeTriggeredEvent event );
- void afterNodeTriggered( ProcessNodeTriggeredEvent event );
- void beforeNodeLeft( ProcessNodeLeftEvent event );
- void afterNodeLeft( ProcessNodeLeftEvent event );
-
-}</programlisting>
-
- <para>An audit log can be created based on the information provided by these process
- listeners. We provide various default logger implementations:
- <orderedlist>
- <listitem>Console logger: This logger writes out all the events to the console.</listitem>
-
- <listitem>File logger: This logger writes out all the events to a file using an
- XML representation. This log file might then be used in the IDE to generate
- a tree-based visualization of the events that occurred during execution.</listitem>
-
- <listitem>Threaded file logger: Because a file logger writes the events to disk only
- when closing the logger or when the number of events in the logger reaches a predefined
- level, it cannot be used when debugging processes at runtime. A threaded file logger
- writes the events to a file after a specified time interval, making it possible to use
- the logger to visualize the progress in realtime, while debugging processes.
- </listitem>
- </orderedlist>
- </para>
-
- <para>The <code>KnowledgeRuntimeLoggerFactory</code> let you add a logger to
- your session, as shown below. When creating a console logger, the Knowledge Session
- for which the logger needs to be created must be passed as an argument. The file
- logger also requires the name of the log file to be created, and the threaded file
- logger requires the interval (in milliseconds) after which the events should be saved.</para>
-
-<programlisting role="JAVA">
-KnowledgeRuntimeLogger logger =
- KnowledgeRuntimeLoggerFactory.newFileLogger( ksession, "test" );
-// add invocations to the process engine here,
-// e.g. ksession.startProcess(processId);
-...
-logger.close();</programlisting>
-
- <para>The log file can be opened in Eclipse, using the Audit View in the Drools
- Eclipse plugin, where the events are visualized as a tree. Events that occur
- between the before and after event are shown as children of that event. The
- following screenshot shows a simple example, where a process is started,
- resulting in the activation of the Start node, an Action node and an End node,
- after which the process was completed. </para>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" format="PNG" role=""
- fileref="images/Chapter-API/AuditView.png"/>
- </imageobject>
- </mediaobject>
-
- </section>
-
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0"
+ xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+ xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
+
+ <title>Drools Flow API</title>
+
+ <para>The Drools Flow API should be used to (1) create a knowledge base that contains
+ your process definitions, and to (2) create a session to start new process instances,
+ signal existing ones, register listeners, etc.</para>
+
+ <section>
+ <title>Knowledge Base</title>
+
+ <para>Our knowledge-based API allows you to first create one Knowledge Base
+ that contains all the necessary knowledge and can be reused across sessions. This
+ knowledge base includes all your process definitions (and other knowledge types
+ like for example rules). The following code snippet shows how to create a
+ Knowledge Base consisting of only one process definition, using a Knowledge Builder
+ to add the resource (from the classpath in this case).</para>
+
+<programlisting role="JAVA">
+KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+kbuilder.add(ResourceFactory.newClassPathResource("MyProcess.rf"), ResourceType.DRF);
+KnowledgeBase kbase = kbuilder.newKnowledgeBase();
+</programlisting>
+
+ <para>Note that the knowledge-based API allows users to add different types of
+ resources, such as processes and rules, in almost identical ways into the same
+ Knowledge Base. This enables a user who knows how to use Drools Flow to start
+ using Drools Fusion almost instantaneously, and even to integrate these
+ different types of Knowledge.</para>
+
+ </section>
+
+ <section>
+ <title>Session</title>
+
+ <para>Next, you should create a session to interact with the engine. The following
+ code snippet shows how easy it is to create a session based on the earlier created
+ Knowledge Base, and to start a process (by id).</para>
+
+<programlisting role="JAVA">
+StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+ProcessInstance processInstance = ksession.startProcess("com.sample.MyProcess");
+</programlisting>
+
+ <para>The <code>ProcessRuntime</code> interface defines all the session methods
+ for interacting with processes, as shown below. Consult the JavaDocs to get
+ a detailed explanation for each of the methods.</para>
+
+<programlisting role="JAVA">
+ProcessInstance startProcess(String processId);
+ProcessInstance startProcess(String processId, Map<String, Object> parameters);
+void signalEvent(String type, Object event);
+void signalEvent(String type, Object event, long processInstanceId);
+Collection<ProcessInstance> getProcessInstances();
+ProcessInstance getProcessInstance(long id);
+void abortProcessInstance(long id);
+WorkItemManager getWorkItemManager();
+</programlisting>
+
+ </section>
+
+ <section>
+ <title>Events</title>
+
+ <para>Both the stateful and stateless knowledge sessions provide methods for
+ registering and removing listeners. <code>ProcessEventListener</code> objects
+ can be used to listen to process-related events, like starting or completing
+ a process, entering and leaving a node, etc. Below, the different methods of a
+ <code>ProcessEventListener</code> are shown. An event object provides access
+ to related information, like the process instance and node instance linked to
+ the event.</para>
+
+<programlisting role="JAVA">
+public interface ProcessEventListener {
+
+ void beforeProcessStarted( ProcessStartedEvent event );
+ void afterProcessStarted( ProcessStartedEvent event );
+ void beforeProcessCompleted( ProcessCompletedEvent event );
+ void afterProcessCompleted( ProcessCompletedEvent event );
+ void beforeNodeTriggered( ProcessNodeTriggeredEvent event );
+ void afterNodeTriggered( ProcessNodeTriggeredEvent event );
+ void beforeNodeLeft( ProcessNodeLeftEvent event );
+ void afterNodeLeft( ProcessNodeLeftEvent event );
+
+}</programlisting>
+
+ <para>An audit log can be created based on the information provided by these process
+ listeners. We provide various default logger implementations:
+ <orderedlist>
+ <listitem>Console logger: This logger writes out all the events to the console.</listitem>
+
+ <listitem>File logger: This logger writes out all the events to a file using an
+ XML representation. This log file might then be used in the IDE to generate
+ a tree-based visualization of the events that occurred during execution.</listitem>
+
+ <listitem>Threaded file logger: Because a file logger writes the events to disk only
+ when closing the logger or when the number of events in the logger reaches a predefined
+ level, it cannot be used when debugging processes at runtime. A threaded file logger
+ writes the events to a file after a specified time interval, making it possible to use
+ the logger to visualize the progress in realtime, while debugging processes.
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>The <code>KnowledgeRuntimeLoggerFactory</code> lets you add a logger to
+ your session, as shown below. When creating a console logger, the knowledge session
+ for which the logger needs to be created must be passed as an argument. The file
+ logger also requires the name of the log file to be created, and the threaded file
+ logger requires the interval (in milliseconds) after which the events should be saved.</para>
+
+<programlisting role="JAVA">
+KnowledgeRuntimeLogger logger =
+ KnowledgeRuntimeLoggerFactory.newFileLogger( ksession, "test" );
+// add invocations to the process engine here,
+// e.g. ksession.startProcess(processId);
+...
+logger.close();</programlisting>
+
+ <para>The log file can be opened in Eclipse, using the Audit View in the Drools
+ Eclipse plugin, where the events are visualized as a tree. Events that occur
+ between the before and after event are shown as children of that event. The
+ following screenshot shows a simple example, where a process is started,
+ resulting in the activation of the Start node, an Action node and an End node,
+ after which the process was completed. </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" format="PNG" role=""
+ fileref="images/Chapter-API/AuditView.png"/>
+ </imageobject>
+ </mediaobject>
+
+ </section>
+
+</chapter>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-BPMN2/Chapter-BPMN2.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-BPMN2/Chapter-BPMN2.xml 2010-07-28 21:11:40 UTC (rev 34269)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-BPMN2/Chapter-BPMN2.xml 2010-07-29 00:09:29 UTC (rev 34270)
@@ -5,12 +5,21 @@
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- <title>Business Process Model and Notation (BPMN)</title>
+ <title>Business Process Model and Notation (BPMN 2.0)</title>
- <para>The Business Process Model and Notation (BPMN) 2.0 specification is steadily moving forward on its way to become a great standard, and we are adopting it for our process modeling in Drools Flow. BPMN 2.0 not only defines a standard on how to graphically represent a business process (like BPMN 1.1), but now also includes execution semantics for the elements defined, and an XML format on how to store (and share) process definitions.</para>
+ <para>The Business Process Model and Notation (BPMN) 2.0 specification is steadily moving forward on its way to become a great standard,
+ and we are adopting it for our process modeling in Drools Flow. BPMN 2.0 not only defines a standard on how to graphically represent
+ a business process (like BPMN 1.1), but now also includes execution semantics for the elements defined, and an XML format on how to
+ store (and share) process definitions.</para>
- <para>In a first fase, we are migrating our custom Drools Flow XML format to the BPMN 2.0 XML, as defined in the specification. The following list gives an overview of the various elements that can already be expressed (and executed) using the BPMN 2.0 XML format:</para>
+ <para>Drools Flow allows you to execute processes defined using the BPMN 2.0 XML format, just the same way as it allows you to execute
+ processes using the custom RuleFlow format. That means that you can use the same API, engine and components like Guvnor and the gwt-console,
+ to execute and manage your BPMN 2.0 processes.</para>
+ <para>We do yet implement all node types and attributes as defined in the BPMN 2.0 specification, but we already support a very significant
+ subset, which includes all common node types. The following list gives an overview of the various elements that can already be
+ executed using the BPMN 2.0 XML format:</para>
+
<itemizedlist>
<listitem><emphasis>Flow objects</emphasis>
<itemizedlist>
@@ -94,14 +103,12 @@
targetNamespace="http://www.jboss.org/drools"
typeLanguage="http://www.java.com/javaTypes"
expressionLanguage="http://www.mvel.org/2.0"
- xmlns="http://schema.omg.org/spec/BPMN/2.0"
+ xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
- xs:schemaLocation="http://schema.omg.org/spec/BPMN/2.0 BPMN20.xsd"
+ xs:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
xmlns:g="http://www.jboss.org/drools/flow/gpd"
xmlns:tns="http://www.jboss.org/drools">
- <itemDefinition id="_employeeItem" structureRef="java.lang.Object" />
-
<process processType="Private" isExecutable="true" id="com.sample.evaluation" name="Evaluation Process" >
<!-- process variables -->
@@ -285,7 +292,9 @@
</potentialOwner>
</userTask>
<parallelGateway id="_6" name="Converge" g:x="603" g:y="55" g:width="49" g:height="49" gatewayDirection="Converging" />
- <endEvent id="_7" name="EndProcess" g:x="690" g:y="56" g:width="48" g:height="48" />
+ <endEvent id="_7" name="EndProcess" g:x="690" g:y="56" g:width="48" g:height="48" >
+ <terminateEventDefinition/>
+ </endEvent>
<!-- connections -->
<sequenceFlow id="_1-_2" sourceRef="_1" targetRef="_2" />
@@ -300,6 +309,29 @@
</definitions></programlisting>
+ <para>To create your own process using BPMN 2.0 format, you can
+ <itemizedlist>
+ <listitem>
+ <para>Create a new Flow file using the Drools Eclipse plugin wizard and in the last page of the wizard,
+ make sure you select Drools 5.1 code compatibility. This will create a new process using the BPMN XML
+ format instead of the old RuleFlow format. Note however that this is not a real BPMN 2.0 editor, as it
+ still uses different attributes. It does however save the process using valid BPMN 2.0 syntax. Also note
+ that the editor does not yet support all node types and attributes that are already supported in the
+ execution engine.</para>
+ </listitem>
+ <listitem>
+ <para>Oryx is an open-source web-based editor that supports the BPMN 2.0 format. We have embedded it into
+ Guvnor for BPMN 2.0 process visualization and editing. You could use the Oryx editor (either standalone or
+ integrated) to create / edit BPMN 2.0 processes and then export them to BPMN 2.0 format so they can be executed.
+ Be aware however that Oryx is still using the BPMN 2.0 beta 1 format and that their implementation is currently
+ incomplete (especially the import / export functionality).</para>
+ </listitem>
+ <listitem>
+ <para>You can always manually create your BPMN 2.0 process files by writing the XML directly.</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
<para>The following code fragment shows you how to load a BPMN process into your knowledge base ...</para>
<programlisting role="JAVA">
@@ -321,8 +353,31 @@
params.put("employee", "krisv");
ksession.startProcess("com.sample.evaluation", params);</programlisting>
- <para>In more detail, the following table gives an overview of which features of the Drools Flow language have already been ported to the BPMN 2.0 XML format. A green check mark means that the functionality can be expressed using the features defined in the BPMN 2.0 specification. Sometimes however, the specification does not specify how some (of the more advanced) features can be expressed using BPMN 2.0 syntax. Luckily, the XML Schema is extensible, so in those cases we extend the BPMN 2.0 specification with additional attributes and/or elements so that these features can be stored in XML as well. Custom extensions to the BPMN 2.0 format are shown using an orange check mark. As shown in the table below, most of the basic BPMN 2.0 nodes are already supported.</para>
+ <section>
+ <title>Current limitations</title>
+ <para>Since the BPMN 2.0 specification is still being finalized, the BPMN 2.0 execution is still an experimental feature. It uses the
+ same execution engine and constructs as the RuleFlow format however (it's just another XML serialization format). Therefore, all features
+ and components that are available using the RuleFlow format also work for BPMN 2.0 processes. You simply have to use the right ResourceType
+ when adding BPMN 2.0 processes to your knowledge base. Since the specification hasn't been finalized yet, it is possible that the XSD that defines the format might still change (slightly)
+ due to updates of the specification, so keep this in mind if you decide to start using the BPMN 2.0 format.</para>
+
+ <para>The use of a specification should give you a lot of advantages, as it allows you to share your processes across tools and possibly even
+ engines as the specification defines the exact format (and even execution semantics) for each of the elements. At this point however, it is likely
+ that different tools are using different intermediate versions of the specification. We believe that this issue will automatically resolve itself
+ over time once the specification is finalized and everyone is using the same version of the specification, but until then, you can encounter
+ compatibility issues related to this problem. Please be a little patient with this.</para>
+
+ <para>Finally, the BPMN 2.0 specification defines a lot of node types and attributes, but nevertheless it is not possible to express everything
+ using the constructs offered by the BPMN 2.0 specification only. However, the specification is designed to allow additional node types, attributes,
+ etc. While we try to limit the use of custom extensions to a minimum, we sometimes have to define custom attributes to express features that we
+ believe are important but cannot be expressed as core BPMN 2.0 syntax. The following table gives an overview of which features of the RuleFlow
+ language have already been ported to the BPMN 2.0 XML format. A green check mark means that the functionality can be expressed using the features
+ defined in the BPMN 2.0 specification. In those cases where we extend the BPMN 2.0 specification with additional attributes and/or elements, we show
+ these using an orange check mark. As shown in the table below, most of the basic BPMN 2.0 nodes are already supported. We decided to not yet
+ implement some of the features that cannot be expressed in BPMN 2.0 by default, like for example the on-entry / on-exit actions or the state node.
+ We will decide later whether we want to support these features for BPMN 2.0 processes in the future, and how.</para>
+
<table>
<title>Keywords</title>
<tgroup cols="3">Drools BPMN 2.0 features
@@ -1115,4 +1170,6 @@
</tgroup>
</table>
+ </section>
+
</chapter>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Console/Chapter-Console.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Console/Chapter-Console.xml 2010-07-28 21:11:40 UTC (rev 34269)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Console/Chapter-Console.xml 2010-07-29 00:09:29 UTC (rev 34270)
@@ -1,376 +1,387 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter version="5.0"
- xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
- xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
-
- <title>Console</title>
-
- <para>Drools processes can be managed through a web console. This includes
- features like managing your process instances (starting/stopping/inspecting),
- inspecting your (human) task list and executing those tasks, and generating
- reports.</para>
-
- <para>The Drools build system generates two wars for you that can be deployed in your
- application server and contains the necessary libraries, the actual application,
- etc. One jar contains the server application, the other one the client. Download
- gwt-console-server-drools-{version}.war and gwt-console-drools-{version}.war and deploy
- them to your application server, {AS_HOME}/server/{configuration}/deploy (so for example,
- we are using jboss-4.2.3.GA/server/default/deploy).</para>
-
- <section>
- <title>Installation</title>
-
- <para>You need to have an application server installed. This chapter assumes
- you are using the JBoss AS version 4.2.3.GA, but other versions or other
- application servers should be possible as well.</para>
-
- <section>
- <title>Installing Guvnor</title>
-
- <para>The process management console uses Drools Guvnor for loading the process
- definitions that can be used inside the console. You therefore need to install
- Guvnor, to be able to add new process definitions to the repository, so they
- can then be managed through the console. To do so, simply copy
- drools-guvnor.war to your application server,
- {AS_HOME}/server/{configuration}/deploy.</para>
-
- </section>
-
- <section>
- <title>Changing the persistence configuration of your runtime data</title>
-
- <para>The persistence.xml that is included in the server war refers to
- a JTA data source called "java:jdbc/testDS1" for storing the runtime information.
- To define this data source, create a testDS1-ds.xml file with the following content
- (note that we are using an embedded H2 in memory database, but similar configurations
- for another JPA data source is possible as well of course), and copy it to your
- application server deploy directory:</para>
-
- <programlisting>
-<?xml version="1.0" encoding="UTF-8"?>
-<datasources>
- <local-tx-datasource>
- <jndi-name>jdbc/testDS1</jndi-name>
- <connection-url>jdbc:h2:mem:mydb</connection-url>
- <driver-class>org.h2.jdbcx.JdbcDataSource</driver-class>
- <user-name>sa</user-name>
- <password></password>
- </local-tx-datasource>
-</datasources></programlisting>
-
- <para>Also make sure that the driver class can be found on the server classpath.
- In this case, we copied the h2-1.0.77.jar to the {AS_HOME}/server/{config}/lib
- folder.</para>
-
- </section>
-
- <section>
- <title>Changing the persistence configuration of your history data</title>
-
- <para>Drools uses Hibernate to persist history information in a database,
- for long term storagy. The drools-bam module (inside the gwt-console-server-drools
- war) contains a hibernate.cfg.xml file that contains the default configuration,
- i.e using an embedded H2 in memory database. However, this embedded database
- does not allow concurrent access. If you are planning to use reporting, concurrent
- access might be required, so you should use the server configuration of the H2 in memory
- database in that case. Change the connection url in the hibernate.cfg.xml
- to this:</para>
-
- <programlisting>
-<property name="connection.url">jdbc:h2:tcp://localhost/~/test</property></programlisting>
-
- <para>In this case, you should also make sure you have the H2 database running in
- server mode when running the application - for example by executing the org.h2.tools.Server
- class.</para>
-
- </section>
-
- <section>
- <title>Installing the reporting engine</title>
-
- <para>The reporting engine is based on the Eclipse BIRT engine. You need to
- install the Eclipse BIRT runtime engine in your application server to be able to use
- the reporting functionality. To do so, create a new directory called
- {AS_HOME}/server/{configuration}/data/birt. Download the Eclipse BIRT report
- engine version 2.3.2 (birt-runtime-2_3_2_2.zip), extract it and copy the ReportEngine
- directory to the newly created directory (the other directories are not needed).</para>
-
- <para>Next, you need to copy your process instance reports to the newly created
- directory as well. Eclipse BIRT allows you to define your own reports based on
- existing data sources. The console expects two different reports:
- <orderedlist>
- <listitem><emphasis>overall_activity.rptdesign</emphasis>: this reports shows
- an overview of all running process instances in your system</listitem>
- <listitem><emphasis>process_summary.rptdesign</emphasis>: this reports is
- shown when the user wants to look into one process definition. It gives more
- details about all instances for that process.</listitem>
- </orderedlist>
- We have created some example reports you could use and customize according to your
- own requirements. The example report templates can be found in the drools-bam
- module (src/test/resources). Note that these example reports are also using the H2
- in memory database (in server mode). If you configured the persistence of the history
- data differently, you will have to update the data source of these reports accordingly.
- You also need to copy your database drivers to the reporting plugin. In our case,
- using H2, copy the h2-1.0.77.jar to {AS_HOME}/server/{configuration}/data/birt/ReportEngine/plugins/
- org.eclipse.birt.report.data.oda.jdbc_2.3.2.r232_v20090212/drivers.</para>
-
- </section>
-
- <section>
- <title>User authentication</title>
-
- <para>The application uses simple password authentication to verify who is allowed to
- use the application. For example, usernames / passwords can be specified in a
- users.properties file in {AS_HOME}/server/{configuration}/conf, for example:</para>
-
- <programlisting>
-admin=admin
-krisv=mypassword</programlisting>
-
- <para>The roles associated with these users can be specified in a roles.properties file
- in the same directory, for example:</para>
-
- <programlisting>
-admin=admin,manager,user
-krisv=admin,manager,user</programlisting>
-
- </section>
-
- <section>
- <title>Configure memory settings</title>
-
- <para>You might want to increase the memory that can be used by the application server
- (especially the PermGen space) if you run into OutOfMemory exceptions. To do so, edit
- the run.conf or run.bat (depending on your OS) and for example add the following line:</para>
-
- <programlisting>
-JAVA_OPTS="$JAVA_OPTS -XX:MaxPermSize=256m"</programlisting>
-
- </section>
-
- <para>You are now ready to startup the application server. If you are using human tasks in
- your processes, you should also make sure you have the task service running (on
- 127.0.0.1:9123). Also make sure your database is up and running of course.</para>
-
- </section>
-
- <section>
- <title>Adding process definitions in Guvnor</title>
-
- <para>Drools Guvnor allows you to manage all your business knowledge in a (logically)
- centralized location. This includes all your process definitions, business rules, etc.
- The process management console automatically retrieves all the processes from the latest
- snapshot of the "default" package on Guvnor. To find out how to get processes on the
- Guvnor repository (for example manually uploading them, or using the Eclipse Guvnor
- synchronization), check out the Guvnor documentation. After deploying Guvnor to your
- application server, navigate to the following URL to open up Guvnor (replace the host
- and/or port depending on how the application server is configured):
- <ulink url="http://localhost:8080/drools-guvnor">http://localhost:8080/drools-guvnor</ulink></para>
-
- <para>The following screenshot shows an example where the "default" package contains one
- "Evaluation" process. After adding the necessary process definitions, make sure to build
- the package, so that the built package can be downloaded by the web console.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/Guvnor.PNG"/></imageobject></mediaobject>
-
- </section>
-
- <section>
- <title>Running the process management console</title>
-
- <para>Now navigate to the following URL (replace the host and/or port depending on how the application server
- is configured):
- <ulink url="http://localhost:8080/gwt-console">http://localhost:8080/gwt-console</ulink></para>
-
- <para>A login screen should pop up, asking for your user name and password.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/Login.PNG"/></imageobject></mediaobject>
-
- <para>After filling these in, the process management workbench should be opened, as shown in the
- screenshot below. On the right you will see several tabs, related to process instance management,
- human task lists and reporting, as explained in the following sections.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/Tasks.PNG"/></imageobject></mediaobject>
-
- <section>
- <title>Managing process instances</title>
-
- <para>The "Processes" section allows you to inspect the process definitions that are currently
- part of the installed knowledge base, start new process instances and manage running process
- instances (which includes inspecting their state and data).</para>
-
- <section>
- <title>Inspecting process definitions</title>
-
- <para>When you open the process definition list, all processes that are stored in the "default"
- package on Guvnor are shown. You can then either inspect process instances for one specific
- process or start a new process instance.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessDefinitions.PNG"/></imageobject></mediaobject>
-
- </section>
-
- <section>
- <title>Starting new process instances</title>
-
- <para>To start a new process instance for one specific process definition, select the process
- definition in the process definition list and select the process instances tab. Click on the
- "Start" button to start a new instance of that specific process. When a form is associated
- with this particular process (to ask for additional information before starting the process),
- this form will be shown. After completing this form, the process will be started with the
- provided information.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/StartProcess.PNG"/></imageobject></mediaobject>
-
- </section>
-
- <section>
- <title>Managing process instances</title>
-
- <para>The process instances tab also contains a table showing all running instances of that
- specific process definition. Select a process instance to show the details of that specific
- process instance.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessInstances.PNG"/></imageobject></mediaobject>
-
- </section>
-
- <section>
- <title>Inspecting process instance state</title>
-
- <para>You can inspect the (top-level) variables of a specific process instance by clicking on
- the "Instance Data" button. This will show you how each variable defined in the process
- maps to it's corresponding value for that specific process instance.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessInstanceDiagram.PNG"/></imageobject></mediaobject>
-
- </section>
-
- <section>
- <title>Inspecting process instance variables</title>
-
- <para>You can inspect the state of a specific process instance by clicking on
- the "Diagram" button. This will show you the process flow chart, where a red
- traingle is shown at each node that is currently active (like for example a human
- task node waiting for the task to be completed or a join node waiting for more
- incoming connections before continuing). [Note that multiple instances of one node
- could be executing simultaneously. They will still be shown using only one red
- triangle.]</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessInstanceData.PNG"/></imageobject></mediaobject>
-
- </section>
-
- </section>
-
- <section>
- <title>Human task lists</title>
-
- <para>The task management section allows a user to see his/her current task list.
- The group task list shows all the tasks that are not yet assigned to one specific
- user but that the currently logged in user could claim. The personal task list shows
- all tasks that are assigned to the currently logged in user. To execute a task,
- select it in your personal task list and select "View". If a form is associated
- with the selected task (for example to ask for additional information), this form
- will be shown. After completing the form, the task will also be completed.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/TaskForm.PNG"/></imageobject></mediaobject>
-
- </section>
-
- <section>
- <title>Reporting</title>
-
- <para>The reporting section allows you to view reports about the execution of
- processes. This includes an overall report showing an overview of all processes,
- as shown below.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ReportOverall.PNG"/></imageobject></mediaobject>
-
- <para>A report regarding one specific process instance can also be generated.</para>
-
- <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ReportProcess.PNG"/></imageobject></mediaobject>
-
- <para>Drools Flow provides some sample reports that could be used to visualize some
- generic execution characteristics like the number of active process instances per
- process etc. But custom reports could be generated to show the information your
- company thinks is important, by replacing the report templates in the report
- directory.</para>
-
- </section>
-
- </section>
-
- <section>
- <title>Adding new process / task forms</title>
-
- <para>Forms can be used to (1) start a new process or (2) complete a human task.
- We use freemarker templates to dynamically create forms. To create a form for a
- specific process definition, create a freemarker template with the name
- {processId}.ftl. The template itself should use HTML
- code to model the form. For example, the form to start the evalution process shown
- above is defined in the com.sample.evaluation.ftl file:</para>
-
- <programlisting>
-<html>
-<body>
-<h2>Start Performance Evaluation</h2>
-<hr>
-<form action="complete" method="POST" enctype="multipart/form-data">
-Please fill in your username: <input type="text" name="employee" /></BR>
-<input type="submit" value="Complete">
-</form>
-</body>
-</html></programlisting>
-
- <para>Similarly, task forms for a specific type of human task (uniquely identified
- by its task name) can be linked to that human task by creating a freemarker template
- with the name {taskName}.ftl. The form has access to a "task" parameter that represents
- the current human task, so it allows you to dynamically adjust the task form based on
- the task input. The task parameter is a Task model object as defined in the
- drools-process-task module. This for example allows you to customize the task form based
- on the description or input data related to that task. For example, the evaluation form
- shown earlier uses the task parameter to access the description of the task and show that
- in the task form:</para>
-
- <programlisting>
-<html>
-<body>
-<h2>Employee evaluation</h2>
-<hr>
-${task.descriptions[0].text}<br/>
-<br/>
-Please fill in the following evaluation form:
-<form action="complete" method="POST" enctype="multipart/form-data">
-Rate the overall performance: <select name="performance">
-<option value="outstanding">Outstanding</option>
-<option value="exceeding">Exceeding expectations</option>
-<option value="acceptable">Acceptable</option>
-<option value="below">Below average</option>
-</select><br/>
-<br/>
-Check any that apply:<br/>
-<input type="checkbox" name="initiative" value="initiative">Displaying initiative<br/>
-<input type="checkbox" name="change" value="change">Thriving on change<br/>
-<input type="checkbox" name="communication" value="communication">Good communication skills<br/>
-<br/>
-<input type="submit" value="Complete">
-</form>
-</body>
-</html>
-</programlisting>
-
- <para>Data that is provided by the user when filling in the task form will be
- added as parameters when completing the task. For example, when completing the
- task above, the Map of outcome parameters will include result variables called
- "performance", "initiative", "change" and "communication". The result parameters
- can be accessed in the related process by mapping these parameters to process
- variables.</para>
-
- <para>Forms should be included in the drools-gwt-form.jar in the server war.</para>
-
- </section>
-
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0"
+ xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+ xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
+
+ <title>Console</title>
+
+ <para>Drools processes can be managed through a web console. This includes
+ features like managing your process instances (starting/stopping/inspecting),
+ inspecting your (human) task list and executing those tasks, and generating
+ reports.</para>
+
+ <para>The Drools build system generates two wars for you that can be deployed in your
+ application server and contains the necessary libraries, the actual application,
+ etc. One jar contains the server application, the other one the client. Download
+ gwt-console-server-drools-{version}.war and gwt-console-drools-{version}.war and deploy
+ them to your application server, {AS_HOME}/server/{configuration}/deploy (so for example,
+ we are using jboss-4.2.3.GA/server/default/deploy).</para>
+
+ <section>
+ <title>Installation</title>
+
+ <para>The easiest way to get started with the console is probably to use the installer.
+ This will download, install and configure all the necessary components to get the console running,
+ including Guvnor, a human task service, etc. Check out the chapter on the installer for
+ more information. If you want to manually install the console, you can continue reading
+ here.</para>
+
+ <para>You need to have an application server installed. This chapter assumes
+ you are using the JBoss AS version 4.2.3.GA, but other versions or other
+ application servers should be possible as well.</para>
+
+ <section>
+ <title>Installing Guvnor</title>
+
+ <para>The process management console uses Drools Guvnor for loading the process
+ definitions that can be used inside the console. You therefore need to install
+ Guvnor, to be able to add new process definitions to the repository, so they
+ can then be managed through the console. To do so, simply copy
+ drools-guvnor.war to your application server,
+ {AS_HOME}/server/{configuration}/deploy.</para>
+
+ </section>
+
+ <section>
+ <title>Changing the persistence configuration of your runtime data</title>
+
+ <para>The persistence.xml that is included in the server war refers to
+ a JTA data source called "java:jdbc/testDS1" for storing the runtime information.
+ To define this data source, create a testDS1-ds.xml file with the following content
+ (note that we are using an embedded H2 in memory database, but similar configurations
+ for another JPA data source is possible as well of course), and copy it to your
+ application server deploy directory:</para>
+
+ <programlisting>
+<?xml version="1.0" encoding="UTF-8"?>
+<datasources>
+ <local-tx-datasource>
+ <jndi-name>jdbc/testDS1</jndi-name>
+ <connection-url>jdbc:h2:mem:mydb</connection-url>
+ <driver-class>org.h2.jdbcx.JdbcDataSource</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ </local-tx-datasource>
+</datasources></programlisting>
+
+ <para>Also make sure that the driver class can be found on the server classpath.
+ In this case, we copied the h2-1.0.77.jar to the {AS_HOME}/server/{config}/lib
+ folder.</para>
+
+ </section>
+
+ <section>
+ <title>Changing the persistence configuration of your history data</title>
+
+ <para>Drools uses Hibernate to persist history information in a database,
+ for long term storagy. The drools-bam module (inside the gwt-console-server-drools
+ war) contains a hibernate.cfg.xml file that contains the default configuration,
+ i.e using an embedded H2 in memory database. However, this embedded database
+ does not allow concurrent access. If you are planning to use reporting, concurrent
+ access might be required, so you should use the server configuration of the H2 in memory
+ database in that case. Change the connection url in the hibernate.cfg.xml
+ to this:</para>
+
+ <programlisting>
+<property name="connection.url">jdbc:h2:tcp://localhost/~/test</property></programlisting>
+
+ <para>In this case, you should also make sure you have the H2 database running in
+ server mode when running the application - for example by executing the org.h2.tools.Server
+ class.</para>
+
+ </section>
+
+ <section>
+ <title>Installing the reporting engine</title>
+
+ <para>The reporting engine is based on the Eclipse BIRT engine. You need to
+ install the Eclipse BIRT runtime engine in your application server to be able to use
+ the reporting functionality. To do so, create a new directory called
+ {AS_HOME}/server/{configuration}/data/birt. Download the Eclipse BIRT report
+ engine version 2.3.2 (birt-runtime-2_3_2_2.zip), extract it and copy the ReportEngine
+ directory to the newly created directory (the other directories are not needed).</para>
+
+ <para>Next, you need to copy your process instance reports to the newly created
+ directory as well. Eclipse BIRT allows you to define your own reports based on
+ existing data sources. The console expects two different reports:
+ <orderedlist>
+ <listitem><emphasis>overall_activity.rptdesign</emphasis>: this reports shows
+ an overview of all running process instances in your system</listitem>
+ <listitem><emphasis>process_summary.rptdesign</emphasis>: this reports is
+ shown when the user wants to look into one process definition. It gives more
+ details about all instances for that process.</listitem>
+ </orderedlist>
+ We have created some example reports you could use and customize according to your
+ own requirements. The example report templates can be found in the drools-bam
+ module (src/test/resources). Note that these example reports are also using the H2
+ in memory database (in server mode). If you configured the persistence of the history
+ data differently, you will have to update the data source of these reports accordingly.
+ You also need to copy your database drivers to the reporting plugin. In our case,
+ using H2, copy the h2-1.0.77.jar to {AS_HOME}/server/{configuration}/data/birt/ReportEngine/plugins/
+ org.eclipse.birt.report.data.oda.jdbc_2.3.2.r232_v20090212/drivers.</para>
+
+ </section>
+
+ <section>
+ <title>User authentication</title>
+
+ <para>The application uses simple password authentication to verify who is allowed to
+ use the application. For example, usernames / passwords can be specified in a
+ users.properties file in {AS_HOME}/server/{configuration}/conf, for example:</para>
+
+ <programlisting>
+admin=admin
+krisv=mypassword</programlisting>
+
+ <para>The roles associated with these users can be specified in a roles.properties file
+ in the same directory, for example:</para>
+
+ <programlisting>
+admin=admin,manager,user
+krisv=admin,manager,user</programlisting>
+
+ </section>
+
+ <section>
+ <title>Configure memory settings</title>
+
+ <para>You might want to increase the memory that can be used by the application server
+ (especially the PermGen space) if you run into OutOfMemory exceptions. To do so, edit
+ the run.conf or run.bat (depending on your OS) and for example add the following line:</para>
+
+ <programlisting>
+JAVA_OPTS="$JAVA_OPTS -XX:MaxPermSize=256m"</programlisting>
+
+ </section>
+
+ <para>You are now ready to startup the application server. If you are using human tasks in
+ your processes, you should also make sure you have the task service running (on
+ 127.0.0.1:9123). Also make sure your database is up and running of course.</para>
+
+ </section>
+
+ <section>
+ <title>Adding process definitions in Guvnor</title>
+
+ <para>Drools Guvnor allows you to manage all your business knowledge in a (logically)
+ centralized location. This includes all your process definitions, business rules, etc.
+ The process management console automatically retrieves all the processes from the latest
+ snapshot of the "defaultPackage" package on Guvnor. To find out how to get processes on the
+ Guvnor repository (for example manually uploading them, or using the Eclipse Guvnor
+ synchronization), check out the Guvnor documentation. After deploying Guvnor to your
+ application server, navigate to the following URL to open up Guvnor (replace the host
+ and/or port depending on how the application server is configured):
+ <ulink url="http://localhost:8080/drools-guvnor">http://localhost:8080/drools-guvnor</ulink></para>
+
+ <para>The following screenshot shows an example where the "defaultPackage" package contains one
+ "Evaluation" process. After adding the necessary process definitions, make sure to build
+ the package, so that the built package can be downloaded by the web console.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/Guvnor.PNG"/></imageobject></mediaobject>
+
+ <para>It is important that you make sure that (1) you add your processes to the package with the
+ name "defaultPackage", otherwise your processes won't show up in the console, and (2) that your
+ processes also define "defaultPackage" as the package of the process. Guvnor does not allow a process
+ to be built if it is not put in the same package as it defines.</para>
+
+ </section>
+
+ <section>
+ <title>Running the process management console</title>
+
+ <para>Now navigate to the following URL (replace the host and/or port depending on how the application server
+ is configured):
+ <ulink url="http://localhost:8080/gwt-console">http://localhost:8080/gwt-console</ulink></para>
+
+ <para>A login screen should pop up, asking for your user name and password.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/Login.PNG"/></imageobject></mediaobject>
+
+ <para>After filling these in, the process management workbench should be opened, as shown in the
+ screenshot below. On the right you will see several tabs, related to process instance management,
+ human task lists and reporting, as explained in the following sections.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/Tasks.PNG"/></imageobject></mediaobject>
+
+ <section>
+ <title>Managing process instances</title>
+
+ <para>The "Processes" section allows you to inspect the process definitions that are currently
+ part of the installed knowledge base, start new process instances and manage running process
+ instances (which includes inspecting their state and data).</para>
+
+ <section>
+ <title>Inspecting process definitions</title>
+
+ <para>When you open the process definition list, all processes that are stored in the "default"
+ package on Guvnor are shown. You can then either inspect process instances for one specific
+ process or start a new process instance.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessDefinitions.PNG"/></imageobject></mediaobject>
+
+ </section>
+
+ <section>
+ <title>Starting new process instances</title>
+
+ <para>To start a new process instance for one specific process definition, select the process
+ definition in the process definition list and select the process instances tab. Click on the
+ "Start" button to start a new instance of that specific process. When a form is associated
+ with this particular process (to ask for additional information before starting the process),
+ this form will be shown. After completing this form, the process will be started with the
+ provided information.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/StartProcess.PNG"/></imageobject></mediaobject>
+
+ </section>
+
+ <section>
+ <title>Managing process instances</title>
+
+ <para>The process instances tab also contains a table showing all running instances of that
+ specific process definition. Select a process instance to show the details of that specific
+ process instance.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessInstances.PNG"/></imageobject></mediaobject>
+
+ </section>
+
+ <section>
+ <title>Inspecting process instance state</title>
+
+ <para>You can inspect the (top-level) variables of a specific process instance by clicking on
+ the "Instance Data" button. This will show you how each variable defined in the process
+ maps to it's corresponding value for that specific process instance.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessInstanceDiagram.PNG"/></imageobject></mediaobject>
+
+ </section>
+
+ <section>
+ <title>Inspecting process instance variables</title>
+
+ <para>You can inspect the state of a specific process instance by clicking on
+ the "Diagram" button. This will show you the process flow chart, where a red
+ traingle is shown at each node that is currently active (like for example a human
+ task node waiting for the task to be completed or a join node waiting for more
+ incoming connections before continuing). [Note that multiple instances of one node
+ could be executing simultaneously. They will still be shown using only one red
+ triangle.]</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ProcessInstanceData.PNG"/></imageobject></mediaobject>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Human task lists</title>
+
+ <para>The task management section allows a user to see his/her current task list.
+ The group task list shows all the tasks that are not yet assigned to one specific
+ user but that the currently logged in user could claim. The personal task list shows
+ all tasks that are assigned to the currently logged in user. To execute a task,
+ select it in your personal task list and select "View". If a form is associated
+ with the selected task (for example to ask for additional information), this form
+ will be shown. After completing the form, the task will also be completed.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/TaskForm.PNG"/></imageobject></mediaobject>
+
+ </section>
+
+ <section>
+ <title>Reporting</title>
+
+ <para>The reporting section allows you to view reports about the execution of
+ processes. This includes an overall report showing an overview of all processes,
+ as shown below.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ReportOverall.PNG"/></imageobject></mediaobject>
+
+ <para>A report regarding one specific process instance can also be generated.</para>
+
+ <mediaobject><imageobject><imagedata align="center" format="PNG" role="" fileref="images/Chapter-Console/ReportProcess.PNG"/></imageobject></mediaobject>
+
+ <para>Drools Flow provides some sample reports that could be used to visualize some
+ generic execution characteristics like the number of active process instances per
+ process etc. But custom reports could be generated to show the information your
+ company thinks is important, by replacing the report templates in the report
+ directory.</para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Adding new process / task forms</title>
+
+ <para>Forms can be used to (1) start a new process or (2) complete a human task.
+ We use freemarker templates to dynamically create forms. To create a form for a
+ specific process definition, create a freemarker template with the name
+ {processId}.ftl. The template itself should use HTML
+ code to model the form. For example, the form to start the evalution process shown
+ above is defined in the com.sample.evaluation.ftl file:</para>
+
+ <programlisting>
+<html>
+<body>
+<h2>Start Performance Evaluation</h2>
+<hr>
+<form action="complete" method="POST" enctype="multipart/form-data">
+Please fill in your username: <input type="text" name="employee" /></BR>
+<input type="submit" value="Complete">
+</form>
+</body>
+</html></programlisting>
+
+ <para>Similarly, task forms for a specific type of human task (uniquely identified
+ by its task name) can be linked to that human task by creating a freemarker template
+ with the name {taskName}.ftl. The form has access to a "task" parameter that represents
+ the current human task, so it allows you to dynamically adjust the task form based on
+ the task input. The task parameter is a Task model object as defined in the
+ drools-process-task module. This for example allows you to customize the task form based
+ on the description or input data related to that task. For example, the evaluation form
+ shown earlier uses the task parameter to access the description of the task and show that
+ in the task form:</para>
+
+ <programlisting>
+<html>
+<body>
+<h2>Employee evaluation</h2>
+<hr>
+${task.descriptions[0].text}<br/>
+<br/>
+Please fill in the following evaluation form:
+<form action="complete" method="POST" enctype="multipart/form-data">
+Rate the overall performance: <select name="performance">
+<option value="outstanding">Outstanding</option>
+<option value="exceeding">Exceeding expectations</option>
+<option value="acceptable">Acceptable</option>
+<option value="below">Below average</option>
+</select><br/>
+<br/>
+Check any that apply:<br/>
+<input type="checkbox" name="initiative" value="initiative">Displaying initiative<br/>
+<input type="checkbox" name="change" value="change">Thriving on change<br/>
+<input type="checkbox" name="communication" value="communication">Good communication skills<br/>
+<br/>
+<input type="submit" value="Complete">
+</form>
+</body>
+</html>
+</programlisting>
+
+ <para>Data that is provided by the user when filling in the task form will be
+ added as parameters when completing the task. For example, when completing the
+ task above, the Map of outcome parameters will include result variables called
+ "performance", "initiative", "change" and "communication". The result parameters
+ can be accessed in the related process by mapping these parameters to process
+ variables.</para>
+
+ <para>Forms should be included in the drools-gwt-form.jar in the server war.</para>
+
+ </section>
+
+</chapter>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Flow/Chapter-RuleFlow.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Flow/Chapter-RuleFlow.xml 2010-07-28 21:11:40 UTC (rev 34269)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Flow/Chapter-RuleFlow.xml 2010-07-29 00:09:29 UTC (rev 34270)
@@ -1,1750 +1,1770 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<chapter version="5.0"
- xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
- xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- <title>Rule Flow</title>
-
- <figure>
- <title>Ruleflow</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/RuleFlow.png" format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>A RuleFlow is a process that describes the order in which a series of steps need to
- be executed, using a flow chart. A process consists of a collection of nodes that are
- linked to each other using connections. Each of the nodes represents one step in the
- overall process while the connections specify how to transition from one node to the other.
- A large selection of predefined node types have been defined. This chapter describes how
- to define such processes and use them in your application.</para>
-
- <section>
- <title>Creating a RuleFlow Process</title>
-
- <para>Processes can be created by using one of the following three methods:
- <orderedlist>
- <listitem>Using the graphical RuleFlow editor in the Drools plug-in for Eclipse</listitem>
- <listitem>As an XML file, according to the XML process format as defined in the
- XML Schema definition for Drools processes.</listitem>
- <listitem>By directly creating a process using the Process API.</listitem>
- </orderedlist>
- </para>
-
- <section>
- <title>Using the Graphical RuleFlow Editor</title>
-
- <para>The graphical RuleFlow editor is a editor that allows you to create a process
- by dragging and dropping different nodes on a canvas and editing the properties of these
- nodes. The graphical RuleFlow editor is part of the Drools plug-in for Eclipse. Once
- you have set up a Drools project (check the IDE chapter if you do not know how to do this),
- you can start adding processes. When in a project, launch the "New" wizard: use Ctrl+N
- or right-click the directory you would like to put your ruleflow in and select
- "New", then "Other...". Choose the section on "Drools" and then pick "RuleFlow file".
- This will create a new .rf file.</para>
-
- <figure>
- <title>Creating a new RuleFlow file</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/RFNewWizard.png" format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>Next you will see the graphical RuleFlow editor. Now would be a good time to
- switch to the Drools Perspective (if you haven't done so already). This will tweak
- the user interface so that it is optimal for rules. Then, ensure that you can see
- the Properties View down the bottom of the Eclipse window, as it will be necessary
- to fill in the different properties of the elements in your process. If you cannot
- see the properties view, open it using the menu "Window", then "Show View" and
- "Other...", and under the "General" folder select the Properties View.</para>
-
- <figure>
- <title>New RuleFlow process</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" width="100%"
- fileref="images/Chapter-Flow/NewRF.png" format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>The RuleFlow editor consists of a palette, a canvas and an Outline View.
- To add new elements to the canvas, select the element you would like to create
- in the palette and then add them to the canvas by clicking on the preferred
- location. For example, click on the "RuleFlowGroup" icon in the "Components"
- palette of the GUI: you can then draw a few rule flow groups. Clicking on an
- element in your rule flow allows you to set the properties of that element. You
- can connect the nodes (as long as it is permitted by the different types
- of nodes) by using "Connection Creation" from the "Components" palette.</para>
-
- <para>You can keep adding nodes and connections to your process until it
- represents the business logic that you want to specify. You'll probably need
- to check the process for any missing information (by pressing the green "Check"
- icon in the IDE menu bar) before trying to use it in your application.</para>
-
- </section>
-
- <section>
- <title>Defining Processes Using XML</title>
-
- <para>It is also possible to specify processes using the underlying XML directly.
- The syntax of these XML processes is defined using an XML Schema definition.
- For example, the following XML fragment shows a simple process that contains a
- sequence of a Start node, an Action node that prints "Hello World" to the console,
- and an End node.</para>
-
-<programlisting>
-<?xml version="1.0" encoding="UTF-8"?>
-<process xmlns="http://drools.org/drools-5.0/process"
- xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
- xs:schemaLocation="http://drools.org/drools-5.0/process drools-processes-5.0.xsd"
- type="RuleFlow" name="ruleflow" id="com.sample.ruleflow" package-name="com.sample" >
-
- <header>
- </header>
-
- <nodes>
- <start id="1" name="Start" x="16" y="16" />
- <actionNode id="2" name="Hello" x="128" y="16" >
- <action type="expression" dialect="mvel" >System.out.println("Hello World");</action>
- </actionNode>
- <end id="3" name="End" x="240" y="16" />
- </nodes>
-
- <connections>
- <connection from="1" to="2" />
- <connection from="2" to="3" />
- </connections>
-
-</process>
-</programlisting>
-
- <para>The process XML file should consist of exactly one <process> element.
- This element contains parameters related to the process (its type, name, id and
- package name), and consists of three subsections: a <header> (where
- process-level information like variables, globals, imports and swimlanes can be
- defined), a <nodes> section that defines each of the nodes in the process,
- and a <connections> section that contains the connections between all the nodes
- in the process. In the nodes section, there is a specific element for each node,
- defining the various parameters and, possibly, sub-elements for that node type.</para>
-
- </section>
-
- <section>
- <title>Defining Processes Using the Process API</title>
-
- <para>While it is recommended to define processes using the graphical editor or
- the underlying XML (to shield yourself from internal APIs), it is also possible
- to define a process using the Process API directly. The most important process
- elements are defined in the packages <code>org.drools.workflow.core</code> and
- <code>org.drools.workflow.core.node</code>. A "fluent API" is provided that
- allows you to easily construct processes in a readable manner using factories.
- At the end, you can validate the process that you were constructing manually.
- Some examples about how to build processes using this fluent API are added below.</para>
-
-
- <section>
- <title>Example 1</title>
-
- <para>This is a simple example of a basic process with a ruleset node only:</para>
- <programlisting role="JAVA">
-RuleFlowProcessFactory factory =
- RuleFlowProcessFactory.createProcess("org.drools.HelloWorldRuleSet");
-factory
- // Header
- .name("HelloWorldRuleSet")
- .version("1.0")
- .packageName("org.drools")
- // Nodes
- .startNode(1).name("Start").done()
- .ruleSetNode(2)
- .name("RuleSet")
- .ruleFlowGroup("someGroup").done()
- .endNode(3).name("End").done()
- // Connections
- .connection(1, 2)
- .connection(2, 3);
-RuleFlowProcess process = factory.validate().getProcess();</programlisting>
-
- <para>You can see that we start by calling the static <code>createProcess()</code>
- method from the <code>RuleFlowProcessFactory</code> class. This method creates
- a new process with the given id and returns the <code>RuleFlowProcessFactory</code>
- that can be used to create the process. A typical process consists of three parts.
- The header part comprises global elements like the name of the process, imports,
- variables, etc. The nodes section contains all the different nodes that are part of the
- process. The connections section finally links these nodes to each other
- to create a flow chart.</para>
-
- <para>In this example, the header contains the name and the version of the
- process and the package name. After that, you can start adding nodes to the
- current process. If you have auto-completion you can see that you have
- different methods to create each of the supported node types at your disposal.</para>
-
- <para>When you start adding nodes to the process, in this example by calling
- the <code>startNode()</code>, <code>ruleSetNode()</code> and <code>endNode()</code>
- methods, you can see that these methods return a specific <code>NodeFactory</code>,
- that allows you to set the properties of that node. Once you have finished
- configuring that specific node, the <code>done()</code> method returns you to the
- current <code>RuleFlowProcessFactory</code> so you can add more nodes, if necessary.</para>
-
- <para>When you are finished adding nodes, you must connect them by creating
- connections between them. This can be done by calling the method
- <code>connection</code>, which will link previously created nodes.</para>
-
- <para>Finally, you can validate the generated process by calling the
- <code>validate()</code> method and retrieve the created
- <code>RuleFlowProcess</code> object.</para>
-
- </section>
-
- <section>
- <title>Example 2</title>
-
- <para>This example is using Split and Join nodes:</para>
- <programlisting role="JAVA">
-RuleFlowProcessFactory factory =
- RuleFlowProcessFactory.createProcess("org.drools.HelloWorldJoinSplit");
-factory
- // Header
- .name("HelloWorldJoinSplit")
- .version("1.0")
- .packageName("org.drools")
- // Nodes
- .startNode(1).name("Start").done()
- .splitNode(2).name("Split").type(Split.TYPE_AND).done()
- .actionNode(3).name("Action 1")
- .action("mvel", "System.out.println(\"Inside Action 1\")").done()
- .actionNode(4).name("Action 2")
- .action("mvel", "System.out.println(\"Inside Action 2\")").done()
- .joinNode(5).type(Join.TYPE_AND).done()
- .endNode(6).name("End").done()
- // Connections
- .connection(1, 2)
- .connection(2, 3)
- .connection(2, 4)
- .connection(3, 5)
- .connection(4, 5)
- .connection(5, 6);
-RuleFlowProcess process = factory.validate().getProcess();</programlisting>
-
- <para>This shows a simple example using Split and Join nodes. As you can see,
- a Split node can have multiple outgoing connections, and a Join node multiple
- incoming connections. To understand the behavior of the different types
- of Split and Join nodes, take a look at the documentation for each of these
- nodes.</para>
-
- </section>
-
- <section>
- <title>Example 3</title>
-
- <para>Now we show a more complex example with a ForEach node, where we have nested nodes:</para>
- <programlisting role="JAVA">
-RuleFlowProcessFactory factory =
- RuleFlowProcessFactory.createProcess("org.drools.HelloWorldForeach");
-factory
- // Header
- .name("HelloWorldForeach")
- .version("1.0")
- .packageName("org.drools")
- // Nodes
- .startNode(1).name("Start").done()
- .forEachNode(2)
- // Properties
- .linkIncomingConnections(3)
- .linkOutgoingConnections(4)
- .collectionExpression("persons")
- .variable("child", new ObjectDataType("org.drools.Person"))
- // Nodes
- .actionNode(3)
- .action("mvel", "System.out.println(\"inside action1\")").done()
- .actionNode(4)
- .action("mvel", "System.out.println(\"inside action2\")").done()
- // Connections
- .connection(3, 4)
- .done()
- .endNode(5).name("End").done()
- // Connections
- .connection(1, 2)
- .connection(2, 5);
-RuleFlowProcess process = factory.validate().getProcess();</programlisting>
-
- <para>Here you can see how we can include a ForEach node with nested action nodes.
- Note the <code>linkIncomingConnections()</code> and
- <code>linkOutgoingConnections()</code> methods that are
- called to link the ForEach node with the internal action node.
- These methods are used to specify the first and last nodes inside the ForEach
- composite node.</para>
-
- </section>
-
- </section>
-
- </section>
-
- <section>
- <title>Using a Process in Your Application</title>
-
- <para>There are two things you need to do to be able to execute processes from
- within your application: (1) you need to create a Knowledge Base that contains
- the definition of the process, and (2) you need to start the process by creating
- a session to communicate with the process engine and start the process.</para>
-
- <orderedlist>
-
- <listitem><para><emphasis>Creating a Knowledge Base</emphasis>: Once you
- have a valid process, you can add the process to the Knowledge Base. Note
- that this is almost identical to adding rules to the Knowledge Base, except
- for the type of knowledge added:</para>
- <programlisting role="JAVA">
-KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-kbuilder.add( ResourceFactory.newClassPathResource("MyProcess.rf"),
- ResourceType.DRF );</programlisting>
- <para>After adding all your knowledge to the builder (you can add more
- than one process, and even rules), you should probably check whether the
- process (and rules) have been parsed correctly and write out any errors
- like this:</para>
- <programlisting role="JAVA">
-KnowledgeBuilderErrors errors = kbuilder.getErrors();
-if (errors.size() > 0) {
- for (KnowledgeBuilderError error: errors) {
- System.err.println(error);
- }
- throw new IllegalArgumentException("Could not parse knowledge.");
-}</programlisting>
- <para>Next, you need to create the Knowledge Base that contains all the necessary
- processes (and rules) like this:</para>
- <programlisting role="JAVA">
-KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
-kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());</programlisting>
- </listitem>
-
- <listitem><para><emphasis>Starting a process</emphasis>: Processes are
- only executed if you explicitly state that they should be executed. This
- is because you could potentially define a lot of processes in your
- Knowledge Base and the engine has no way to know when you would like
- to start each of these. To activate a particular process, you will need
- to start it by calling the <code>startProcess</code> method on your session.
- For example:</para>
- <programlisting role="JAVA">
-StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
-ksession.startProcess("com.sample.MyProcess");</programlisting>
- <para>The parameter of the <code>startProcess</code> method represents the id
- of the process that needs to be started. This process id needs to be
- specified as a property of the process, shown in the Properties View
- when you click the background canvas of your process. If your process
- also requires the execution of rules during the execution of the process,
- you also need to call the <code>ksession.fireAllRules()</code> method to
- make sure the rules are executed as well. That's it!</para>
-
- <para>You may specify additional parameters that are used to pass
- on input data to the process, using the
- <code>startProcess(String processId, Map parameters)</code> method, which
- takes an additional set of parameters as name-value pairs. These parameters
- are then copied to the newly created process instance as top-level variables
- of the process.</para>
-
- <para>You can also start a process from within a rule consequence, using</para>
- <programlisting role="JAVA">
-kcontext.getKnowledgeRuntime().startProcess("com.sample.MyProcess");</programlisting>
- </listitem>
-
- </orderedlist>
-
- </section>
-
- <section>
- <title>Detailed Explanation of the Different Node Types</title>
-
- <para>A ruleflow process is a flow chart where different types of nodes are
- linked using connections. The process itself exposes the following properties:
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The unique id of the process.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the process.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Version</emphasis>: The version number of the process.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Package</emphasis>: The package (namespace) the process is
- defined in.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Variables</emphasis>: Variables can be defined to store data
- during the execution of your process. See section
- <quote><link linkend='sec.data' endterm="sec.data.title"/></quote>
- for details.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Swimlanes</emphasis>: Specify the actor responsible for the
- execution of human tasks. See chapter
- <quote><link linkend='ch.Human_Tasks' endterm="ch.Human_Tasks.title"/></quote>
- for details.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Exception Handlers</emphasis>: Specify the behaviour when a fault
- occurs in the process. See section
- <quote><link linkend='sec.exceptions' endterm="sec.exceptions.title"/></quote>
- for details.</para>
- </listitem>
-
- <listitem>
- <para><emphasis>Connection Layout</emphasis>: Specify how the connections are
- visualized on the canvas using the connection layout property:
- <itemizedlist>
- <listitem>
- <para>'Manual' always draws your connections as lines going straight from
- their start to end point (with the possibility to use intermediate break
- points).</para>
- </listitem>
- <listitem>
- <para>'Shortest path' is similar, but it tries to go around any obstacles
- it might encounter between the start and end point, to avoid lines crossing
- nodes.</para>
- </listitem>
- <listitem>
- <para>'Manhattan' draws connections by only using horizontal and vertical
- lines.</para>
- </listitem>
- </itemizedlist></para>
- </listitem>
- </itemizedlist>
- </para>
-
- <para>A RuleFlow process supports different types of nodes:
-
- <figure>
- <title>The different types of ruleflow nodes</title>
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/ruleflow_nodes.png" format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <orderedlist>
-
- <!-- START -->
- <listitem>
- <para><emphasis role="strong">Start</emphasis>: The start of the ruleflow.
- A ruleflow should have exactly one start node, which cannot have
- incoming connections and should have one outgoing connection. Whenever a
- RuleFlow process is started, execution will start at this node and
- automatically continue to the first node linked to this start node, and
- so on. It contains the following properties:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Triggers</emphasis>: A Start node can also specify additional
- triggers that can be used to automatically start the process. Examples are a
- "constraint" trigger that automatically starts the process if a given rule or
- constraint is satisfied, or an "event" trigger that automatically starts the
- process if a specific event is signalled.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- END -->
- <listitem>
- <para><emphasis role="strong">End</emphasis>: The end of the ruleflow. A ruleflow
- should have one or more End nodes. The End node should have one incoming
- connection and cannot have outgoing connections. It contains the following
- properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique within
- one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Terminate</emphasis>: An End node can be terminating for
- the entire process (default) or just for the path. If the process is
- terminated, all nodes that are still active (on parallel paths) in this
- ruleflow are cancelled. Non-terminating End nodes are simply ends for
- some path, while other parallel paths still continue.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- RULESET -->
- <listitem>
- <para><emphasis role="strong">RuleFlowGroup</emphasis>: Represents a set
- of rules that need to be evaluated. The rules are evaluated when the node
- is reached. A RuleFlowGroup node should have one incoming connection and
- one outgoing connection. Rules can become part of a specific ruleflow group
- using the <literal>ruleflow-group</literal> attribute in the header. When a RuleFlowGroup node
- is reached in the ruleflow, the engine will start executing rules that are
- part of the corresponding ruleflow-group (if any). Execution will
- automatically continue to the next node if there are no more active rules in
- this ruleflow group. This means that, during the execution of a ruleflow group,
- it is possible that new activations belonging to the currently active
- ruleflow group are added to the Agenda due to changes made to the facts by
- the other rules. Note that the ruleflow will immediately continue with the
- next node if it encounters a ruleflow group where there are no active rules
- at that time. If the ruleflow group was already active, the ruleflow group
- will remain active and execution will only continue if all active rules of the
- ruleflow group has been completed. It contains the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique within
- one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>RuleFlowGroup</emphasis>: The name of the ruleflow group
- that represents the set of rules of this RuleFlowGroup node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Timers</emphasis>: Timers that are linked to this node.
- See section
- <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
- for details.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- SPLIT -->
- <listitem>
- <para><emphasis role="strong">Split</emphasis>: Allows you to create branches
- in your ruleflow. A Split node should have one incoming connection and two or
- more outgoing connections. There are three types of Split nodes currently
- supported:
- <itemizedlist>
- <listitem>
- <para>AND means that the control flow will continue in all outgoing
- connections simultaneously.</para>
- </listitem>
- <listitem>
- <para>XOR means that exactly one of the outgoing connections will
- be chosen. The decision is made by evaluating the constraints
- that are linked to each of the outgoing connections. Constraints are
- specified using the same syntax as the left-hand side of a rule. The
- constraint with the <emphasis>lowest</emphasis> priority number that
- evaluates to true is selected. Note that you should always make sure
- that at least one of the outgoing connections will evaluate to true
- at runtime (the ruleflow will throw an exception at runtime if it
- cannot find at least one outgoing connection). For example, you could use a
- connection which is always true (default) with a <emphasis>high</emphasis>
- priority number to specify what should happen if none of the other
- connections can be taken.</para>
- </listitem>
- <listitem>
- <para>OR means that all outgoing connections whose condition evaluates
- to true are selected. Conditions are similar to the XOR split, except
- that no priorities are taken into account. Note that you should
- make sure that at least one of the outgoing connections will evaluate
- to true at runtime because the ruleflow will throw an exception at
- runtime if it cannot determine an outgoing connection.
- </para>
- </listitem>
- </itemizedlist>
- It contains the following properties:
- </para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique within
- one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Type</emphasis>: The type of the split node, i.e., AND,
- XOR or OR (see above).</para>
- </listitem>
- <listitem><para><emphasis>Constraints</emphasis>: The constraints linked
- to each of the outgoing connections (in case of an (X)OR split).</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- JOIN -->
- <listitem>
- <para><emphasis role="strong">Join</emphasis>: Allows you to synchronize
- multiple branches. A join node should have two or more incoming connections
- and one outgoing connection. There are four types of splits currently supported:
- <itemizedlist>
- <listitem>
- <para>AND means that is will wait until <emphasis>all</emphasis> incoming
- branches are completed before continuing.
- </para>
- </listitem>
- <listitem>
- <para>XOR means that it continues as soon as <emphasis>one</emphasis> of its
- incoming branches has been completed. If it is triggered from more than one
- incoming connection, it will trigger the next node for each of those triggers.</para>
- </listitem>
- <listitem>
- <para>Discriminator means that it continues if one of its incoming
- branches has been completed. Completions of other incoming branches
- are registered until all connections have completed. At that point, the
- node will be reset, so that it can trigger again when one of its
- incoming branches has been completed once more.</para>
- </listitem>
- <listitem>
- <para>n-of-m means that it continues if <emphasis>n</emphasis> of its
- <emphasis>m</emphasis> incoming branches
- have been completed. The variable <emphasis>n</emphasis> could either
- be hardcoded to a fixed value, or refer to a process variable that will
- contain the number of incoming branches to wait for.</para>
- </listitem>
- </itemizedlist>
- It contains the following properties:
- </para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Type</emphasis>: The type of the Join node, i.e. AND,
- XOR or Discriminator (see above).</para>
- </listitem>
- <listitem>
- <para><emphasis>n</emphasis>: The number of incoming connections to
- wait for (in case of a n-of-m join).</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- EVENT WAIT -->
- <listitem>
- <para><emphasis role="strong">EventWait</emphasis>
- (or <emphasis role="strong">Milestone</emphasis>):
- Represents a wait state. An EventWait should have one incoming connection
- and one outgoing connection. It specifies a constraint which defines how
- long the process should wait in this state before continuing. For example,
- a constraint in an order entry application might specify that the process
- should wait until no more errors are found in the given order. Constraints
- are specified using the same syntax as the left-hand side of a rule. When
- a Wait node is reached in the ruleflow, the engine will check the associated
- constraint. If the constraint evaluates to true directly, the flow will
- continue imediately. Otherwise, the flow will continue if the constraint
- is satisfied later on, for example when a fact is inserted, updated or
- removed from the working memory. It contains the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique within
- one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Constraint</emphasis>: Defines when the process can
- leave this state and continue.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- SUBPROCESS -->
- <listitem>
- <para><emphasis role="strong">SubFlow</emphasis>: represents the invocation
- of another process from within this process. A sub-process node should
- have one incoming connection and one outgoing connection. When a SubFlow
- node is reached in the ruleflow, the engine will start the process with the
- given id. It contains the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique within
- one node container).</para></listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>ProcessId</emphasis>: The id of the process that should
- be executed.</para>
- </listitem>
- <listitem>
- <para><emphasis>Wait for completion</emphasis>: If this property is true,
- the SubFlow node will only continue if that SubFlow process has
- terminated its execution (completed or aborted); otherwise it will continue
- immediately after starting the subprocess.</para>
- </listitem>
- <listitem>
- <para><emphasis>Independent</emphasis>: If this property is true, the
- subprocess is started as an independent process, which means that the
- SubFlow process will not be terminated if this process reaches an end node;
- otherwise the active sub-process will be cancelled on termination (or abortion)
- of the process.</para>
- </listitem>
- <listitem>
- <para><emphasis>On-entry and on-exit actions</emphasis>: Actions that are
- executed upon entry or exit of this node, respectively.</para>
- </listitem>
- <listitem>
- <para><emphasis>Parameter in/out mapping</emphasis>: A SubFlow node can
- also define in- and out-mappings for variables. The value of variables
- in this process with variable names given in the "in" mapping will be used
- as parameters (with the associated parameter name) when starting the process.
- The value of the variables in the subprocess with the given variable name
- in the "out" mappings will be copied to the variables of this process when the
- subprocess has been completed. Note that you can use "out" mappings only when
- "Wait for completion" is set to true.</para>
- </listitem>
- <listitem>
- <para><emphasis>Timers</emphasis>: Timers that are linked to this node.
- See section
- <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
- for details.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- ACTION -->
- <listitem>
- <para><emphasis role="strong">Action</emphasis>: represents an action that
- should be executed in this ruleflow. An Action node should have one incoming
- connection and one outgoing connection. The associated action specifies what
- should be executed, the dialect used for coding the action (i.e., Java or MVEL),
- and the actual action code. This code can access any globals, the predefined
- variable <code>drools</code> referring to a <code>KnowledgeHelper</code> object
- (which can, for example,
- be used to retrieve the Working Memory by calling
- <code>drools.getWorkingMemory()</code>), and the variable <code>context</code>
- that references the <code>ProcessContext</code> object (which can,
- for example, be used to access the current <code>ProcessInstance</code> or
- <code>NodeInstance</code>, and to get and set variables). When an Action node
- is reached in the ruleflow, it will execute the action and then continue with the
- next node. It contains the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique within
- one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Action</emphasis>: The action associated with this
- action node.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- TIMER -->
- <listitem>
- <para><emphasis role="strong">Timer</emphasis>: represents a timer that can
- trigger one or multiple times after a given period of time. A Timer node
- should have one incoming connection and one outgoing connection. The timer
- delay specifies how long (in milliseconds) the timer should wait before
- triggering the first time. The timer period specifies the time between two
- subsequent triggers. A period of 0 means that the timer should only be
- triggered once. When a Timer node is reached in the ruleflow, it will
- start the associated timer. The timer is cancelled if the timer node is
- cancelled (e.g., by completing or aborting the process). Consult the
- section <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
- for more information. - The Timer node contains the
- following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Timer delay</emphasis>: The delay (in milliseconds)
- that the node should wait before triggering the first time.</para>
- </listitem>
- <listitem>
- <para><emphasis>Timer period</emphasis>: The period (in milliseconds)
- between two subsequent triggers. If the period is 0, the timer should
- only be triggered once.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- FAULT -->
- <listitem>
- <para><emphasis role="strong">Fault</emphasis>: A Fault node can be used
- to signal an exceptional condition in the process. It should
- have one incoming connection and no outgoing connections. When a Fault
- node is reached in the ruleflow, it will throw a fault with the given name.
- The process will search for an appropriate exception handler that is
- capable of handling this kind of fault. If no fault handler is found,
- the process instance will be aborted. A Fault node contains the following
- properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>FaultName</emphasis>: The name of the fault. This
- name is used to search for appriopriate exception handlers that is
- capable of handling this kind of fault.</para>
- </listitem>
- <listitem>
- <para><emphasis>FaultVariable</emphasis>: The name of the variable
- that contains the data associated with this fault. This data is also
- passed on to the exception handler (if one is found).</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- EVENT -->
- <listitem>
- <para><emphasis role="strong">Event</emphasis>: An Event node can be used
- to respond to internal or external events during the execution of the process.
- An Event node should have no incoming connections and one outgoing
- connection. It specifies the type of event that is expected. Whenever
- that type of event is detected, the node connected to this Event node will
- be triggered. It contains the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>EventType</emphasis>: The type of event that is
- expected.</para>
- </listitem>
- <listitem>
- <para><emphasis>VariableName</emphasis>: The name of the variable that
- will contain the data associated with this event (if any) when this
- event occurs.</para>
- </listitem>
- <listitem>
- <para><emphasis>Scope</emphasis>: An event could be used to listen
- to internal events only, i.e., events that are signalled to this
- process instance directly, using
- <code>processInstance.signalEvent(String type, Object data)</code>.
- When an Event node is defined as external, it will also be listening
- to external events that are signalled to the process engine directly,
- using <code>workingMemory.signalEvent(String type, Object event)</code>.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- HUMAN TASK -->
- <listitem>
- <para><emphasis role="strong">Human Task</emphasis>: Processes can also
- involve tasks that need to be executed by human actors. A Human Task node
- represents an atomic task to be executed by a human actor. It
- should have one incoming connection and one outgoing connection.
- Human Task nodes can be used in combination with Swimlanes to assign multiple
- human tasks to similar actors. Refer to chapter
- <quote><link linkend='ch.Human_Tasks' endterm="ch.Human_Tasks.title"/></quote>
- for more details. A Human Task node is actually nothing more than a specific
- type of work item node (of type "Human Task"). A Human Task node contains
- the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>TaskName</emphasis>: The name of the human task.</para>
- </listitem>
- <listitem>
- <para><emphasis>Priority</emphasis>: An integer indicating the priority
- of the human task.</para>
- </listitem>
- <listitem>
- <para><emphasis>Comment</emphasis>: A comment associated with the human
- task.</para>
- </listitem>
- <listitem>
- <para><emphasis>ActorId</emphasis>: The actor id that is responsible for
- executing the human task. A list of actor id's can be specified using
- a comma (',') as separator.</para>
- </listitem>
- <listitem>
- <para><emphasis>Skippable</emphasis>: Specifies whether the human task
- can be skipped, i.e., whether the actor may decide not to execute the
- task.</para>
- </listitem>
- <listitem>
- <para><emphasis>Content</emphasis>: The data associated with this task.</para>
- </listitem>
- <listitem>
- <para><emphasis>Swimlane</emphasis>: The swimlane this human task node
- is part of. Swimlanes make it easy to assign multiple human tasks to
- the same actor. See the human tasks chapter for more detail on how to
- use swimlanes.</para>
- </listitem>
- <listitem>
- <para><emphasis>Wait for completion</emphasis>: If this property is true,
- the human task node will only continue if the human task has been
- terminated (i.e., by completing or reaching any other terminal state);
- otherwise it will continue immediately after creating the human task.</para>
- </listitem>
- <listitem>
- <para><emphasis>On.entry and on-exit actions</emphasis>: Actions that are
- executed upon entry and exit of this node, respectively.</para>
- </listitem>
- <listitem>
- <para><emphasis>Parameter mapping</emphasis>: Allows copying the value
- of process variables to parameters of the human task. Upon creation of
- the human tasks, the values will be copied.</para>
- </listitem>
- <listitem>
- <para><emphasis>Result mapping</emphasis>: Allows copying the value
- of result parameters of the human task to a process variable. Upon
- completion of the human task, the values will be copied. Note that
- you can use result mappings only when "Wait for completion" is set to
- true. A human task has a result variable "Result" that contains
- the data returned by the human actor. The variable "ActorId" contains
- the id of the actor that actually executed the task.</para>
- </listitem>
- <listitem>
- <para><emphasis>Timers</emphasis>: Timers that are linked to this
- node. Consult the section
- <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
- for details.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- COMPOSITE -->
- <listitem>
- <para><emphasis role="strong">Composite</emphasis>: A Composite node is
- a node that can contain other nodes so that it acts as a node container.
- This allows not only the embedding of a part of the flow within such
- a Composite node, but also the definition of additional variables and
- exception handlers that are accessible for all nodes inside this
- container. A Composite node should have one incoming connection and one
- outgoing connection. It contains the following properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>StartNodeId</emphasis>: The id of the node (within
- this node container) that should be triggered when this node is
- triggered.</para>
- </listitem>
- <listitem>
- <para><emphasis>EndNodeId</emphasis>: The id of the node (within
- this node container) that represents the end of the flow contained
- in this node. When this node is completed, the composite node will
- also be completed and trigger its outgoing connection. All other
- executing nodes within this composite node will be cancelled.</para>
- </listitem>
- <listitem>
- <para><emphasis>Variables</emphasis>: Additional variables can be
- defined to store data during the execution of this node. See section
- <quote><link linkend='sec.data' endterm="sec.data.title"/></quote>
- for details.</para>
- </listitem>
- <listitem>
- <para><emphasis>Exception Handlers</emphasis>: Specify the behavior
- when a fault occurs in this node container. See section
- <quote><link linkend='sec.exceptions' endterm="sec.exceptions.title"/></quote>
- for details.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- FOR EACH -->
- <listitem>
- <para><emphasis role="strong">ForEach</emphasis>: A ForEach node is a
- special kind of composite node that allows you to execute the contained
- flow multiple times, once for each element in a collection. A ForEach
- node should have one incoming connection and one outgoing connection. A
- ForEach node awaits the completion of the embedded flow for each of the
- collection''s elements before continuing. It contains the following
- properties:</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which
- is unique within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>StartNodeId</emphasis>: The id of the node (within
- this node container) that should be triggered for each of the
- elements in a collection.</para>
- </listitem>
- <listitem>
- <para><emphasis>EndNodeId</emphasis>: The id of the node (within
- this node container) that represents the end of the flow contained
- in this node. When this node is completed, the execution of the
- ForEach node will also be completed for the current collection element.
- The outgoing connection is triggered if the collection is exhausted.
- All other executing nodes within this composite node will be cancelled.</para>
- </listitem>
- <listitem>
- <para><emphasis>CollectionExpression</emphasis>: The name of a
- variable that represents the collection of elements that should
- be iterated over. The collection variable should be of type
- <code>java.util.Collection</code>.</para>
- </listitem>
- <listitem>
- <para><emphasis>VariableName</emphasis>: The name of the variable
- to contain the current element from the collection. This
- gives nodes within the composite node access to the selected
- element.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- <!-- WORK ITEMS -->
- <listitem>
- <para><emphasis role="strong">WorkItem</emphasis>: Represents an (abstract)
- unit of work that should be executed in this process. All work that is
- executed outside the process engine should be represented (in a declarative
- way) using a WorkItem node. Different types of work items are predefined, e.g.,
- sending an email, logging a message, etc. Users can define domain-specific
- work items, using a unique name and by defining
- the parameters (input) and results (output) that are associated with this
- type of work. Refer to the chapter
- <quote><link linkend='ch.Domain_Specific_Processes'
- endterm="ch.Domain_Specific_Processes.title"/></quote> for a
- detailed explanation and illustrative examples of how to define and use
- work items in your processes. When a WorkItem node is reached in the
- process, the associated work item is executed. A WorkItem node should
- have one incoming connection and one outgoing connection.</para>
- <itemizedlist>
- <listitem>
- <para><emphasis>Id</emphasis>: The id of the node (which is unique
- within one node container).</para>
- </listitem>
- <listitem>
- <para><emphasis>Name</emphasis>: The display name of the node.</para>
- </listitem>
- <listitem>
- <para><emphasis>Wait for completion</emphasis>: If the property
- "Wait for completion" is true, the WorkItem node will only continue
- if the created work item has terminated (completed or aborted)
- its execution; otherwise it will continue immediately after
- starting the work item.</para>
- </listitem>
- <listitem>
- <para><emphasis>Parameter mapping</emphasis>: Allows copying the
- value of process variables to parameters of the work item. Upon
- creation of the work item, the values will be copied.</para>
- </listitem>
- <listitem>
- <para><emphasis>Result mapping</emphasis>: Allows copying the value
- of result parameters of the work item to a process variable. Each
- type of work can define result parameters that will (potentially)
- be returned after the work item has been completed. A result
- mapping can be used to copy the value of the given result parameter
- to the given variable in this process. For example, the "FileFinder"
- work item returns a list of files that match the given search
- criteria within the result parameter <code>Files</code>. This list
- of files can then be bound to a process variable for use within the
- process. Upon completion of the work item, the values will be copied.
- Note that you can use result mappings only when "Wait for completion"
- is set to true.</para>
- </listitem>
- <listitem>
- <para><emphasis>On-entry and on-exit actions</emphasis>: Actions that are
- executed upon entry or exit of this node, respectively.</para>
- </listitem>
- <listitem>
- <para><emphasis>Timers</emphasis>: Timers that are linked to this
- node. See the section
- <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
- for details.</para>
- </listitem>
- <listitem>
- <para><emphasis>Additional parameters</emphasis>: Each type of work
- item can define additional parameters that are relevant for that
- type of work. For example, the "Email" work item defines additional
- parameters such as <code>From</code>, <code>To</code>, <code>Subject</code>
- and <code>Body</code>. The user can either provide values for these
- parameters directly, or define a
- parameter mapping that will copy the value of the given variable
- in this process to the given parameter; if both are specified, the
- mapping will have precedence. Parameters of type <code>String</code> can use
- <emphasis><code>#{expression}</code></emphasis> to embed a value in the
- string. The value will be retrieved when creating the work item, and the
- substitution expression will be replaced by the result of calling
- <code>toString()</code> on the variable. The expression could
- simply be the name of a variable (in which case it resolves
- to the value of the variable), but more advanced MVEL expressions
- are possible as well, e.g., <code>#{person.name.firstname}</code>.</para>
- </listitem>
- </itemizedlist>
- </listitem>
-
- </orderedlist>
- </para>
- </section>
-
- <section id='sec.data'>
- <title id='sec.data.title'>Data</title>
-
- <para>While the flow graph focusses on specifying the control flow of the
- process, it is usually also necessary to look at the process from a data
- perspective. Throughout the execution of a process, data can retrieved,
- stored, passed on and used.</para>
-
- <para>For storing runtime data, during the execution of the process,
- you use variables. A variable is defined by a name and a data type. This
- could be a basic data type, such as boolean, int, or String, or any kind of
- Object subclass. Variables can be defined inside a variable
- <emphasis>scope</emphasis>. The top-level
- scope is the variable scope of the process itself. Subscopes can be
- defined using a Composite node. Variables that are defined in a subscope
- are only accessible for nodes within that scope.</para>
-
- <para>Whenever a variable is accessed, the process will search for the
- appropriate variable scope that defines the variable. Nesting of variable
- scopes is allowed. A node will always search for a variable in its parent
- container. If the variable cannot be found, it will look in that one's
- parent container, and so on, until the process instance itself is reached.
- If the variable cannot be found, a read access yields null, and a write
- access produces an error message, with the process continuing its
- execution.</para>
-
- <para>Variables can be used in various ways:</para>
- <itemizedlist>
- <listitem><para>Process-level variables can be set when starting a process
- by providing a map of parameters to the invocation of the
- <code>startProcess</code> method. These parameters will be set as
- variables on the process scope.</para>
- </listitem>
- <listitem><para>Actions can access variables directly, simply by using the
- name of the variable as a parameter name.</para>
- <programlisting role="JAVA">
-// call method on the process variable "person"
-person.setAge(10);</programlisting>
- <para>Changing the value of a variable can be done through the Knowledge Context:</para>
- <programlisting role="JAVA">
-kcontext.setVariable(variableName, value);</programlisting>
- </listitem>
- <listitem><para>WorkItem and SubFlow nodes can pass the value of parameters
- to the outside world by mapping the variable to one of the work item
- parameters, either by using a parameter mapping or by interpolating
- it into a String parameter, using
- <emphasis><code>#{expression}</code></emphasis>. The results of a WorkItem
- can also be copied to a variable using a result mapping.</para>
- </listitem>
- <listitem><para>Various other nodes can also access data. Event nodes, for
- example, can store the data associated to the event in a variable,
- exception handlers can read error data from a specific variable, etc.
- Check the properties of the different node types for more information.</para>
- </listitem>
- </itemizedlist>
-
- <para>Finally, processes and rules all have access to globals, i.e.,
- globally defined variables that are considered immutable with regard
- to rule evaluation, and data in the Knowledge Session. The Knowledge Session
- can be accessed in actions using the Knowledge Context:</para>
- <programlisting role="JAVA">
-kcontext.getKnowledgeRuntime().insert( new Person(...) );</programlisting>
-
- </section>
-
- <section>
- <title>Constraints</title>
-
- <para>Constraints can be used in various locations in your processes,
- for example in a Split node using OR or XOR decisions, or as a
- constraint for an EventWait. Drools Flow supports two types of constraints:</para>
- <itemizedlist>
- <listitem><para><emphasis>Code constraints</emphasis> are boolean expressions,
- evaluated directly whenever they are reached. We currently support two
- dialects for expressing these code constraints: Java and MVEL.
- Both Java and MVEL code constraints have direct access
- to the globals and variables defined in the process. Here is an example
- of a valid Java code constraint, <code>person</code> being a variable
- in the process:</para>
- <programlisting role="JAVA">
-return person.getAge() > 20;</programlisting>
- <para>A similar example of a valid MVEL code constraint is:</para>
- <programlisting>
-return person.age > 20;</programlisting>
- </listitem>
- <listitem><para><emphasis>Rule constraints</emphasis> are equals to normal
- Drools rule conditions. They use the Drools Rule Language syntax to
- express possibly complex constraints. These rules can, like any other
- rule, refer to data in the Working Memory. They can also refer to
- globals directly. Here is an example of a valid rule constraint:</para>
- <programlisting
->Person( age > 20 )</programlisting>
- <para>This tests for a person older than 20 being in the Working
- Memory.</para></listitem>
- </itemizedlist>
-
- <para>Rule constraints do not have direct access to variables defined
- inside the process. It is however possible to refer to the current process
- instance inside a rule constraint, by adding the process instance to the
- Working Memory and matching for the process instance in your rule
- constraint. We have added special logic to make sure that a variable
- <code>processInstance</code> of type <code>WorkflowProcessInstance</code>
- will only match to the current process instance and not to other process
- instances in the Working Memory. Note that you are however responsible
- yourself to insert the process instance into the session and, possibly,
- to update it, for example, using Java code or an on-entry or on-exit or
- explicit action in your process. The following example of a rule
- constraint will search for a person with the same name as the value
- stored in the variable "name" of the process:</para>
-
- <programlisting>processInstance : WorkflowProcessInstance()
-Person( name == ( processInstance.getVariable("name") ) )
-# add more constraints here ...</programlisting>
- </section>
-
-
- <section>
- <title>Actions</title>
-
- <para>Actions can be used in different ways:
- <itemizedlist>
- <listitem>Within an Action node,</listitem>
- <listitem>As entry or exit actions, with a number of nodes,</listitem>
- <listitem>Actions specifying the behavior of exception handlers.</listitem>
- </itemizedlist>
- </para>
-
- <para>Actions have access to globals and the variables that are defined
- for the process and the predefined variable <code>context</code>. This
- variable is of type
- <code>org.drools.runtime.process.ProcessContext</code> and can be used for
- several tasks:</para>
- <itemizedlist>
- <listitem><para>Getting the current node instance (if applicable). The node
- instance could be queried for data, such as its name and type. You can
- also cancel the current node instance.</para>
- <programlisting role="JAVA">
-NodeInstance node = context.getNodeInstance();
-String name = node.getNodeName();</programlisting>
- </listitem>
- <listitem><para>Getting the current process instance. A process instance
- can be queried for data (name, id, processId, etc.), aborted or
- signalled an internal event.</para>
- <programlisting role="JAVA">
-WorkflowProcessInstance proc = context.getProcessInstance();
-proc.signalEvent( type, eventObject );</programlisting>
- </listitem>
- <listitem><para>Getting or setting the value of variables.</para></listitem>
- <listitem><para>Accessing the Knowledge Runtime allows you do things
- like starting a process, signalling external events, inserting data,
- etc.</para></listitem>
- </itemizedlist>
-
- <para>Drools currently supports two dialects, Java and MVEL.
- Java actions should be valid Java code. MVEL actions can use the business
- scripting language MVEL to express the action. MVEL accepts any valid Java
- code but additionally provides support for nested accesses of parameters
- (e.g., <code>person.name</code> instead of <code>person.getName()</code>),
- and many other scripting improvements. Thus, MVEL expressions are more
- convenient for the business user. For example, an action that prints out
- the name of the person in the "requester" variable of the process would
- look like this:</para>
-
- <programlisting>
-// Java dialect
-System.out.println( person.getName() );
-
-// MVEL dialect
-System.out.println( person.name );
- </programlisting>
- </section>
-
- <section>
- <title>Events</title>
-
- <figure>
- <title>A sample process using events</title>
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/EventProcess.png" format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>During the execution of a process, the process engine makes sure that all the relevant
- tasks are executed according to the process plan, by requesting the execution of work items
- and waiting for the results. However, it is also possible that the process should respond to
- events that were not directly requested by the process engine. Explicitly representing these
- events in a process allows the process author to specify how the process should react
- to such events.</para>
-
- <para>Events have a type and possibly data associated with them. Users are free to define
- their own event types and their associated data.</para>
-
- <para>A process can specify how to respond to events by using Event nodes. An Event
- node needs to specify the type of event the node is interested in. It can also define
- the name of a variable, which will receive the data that is associated with the event.
- This allows subsequent nodes in the process to access the event data and take appropriate
- action based on this data.</para>
-
- <para>An event can be signalled to a running instance of a process in a number of ways:</para>
- <itemizedlist>
- <listitem><para>Internal event: Any action inside a process (e.g., the action of an
- action node, or an on-entry or on-exit action of some node) can signal the
- occurence of an internal event to the surrounding process instance, using code
- like the following:</para>
- <programlisting role="JAVA">
-context.getProcessInstance().signalEvent(type, eventData);</programlisting></listitem>
- <listitem><para>External event: A process instance can be notified of an event
- from outside using code such as:</para>
- <programlisting role="JAVA">
-processInstance.signalEvent(type, eventData);</programlisting></listitem>
- <listitem><para>External event using event correlation: Instead of notifying a
- process instance directly, it is also possible to have the engine
- automatically determine which process instances might be interested
- in an event using <emphasis>event correlation</emphasis>, which is based
- on the event type. A process instance that contains an event node
- listening to external events of some type is notified whenever such
- an event occurs. To signal such an event to the process engine, write
- code such as:</para>
- <programlisting role="JAVA">
-workingMemory.signalEvent(type, eventData);</programlisting></listitem>
- </itemizedlist>
-
- <para>Events could also be used to start a process. Whenever a Start node
- defines an event trigger of a specific type, a new process instance will be
- started every time that type of event is signalled to the process engine.</para>
-
- </section>
-
- <section id="sec.exceptions">
- <title id="sec.exceptions.title">Exceptions</title>
-
- <figure>
- <title>A sample process using exception handlers</title>
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/FaultProcess.png" format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>Whenever an exceptional condition occurs during the execution of
- a process, a fault could be raised to signal the occurrence of this exception.
- The process will then search for an appropriate exception handler
- that is capable of handling such a fault.</para>
-
- <para>Similar to events, faults also have a type and possibly data
- associated with the fault. Users are free to define their own types of
- faults, together with their data.</para>
-
- <para>Faults are effected by a Fault node, generating a fault of the
- given type, indicated by the fault name. If the Fault node
- specifies a fault variable, the value of the given variable will be
- associated with the fault.</para>
-
- <para>Whenever a fault is created, the process will search for an
- appropriate exception handler that is capable of handling the given type
- of fault. Processes and Composite nodes both can define exception handlers
- for handling faults. Nesting of exception handlers is allowed; a node
- will always search for an appropriate exception handler in its parent
- container. If none is found, it will look in that one's parent container,
- and so on, until the process instance itself is reached. If no exception
- handler can be found, the process instance will be aborted, resulting
- in the cancellation of all nodes inside the process.</para>
-
- <para>Exception handlers can also specify a fault variable. The data
- associated with the fault (if any) will be copied to this variable
- whenever an exception handler is selected to handle a fault. This
- allows subsequent Action nodes in the process to access the fault data
- and take appropriate action based on this data.</para>
-
- <para>Exception handlers need to define an action that specifies how
- to respond to the given fault. In most cases, the behavior that is
- needed to react to the given fault cannot be expressed in one action.
- It is therefore recommended to have the exception handler signal an
- event of a specific type (in this case "Fault") using</para>
- <programlisting role="JAVA">
-context.getProcessInstance().signalEvent("FaultType", context.getVariable("FaultVariable");</programlisting>
-
- </section>
-
- <section id="sec.timers">
- <title id="sec.timers.title">Timers</title>
-
- <para>Timers wait for a predefined amount of time, before triggering, once
- or repeatedly. They cou be used to specify time supervision, or to trigger
- certain logic after a certain period, or to repeat some action at regular
- intervals.</para>
-
- <para>A Timer node is set up with a delay and a period. The delay specifies
- the amount of time (in milliseconds) to wait after node activation before
- triggering the timer the first time. The period defines the time between
- subsequent trigger activations. A period of 0 results in a one-shot timer.</para>
-
- <para>The timer service is responsible for making sure that timers get
- triggered at the appropriate times. Timers can also be cancelled, meaning
- that the timer will no longer be triggered.</para>
-
- <para>Timers can be used in two ways inside a process:</para>
- <itemizedlist>
- <listitem><para>A Timer node may be added to the process flow. Its activation
- starts the timer, and its triggers, once or repeatedly, activate the
- Timer node's successor. This means that the outgoing connection of a
- timer with a positive perios is triggered multiple times. Cancelling a
- Timer node also cancels the associated timer, whereafter no more triggerings
- will occur.</para></listitem>
- <listitem><para>Timers may be associated with event-based nodes like WorkItem,
- SubFlow, etc. A timer associated with a node is activated whenever
- the node becomes active. The associated action is executed whenever
- the timer triggers. You may use this, for instance, to send out
- notifications, at regular intervals, when the execution of a task takes
- too long, or to signal an event or a fault in case a time supervision
- expires. When the node owning the timer completes, the timer is
- automatically cancelled.</para></listitem>
- </itemizedlist>
-
- <para>By default, the Drools engine is a passive component, meaning that
- it will start processing only if you tell it to. Typically, you first
- insert the necessary data and then tell the engine to start processing.
- In passive mode, a timer that has been triggered will be put on the
- action queue. This means that it will either be executed automatically
- if the engine is still running, or it will become delayed until the engine
- is told to start executing by the user (by calling
- <code>fireAllRules()</code>).</para>
-
- <para>When using timers, it does usually make sense to let the Drools
- engine operate as an active component, so that it will execute actions
- whenever they become available, without the need to wait until the user
- tells it to resume execution. Thus, a timer would become effective as
- soon as it triggers. To make the engine fire all actions continuously,
- you must call the method <code>fireUntilHalt()</code>, whereupon the
- engine operates until <code>halt()</code> is called. Note that you should call
- <code>fireUntilHalt()</code> in a separate thread as it will only
- return if the engine has been halted, either by the user or some some
- logic calling <code>halt()</code> on the session. The following
- code snippet shows how to do this.</para>
-
- <programlisting role="JAVA">
-new Thread(new Runnable() {
- public void run() {
- ksession.fireUntilHalt();
- }
-}).start();
-
-// starting a new process instance
-ksession.startProcess("...");
-// any timer that triggers will now be executed automatically</programlisting>
- </section>
-
- <section>
- <title>Updating processes</title>
-
- <para>Over time, processes may evolve, for example because the process itself
- needs to be improved, or due to changing requirements. Actually, you cannot really
- update a process, you can only deploy a new version of the process, the old process
- will still exist. That is because existing process instances might still need that
- process definition. So the new process should have a different id, though the name
- could be the same, and you can use the version parameter to show when a process is
- updated (the version parameter is just a String and is not validated by the process
- framework itself, so you can select your own format for specifying minor/major
- updates, etc.).</para>
-
- <para>Whenever a process is updated, it is important to determine what should happen
- to the already running process instances. There are various strategies one could
- consider for each running instance:</para>
- <itemizedlist>
- <listitem><para><emphasis>Proceed</emphasis>: The running process instance proceeds as
- normal, following the process (definition) as it was defined when the process
- instance was started. As a result, the already running instance will proceed as
- if the process was never updated. New instances can be started using the updated
- process.</para></listitem>
- <listitem><para><emphasis>Abort (and restart)</emphasis>: The already running instance
- is aborted. If necessary, the process instance can be restarted using the new
- process definition.</para></listitem>
- <listitem><para><emphasis>Transfer</emphasis>: The process instance is migrated to the
- new process definition, meaning that - once it has been migrated successfully -
- it will continue executing based on the updated process logic.</para></listitem>
- </itemizedlist>
-
- <para>By default, Drools Flow uses the proceed approach, meaning that multiple
- versions of the same process can be deployed, but existing process instances will
- simply continue executing based on the process definition that was used when starting
- the process instance. Running process instances could always be aborted as well of
- course, using the process management API. Process instance migration is more difficult
- and is explained in the following paragraphs.</para>
-
- <section>
- <title>Process instance migration</title>
-
- <para>A process instance contains all the runtime information needed to continue
- execution at some later point in time. This includes all the data linked to this
- process instance (as variables), but also the current state in the process diagram.
- For each node that is currently active, a node instance is used to represent this.
- This node instance can also contain additional state linked to the execution of that
- specific node only. There are different types of node instances, one for each type
- of node.</para>
-
- <para>A process instance only contains the runtime state and is linked to a particular
- process (indirectly, using id references) that represents the process logic that needs
- to be followed when executing this process instance (this clear separation of definition
- and runtime state allows reuse of the definition accross all process instances based
- on this process and minimizes runtime state). As a result, updating a running process
- instance to a newer version so it used the new process logic instead of the old one is
- simply a matter of changing the referenced process id from the old to the new id.</para>
-
- <para>However, this does not take into account that the state of the process instance (the
- variable instances and the node instances) might need to be migrated as well. In cases
- where the process is only extended and all existing wait states are kept, this is pretty
- straightforward, the runtime state of the process instance does not need to change at all.
- However, it is also possible that a more sofisticated mapping is necessary. For example,
- when an existing wait state is removed, or split into multiple wait states, an existing
- process instance that is waiting in that state cannot simply be updated. Or when a new
- process variable is introduced, that variable might need to be initiazed correctly so it
- can be used in the remainder of the (updated) process.</para>
-
- <para>The WorkflowProcessInstanceUpgrader can be used to upgrade a workflow process
- instance to a newer process instance. Of course, you need to provide the process instance
- and the new process id. By default, Drools Flow will automatically map old node instances
- to new node instances with the same id. But you can provide a mapping of the old (unique)
- node id to the new node id. The unique node id is the node id, preceded by the node ids
- of its parents (with a colon inbetween), to allow to uniquely identify a node when composite
- nodes are used (as a node id is only unique within its node container. The new node id
- is simply the new node id in the node container (so no unique node id here, simply the new
- node id). The following code snippet shows a simple example.</para>
-
- <programlisting role="JAVA">
-// create the session and start the process "com.sample.ruleflow"
-KnowledgeBuilder kbuilder = ...
-StatefulKnowledgeSession ksession = ...
-ProcessInstance processInstance = ksession.startProcess("com.sample.ruleflow");
-
-// add a new version of the process "com.sample.ruleflow2"
-kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-kbuilder.add(..., ResourceType.DRF);
-kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
-
-// migrate process instance to new version
-Map<String, Long> mapping = new HashMap<String, Long>();
-// top level node 2 is mapped to a new node with id 3
-mapping.put("2", 3L);
-// node 2, which is part of composite node 5, is mapped to a new node with id 4
-mapping.put("5.2", 4L);
-WorkflowProcessInstanceUpgrader.upgradeProcessInstance(
- ksession, processInstance.getId(),
- "com.sample.ruleflow2", mapping);</programlisting>
-
- <para>If this kind of mapping is still insufficient, you can still describe your own custom
- mappers for specific situations. Be sure to first disconnect the process instance, change
- the state accordingly and then reconnect the process instance, similar to how the
- WorkflowProcessinstanceUpgrader does it.</para>
-
- </section>
-
- </section>
-
- <section>
- <title>Assigning Rules to a Ruleflow Group</title>
-
- <para>Drools already provides some functionality to define the order in
- which rules should be executed, like salience, activation groups, etc. When
- dealing with potentially many large rule-sets, managing the order in
- which rules are evaluated might become complex. Ruleflow allows you to
- specify the order in which rule sets should be evaluated by using a flow
- chart. This allows you to define which rule sets should be evaluated in
- sequence or in parallel, to specify conditions under which rule sets should
- be evaluated. This chapter contains a few ruleflow examples.</para>
-
- <para>A ruleflow is a graphical description of a sequence of steps that the
- rule engine needs to take, where the order is important. The ruleflow can
- also deal with conditional branching, parallelism, and synchonization.</para>
-
- <para>To use a ruleflow to describe the order in which rules should be
- evaluated, you should first group rules into ruleflow groups using the
- <literal>ruleflow-group</literal> rule attribute ("options" in the GUI). Then you
- should create a ruleflow graph (which is a flow chart) that graphically
- describe the order in which the rules should be considered, by specifying
- the order in which the ruleflow-groups should be evaluated.</para>
-
- <programlisting>
-rule 'YourRule'
- ruleflow-group 'group1'
-when
- ...
-then
- ...
-end</programlisting>
-
- <para>This rule belongs to the ruleflow-group called "group1".</para>
- </section>
-
- <section>
- <title>A Simple Ruleflow</title>
-
- <figure>
- <title>Ruleflow</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/RuleFlowSimple.png" format="PNG"
- role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>The above rule flow specifies that the rules in the group "Check Order" must be
- executed before the rules in the group "Process Order". This means that first only
- rules which are marked as having a ruleflow-group of "Check Order" will be
- considered, and then, only if there aren't any more of those, the rules of
- "Process Order". That's about it. You could achieve similar results with either
- using salience, but this is harder to maintain and makes the time-relationship
- implicit in the rules, or Agenda groups. However, using a ruleflow makes the
- order of processing explicit, in a layer on top of the rule structure, so that
- managing more complex situations becomes much easier.</para>
-
- <para>In practice, if you are using ruleflow, you will most likely be
- doing more than setting a simple sequence of groups to progress though.
- You'll use Split and Join nodes for modeling branches of processing, and
- define the flows of control by connections, from the Start to ruleflow
- groups, to Splits and then on to more groups, Joins, and so on. All this
- is done in a grphic editor.</para>
-
- <figure>
- <title>Complex ruleflow</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" width="100%"
- fileref="images/Chapter-Flow/RFComplex.png" format="PNG"
- role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>The above flow is a more complex example, representing the rule
- flow for processing an insurance claim. Initially the claim
- data validation rules are processed, checking for data integrity,
- consistency and completeness. Next, in a Split node, there is a decision
- based on a condition based on the value ofthe claim. Processing will
- either move on to an "auto-settlement" group, or to another Split node,
- which checks whether there was a fatality in the incident. If so, it
- determines whether the "regular" of fatality specific rules should take
- effect, with more processing to follow. Based on a few conditions, many
- different control flows are possible. Note that all the rules can be in
- one package, with the control flow definition being separated from the
- actual rules.</para>
-
- <figure>
- <title>Split types</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" width="100%"
- fileref="images/Chapter-Flow/RFSplitType.png" format="PNG"
- role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>To edit Split nodes you click on the node, which will show you
- a properties panel as shown above. You then have to choose the type:
- AND, OR, and XOR. If you choose OR, then any of the "outputs" of the
- split can happen, so that processing can proceed, in parallel, along
- two or more paths. If you chose XOR, then only one path is chosen.</para>
-
- <para>If you choose OR or XOR, the "Constraints" row will have a
- square button on the right hand side. Clickin on this button opens
- the Constraint editor, where you set the conditions deciding which
- outgoing path to follow.</para>
-
- <figure>
- <title>Edit constraints</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/RFEditConstraints.png"
- format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>Choose the output path you want to set the constraints for (e.g.
- Autosettlement), and then you should see the following constraint
- editor:</para>
-
- <figure>
- <title>Constraint editor</title>
-
- <mediaobject>
- <imageobject>
- <imagedata align="center" fileref="images/Chapter-Flow/RFConstraintEditor.png"
- format="PNG" role="" />
- </imageobject>
- </mediaobject>
- </figure>
-
- <para>This is a text editor where the constraints - which are like the
- condition part of a rule - are entered. These constraints operate on facts
- in the working memory. In the above example, there is a check for claims
- with a value of less than 250. Should this condition be true, then the
- associated path will be followed.</para>
- </section>
-
- <section>
- <title>Using Drools 4.x RuleFlow Processes</title>
-
- <para>The XML format that was used in Drools4 to store RuleFlow processes
- was generated automatically, using XStream. As a result, it was hard to
- read by human readers and difficult to maintain and extend. The
- new Drools Flow XML format has been created to simplify this. This however
- means that, by default, old RuleFlow processes cannot simply be executed on
- the Drools5 engine.</para>
-
- <para>We do however provide a Rule Flow Migrator that allows you to transform
- your old .rf file to the new format. It uses an XSLT transformation to
- generate the new XML based on the old content. You can use this class to
- manually transform your old processes to the new format once when upgrading
- from Drools4.x to Drools5.x. You can however also let the KnowledgeBuilder
- automatically upgrade your processes to the new format when they are
- loaded into the Knowledge Base. While this requires a conversion every time
- the process is loaded into the Knowledge Base, it does support a more
- seamless upgrade. To enact this automatic upgrade you need to set the
- "drools.ruleflow.port" system property to "true", for example by adding
- <code>-Ddrools.ruleflow.port=true</code> when starting your application,
- or by calling <code>System.setProperty("drools.ruleflow.port", "true")</code>.</para>
-
- <para>The Drools Eclipse plugin also automatically detects if an old RuleFlow
- file is opened. At that point, it will automatically perform the conversion
- and show the result in the graphical editor. You then need to save this result,
- either in a new file or overwriting the old one, to retain the old process
- in the new format. Note that the plugin does not support editing and saving
- processes in the old Drools4.x format.</para>
- </section>
-
-
-</chapter>
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0"
+ xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+ xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
+ <title>Rule Flow</title>
+
+ <figure>
+ <title>Ruleflow</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/RuleFlow.png" format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>A RuleFlow is a process that describes the order in which a series of steps need to
+ be executed, using a flow chart. A process consists of a collection of nodes that are
+ linked to each other using connections. Each of the nodes represents one step in the
+ overall process while the connections specify how to transition from one node to the other.
+ A large selection of predefined node types have been defined. This chapter describes how
+ to define such processes and use them in your application.</para>
+
+ <section>
+ <title>Creating a RuleFlow Process</title>
+
+ <para>Processes can be created by using one of the following three methods:
+ <orderedlist>
+ <listitem>Using the graphical RuleFlow editor in the Drools plug-in for Eclipse</listitem>
+ <listitem>As an XML file, according to the XML process format as defined in the
+ XML Schema definition for Drools processes.</listitem>
+ <listitem>By directly creating a process using the Process API.</listitem>
+ </orderedlist>
+ </para>
+
+ <section>
+ <title>Using the Graphical RuleFlow Editor</title>
+
+ <para>The graphical RuleFlow editor is a editor that allows you to create a process
+ by dragging and dropping different nodes on a canvas and editing the properties of these
+ nodes. The graphical RuleFlow editor is part of the Drools plug-in for Eclipse. Once
+ you have set up a Drools project (check the IDE chapter if you do not know how to do this),
+ you can start adding processes. When in a project, launch the "New" wizard: use Ctrl+N
+ or right-click the directory you would like to put your ruleflow in and select
+ "New", then "Other...". Choose the section on "Drools" and then pick "RuleFlow file".
+ This will create a new .rf file.</para>
+
+ <figure>
+ <title>Creating a new RuleFlow file</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/RFNewWizard.png" format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>Next you will see the graphical RuleFlow editor. Now would be a good time to
+ switch to the Drools Perspective (if you haven't done so already). This will tweak
+ the user interface so that it is optimal for rules. Then, ensure that you can see
+ the Properties View down the bottom of the Eclipse window, as it will be necessary
+ to fill in the different properties of the elements in your process. If you cannot
+ see the properties view, open it using the menu "Window", then "Show View" and
+ "Other...", and under the "General" folder select the Properties View.</para>
+
+ <figure>
+ <title>New RuleFlow process</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" width="100%"
+ fileref="images/Chapter-Flow/NewRF.png" format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>The RuleFlow editor consists of a palette, a canvas and an Outline View.
+ To add new elements to the canvas, select the element you would like to create
+ in the palette and then add them to the canvas by clicking on the preferred
+ location. For example, click on the "RuleFlowGroup" icon in the "Components"
+ palette of the GUI: you can then draw a few rule flow groups. Clicking on an
+ element in your rule flow allows you to set the properties of that element. You
+ can connect the nodes (as long as it is permitted by the different types
+ of nodes) by using "Connection Creation" from the "Components" palette.</para>
+
+ <para>You can keep adding nodes and connections to your process until it
+ represents the business logic that you want to specify. You'll probably need
+ to check the process for any missing information (by pressing the green "Check"
+ icon in the IDE menu bar) before trying to use it in your application.</para>
+
+ </section>
+
+ <section>
+ <title>Defining Processes Using XML</title>
+
+ <para>It is also possible to specify processes using the underlying XML directly.
+ The syntax of these XML processes is defined using an XML Schema definition.
+ For example, the following XML fragment shows a simple process that contains a
+ sequence of a Start node, an Action node that prints "Hello World" to the console,
+ and an End node.</para>
+
+<programlisting>
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://drools.org/drools-5.0/process"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:schemaLocation="http://drools.org/drools-5.0/process drools-processes-5.0.xsd"
+ type="RuleFlow" name="ruleflow" id="com.sample.ruleflow" package-name="com.sample" >
+
+ <header>
+ </header>
+
+ <nodes>
+ <start id="1" name="Start" x="16" y="16" />
+ <actionNode id="2" name="Hello" x="128" y="16" >
+ <action type="expression" dialect="mvel" >System.out.println("Hello World");</action>
+ </actionNode>
+ <end id="3" name="End" x="240" y="16" />
+ </nodes>
+
+ <connections>
+ <connection from="1" to="2" />
+ <connection from="2" to="3" />
+ </connections>
+
+</process>
+</programlisting>
+
+ <para>The process XML file should consist of exactly one <process> element.
+ This element contains parameters related to the process (its type, name, id and
+ package name), and consists of three subsections: a <header> (where
+ process-level information like variables, globals, imports and swimlanes can be
+ defined), a <nodes> section that defines each of the nodes in the process,
+ and a <connections> section that contains the connections between all the nodes
+ in the process. In the nodes section, there is a specific element for each node,
+ defining the various parameters and, possibly, sub-elements for that node type.</para>
+
+ </section>
+
+ <section>
+ <title>Defining Processes Using the Process API</title>
+
+ <para>While it is recommended to define processes using the graphical editor or
+ the underlying XML (to shield yourself from internal APIs), it is also possible
+ to define a process using the Process API directly. The most important process
+ elements are defined in the packages <code>org.drools.workflow.core</code> and
+ <code>org.drools.workflow.core.node</code>. A "fluent API" is provided that
+ allows you to easily construct processes in a readable manner using factories.
+ At the end, you can validate the process that you were constructing manually.
+ Some examples about how to build processes using this fluent API are added below.</para>
+
+
+ <section>
+ <title>Example 1</title>
+
+ <para>This is a simple example of a basic process with a ruleset node only:</para>
+ <programlisting role="JAVA">
+RuleFlowProcessFactory factory =
+ RuleFlowProcessFactory.createProcess("org.drools.HelloWorldRuleSet");
+factory
+ // Header
+ .name("HelloWorldRuleSet")
+ .version("1.0")
+ .packageName("org.drools")
+ // Nodes
+ .startNode(1).name("Start").done()
+ .ruleSetNode(2)
+ .name("RuleSet")
+ .ruleFlowGroup("someGroup").done()
+ .endNode(3).name("End").done()
+ // Connections
+ .connection(1, 2)
+ .connection(2, 3);
+RuleFlowProcess process = factory.validate().getProcess();</programlisting>
+
+ <para>You can see that we start by calling the static <code>createProcess()</code>
+ method from the <code>RuleFlowProcessFactory</code> class. This method creates
+ a new process with the given id and returns the <code>RuleFlowProcessFactory</code>
+ that can be used to create the process. A typical process consists of three parts.
+ The header part comprises global elements like the name of the process, imports,
+ variables, etc. The nodes section contains all the different nodes that are part of the
+ process. The connections section finally links these nodes to each other
+ to create a flow chart.</para>
+
+ <para>In this example, the header contains the name and the version of the
+ process and the package name. After that, you can start adding nodes to the
+ current process. If you have auto-completion you can see that you have
+ different methods to create each of the supported node types at your disposal.</para>
+
+ <para>When you start adding nodes to the process, in this example by calling
+ the <code>startNode()</code>, <code>ruleSetNode()</code> and <code>endNode()</code>
+ methods, you can see that these methods return a specific <code>NodeFactory</code>,
+ that allows you to set the properties of that node. Once you have finished
+ configuring that specific node, the <code>done()</code> method returns you to the
+ current <code>RuleFlowProcessFactory</code> so you can add more nodes, if necessary.</para>
+
+ <para>When you are finished adding nodes, you must connect them by creating
+ connections between them. This can be done by calling the method
+ <code>connection</code>, which will link previously created nodes.</para>
+
+ <para>Finally, you can validate the generated process by calling the
+ <code>validate()</code> method and retrieve the created
+ <code>RuleFlowProcess</code> object.</para>
+
+ </section>
+
+ <section>
+ <title>Example 2</title>
+
+ <para>This example is using Split and Join nodes:</para>
+ <programlisting role="JAVA">
+RuleFlowProcessFactory factory =
+ RuleFlowProcessFactory.createProcess("org.drools.HelloWorldJoinSplit");
+factory
+ // Header
+ .name("HelloWorldJoinSplit")
+ .version("1.0")
+ .packageName("org.drools")
+ // Nodes
+ .startNode(1).name("Start").done()
+ .splitNode(2).name("Split").type(Split.TYPE_AND).done()
+ .actionNode(3).name("Action 1")
+ .action("mvel", "System.out.println(\"Inside Action 1\")").done()
+ .actionNode(4).name("Action 2")
+ .action("mvel", "System.out.println(\"Inside Action 2\")").done()
+ .joinNode(5).type(Join.TYPE_AND).done()
+ .endNode(6).name("End").done()
+ // Connections
+ .connection(1, 2)
+ .connection(2, 3)
+ .connection(2, 4)
+ .connection(3, 5)
+ .connection(4, 5)
+ .connection(5, 6);
+RuleFlowProcess process = factory.validate().getProcess();</programlisting>
+
+ <para>This shows a simple example using Split and Join nodes. As you can see,
+ a Split node can have multiple outgoing connections, and a Join node multiple
+ incoming connections. To understand the behavior of the different types
+ of Split and Join nodes, take a look at the documentation for each of these
+ nodes.</para>
+
+ </section>
+
+ <section>
+ <title>Example 3</title>
+
+ <para>Now we show a more complex example with a ForEach node, where we have nested nodes:</para>
+ <programlisting role="JAVA">
+RuleFlowProcessFactory factory =
+ RuleFlowProcessFactory.createProcess("org.drools.HelloWorldForeach");
+factory
+ // Header
+ .name("HelloWorldForeach")
+ .version("1.0")
+ .packageName("org.drools")
+ // Nodes
+ .startNode(1).name("Start").done()
+ .forEachNode(2)
+ // Properties
+ .linkIncomingConnections(3)
+ .linkOutgoingConnections(4)
+ .collectionExpression("persons")
+ .variable("child", new ObjectDataType("org.drools.Person"))
+ // Nodes
+ .actionNode(3)
+ .action("mvel", "System.out.println(\"inside action1\")").done()
+ .actionNode(4)
+ .action("mvel", "System.out.println(\"inside action2\")").done()
+ // Connections
+ .connection(3, 4)
+ .done()
+ .endNode(5).name("End").done()
+ // Connections
+ .connection(1, 2)
+ .connection(2, 5);
+RuleFlowProcess process = factory.validate().getProcess();</programlisting>
+
+ <para>Here you can see how we can include a ForEach node with nested action nodes.
+ Note the <code>linkIncomingConnections()</code> and
+ <code>linkOutgoingConnections()</code> methods that are
+ called to link the ForEach node with the internal action node.
+ These methods are used to specify the first and last nodes inside the ForEach
+ composite node.</para>
+
+ </section>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Using a Process in Your Application</title>
+
+ <para>There are two things you need to do to be able to execute processes from
+ within your application: (1) you need to create a Knowledge Base that contains
+ the definition of the process, and (2) you need to start the process by creating
+ a session to communicate with the process engine and start the process.</para>
+
+ <orderedlist>
+
+ <listitem><para><emphasis>Creating a Knowledge Base</emphasis>: Once you
+ have a valid process, you can add the process to the Knowledge Base. Note
+ that this is almost identical to adding rules to the Knowledge Base, except
+ for the type of knowledge added:</para>
+ <programlisting role="JAVA">
+KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+kbuilder.add( ResourceFactory.newClassPathResource("MyProcess.rf"),
+ ResourceType.DRF );</programlisting>
+ <para>After adding all your knowledge to the builder (you can add more
+ than one process, and even rules), you can create a new knowledge base
+ like this:</para>
+ <programlisting role="JAVA">
+KnowledgeBase kbase = kbuilder.newKnowledgeBase();</programlisting>
+ <para>Note that this will throw an exception if the knowledge base contains
+ errors (because it could not parse your processes correctly).</para>
+ </listitem>
+
+ <listitem><para><emphasis>Starting a process</emphasis>: Processes are
+ only executed if you explicitly state that they should be executed. This
+ is because you could potentially define a lot of processes in your
+ Knowledge Base and the engine has no way to know when you would like
+ to start each of these. To activate a particular process, you will need
+ to start it by calling the <code>startProcess</code> method on your session.
+ For example:</para>
+ <programlisting role="JAVA">
+StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+ksession.startProcess("com.sample.MyProcess");</programlisting>
+ <para>The parameter of the <code>startProcess</code> method represents the id
+ of the process that needs to be started. This process id needs to be
+ specified as a property of the process, shown in the Properties View
+ when you click the background canvas of your process. If your process
+ also requires the execution of rules during the execution of the process,
+ you also need to call the <code>ksession.fireAllRules()</code> method to
+ make sure the rules are executed as well. That's it!</para>
+
+ <para>You may specify additional parameters that are used to pass
+ on input data to the process, using the
+ <code>startProcess(String processId, Map parameters)</code> method, which
+ takes an additional set of parameters as name-value pairs. These parameters
+ are then copied to the newly created process instance as top-level variables
+ of the process.</para>
+
+ <para>You can also start a process from within a rule consequence, or from
+ inside a process action, using the predefined kcontext parameter:</para>
+ <programlisting role="JAVA">
+kcontext.getKnowledgeRuntime().startProcess("com.sample.MyProcess");</programlisting>
+ </listitem>
+
+ </orderedlist>
+
+ </section>
+
+ <section>
+ <title>Detailed Explanation of the Different Node Types</title>
+
+ <para>A ruleflow process is a flow chart where different types of nodes are
+ linked using connections. The process itself exposes the following properties:
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The unique id of the process.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the process.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Version</emphasis>: The version number of the process.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Package</emphasis>: The package (namespace) the process is
+ defined in.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Variables</emphasis>: Variables can be defined to store data
+ during the execution of your process. See section
+ <quote><link linkend='sec.data' endterm="sec.data.title"/></quote>
+ for details.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Swimlanes</emphasis>: Specify the actor responsible for the
+ execution of human tasks. See chapter
+ <quote><link linkend='ch.Human_Tasks' endterm="ch.Human_Tasks.title"/></quote>
+ for details.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Exception Handlers</emphasis>: Specify the behaviour when a fault
+ occurs in the process. See section
+ <quote><link linkend='sec.exceptions' endterm="sec.exceptions.title"/></quote>
+ for details.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Connection Layout</emphasis>: Specify how the connections are
+ visualized on the canvas using the connection layout property:
+ <itemizedlist>
+ <listitem>
+ <para>'Manual' always draws your connections as lines going straight from
+ their start to end point (with the possibility to use intermediate break
+ points).</para>
+ </listitem>
+ <listitem>
+ <para>'Shortest path' is similar, but it tries to go around any obstacles
+ it might encounter between the start and end point, to avoid lines crossing
+ nodes.</para>
+ </listitem>
+ <listitem>
+ <para>'Manhattan' draws connections by only using horizontal and vertical
+ lines.</para>
+ </listitem>
+ </itemizedlist></para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>A RuleFlow process supports different types of nodes:
+
+ <figure>
+ <title>The different types of ruleflow nodes</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/ruleflow_nodes.png" format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <orderedlist>
+
+ <!-- START -->
+ <listitem>
+ <para><emphasis role="strong">Start Event</emphasis>: The start of the ruleflow.
+ A ruleflow should have exactly one start node, which cannot have
+ incoming connections and should have one outgoing connection. Whenever a
+ RuleFlow process is started, execution will start at this node and
+ automatically continue to the first node linked to this start node, and
+ so on. It contains the following properties:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Triggers</emphasis>: A Start node can also specify additional
+ triggers that can be used to automatically start the process. Examples are a
+ "constraint" trigger that automatically starts the process if a given rule or
+ constraint is satisfied, or an "event" trigger that automatically starts the
+ process if a specific event is signalled. Note that it currently not possibly
+ to specify this in the graphical editor. You should manually update the process
+ XML for now.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- END -->
+ <listitem>
+ <para><emphasis role="strong">End Event</emphasis>: The end of the ruleflow. A ruleflow
+ should have one or more End nodes. The End node should have one incoming
+ connection and cannot have outgoing connections. It contains the following
+ properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique within
+ one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Terminate</emphasis>: An End node can be terminating for
+ the entire process (default) or just for the path. If the process is
+ terminated, all nodes that are still active (on parallel paths) in this
+ ruleflow are cancelled. Non-terminating End nodes are simply ends for
+ some path, while other parallel paths still continue.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- RULESET -->
+ <listitem>
+ <para><emphasis role="strong">Rule Task (or RuleFlowGroup)</emphasis>: Represents a set
+ of rules that need to be evaluated. The rules are evaluated when the node
+ is reached. A RuleFlowGroup node should have one incoming connection and
+ one outgoing connection. Rules can become part of a specific ruleflow group
+ using the <literal>ruleflow-group</literal> attribute in the header. When a RuleFlowGroup node
+ is reached in the ruleflow, the engine will start executing rules that are
+ part of the corresponding ruleflow-group (if any). Execution will
+ automatically continue to the next node if there are no more active rules in
+ this ruleflow group. This means that, during the execution of a ruleflow group,
+ it is possible that new activations belonging to the currently active
+ ruleflow group are added to the Agenda due to changes made to the facts by
+ the other rules. Note that the ruleflow will immediately continue with the
+ next node if it encounters a ruleflow group where there are no active rules
+ at that time. If the ruleflow group was already active, the ruleflow group
+ will remain active and execution will only continue if all active rules of the
+ ruleflow group has been completed. It contains the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique within
+ one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>RuleFlowGroup</emphasis>: The name of the ruleflow group
+ that represents the set of rules of this RuleFlowGroup node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timers</emphasis>: Timers that are linked to this node.
+ See section
+ <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
+ for details.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- SPLIT -->
+ <listitem>
+ <para><emphasis role="strong">Diverging Gateway (or Split)</emphasis>: Allows you to create branches
+ in your ruleflow. A Split node should have one incoming connection and two or
+ more outgoing connections. There are three types of Split nodes currently
+ supported:
+ <itemizedlist>
+ <listitem>
+ <para>AND means that the control flow will continue in all outgoing
+ connections simultaneously.</para>
+ </listitem>
+ <listitem>
+ <para>XOR means that exactly one of the outgoing connections will
+ be chosen. The decision is made by evaluating the constraints
+ that are linked to each of the outgoing connections. Constraints are
+ specified using the same syntax as the left-hand side of a rule. The
+ constraint with the <emphasis>lowest</emphasis> priority number that
+ evaluates to true is selected. Note that you should always make sure
+ that at least one of the outgoing connections will evaluate to true
+ at runtime (the ruleflow will throw an exception at runtime if it
+ cannot find at least one outgoing connection). For example, you could use a
+ connection which is always true (default) with a <emphasis>high</emphasis>
+ priority number to specify what should happen if none of the other
+ connections can be taken.</para>
+ </listitem>
+ <listitem>
+ <para>OR means that all outgoing connections whose condition evaluates
+ to true are selected. Conditions are similar to the XOR split, except
+ that no priorities are taken into account. Note that you should
+ make sure that at least one of the outgoing connections will evaluate
+ to true at runtime because the ruleflow will throw an exception at
+ runtime if it cannot determine an outgoing connection.
+ </para>
+ </listitem>
+ </itemizedlist>
+ It contains the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique within
+ one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Type</emphasis>: The type of the split node, i.e., AND,
+ XOR or OR (see above).</para>
+ </listitem>
+ <listitem><para><emphasis>Constraints</emphasis>: The constraints linked
+ to each of the outgoing connections (in case of an (X)OR split).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- JOIN -->
+ <listitem>
+ <para><emphasis role="strong">Converging Gateway (or Join)</emphasis>: Allows you to synchronize
+ multiple branches. A join node should have two or more incoming connections
+ and one outgoing connection. There are four types of splits currently supported:
+ <itemizedlist>
+ <listitem>
+ <para>AND means that is will wait until <emphasis>all</emphasis> incoming
+ branches are completed before continuing.
+ </para>
+ </listitem>
+ <listitem>
+ <para>XOR means that it continues as soon as <emphasis>one</emphasis> of its
+ incoming branches has been completed. If it is triggered from more than one
+ incoming connection, it will trigger the next node for each of those triggers.</para>
+ </listitem>
+ <listitem>
+ <para>Discriminator means that it continues if one of its incoming
+ branches has been completed. Completions of other incoming branches
+ are registered until all connections have completed. At that point, the
+ node will be reset, so that it can trigger again when one of its
+ incoming branches has been completed once more.</para>
+ </listitem>
+ <listitem>
+ <para>n-of-m means that it continues if <emphasis>n</emphasis> of its
+ <emphasis>m</emphasis> incoming branches
+ have been completed. The variable <emphasis>n</emphasis> could either
+ be hardcoded to a fixed value, or refer to a process variable that will
+ contain the number of incoming branches to wait for.</para>
+ </listitem>
+ </itemizedlist>
+ It contains the following properties:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Type</emphasis>: The type of the Join node, i.e. AND,
+ XOR or Discriminator (see above).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>n</emphasis>: The number of incoming connections to
+ wait for (in case of a n-of-m join).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- EVENT WAIT -->
+ <listitem>
+ <para><emphasis role="strong">State</emphasis>:
+ Represents a wait state. A state should have one incoming connection
+ and one or more outgoing connections. For each of the outgoing connections,
+ a rule constraint can be specified which defines how long the process should wait
+ in this state before continuing. For example, a constraint in an order entry
+ application might specify that the process should wait until no more errors are
+ found in the given order. Constraints are specified using the same syntax as
+ the left-hand side of a rule. When a state is reached in the ruleflow, the
+ engine will check the associated constraints. If one of the constraint evaluates
+ to true directly, the flow will continue imediately. Otherwise, the flow will
+ continue if one of the constraints is satisfied later on, for example when a fact
+ is inserted, updated or removed from the working memory. A state can also be
+ signaled manually to make it progress to the next state, using
+ ksession.signalEvent("signal", "name") where "name" should either be the name of
+ the constraint for the connection that should be selected, or the name of the node
+ that should be moved to. A state contains the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique within
+ one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Constraints</emphasis>: Defines when the process can
+ leave this state and continue for each of the outgoing connections.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timers</emphasis>: Timers that are linked to this node.
+ See section
+ <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
+ for details.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>On-entry and on-exit actions</emphasis>: Actions that are
+ executed upon entry or exit of this node, respectively.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- SUBPROCESS -->
+ <listitem>
+ <para><emphasis role="strong">Reusable Sub-Process (or SubFlow)</emphasis>: represents the invocation
+ of another process from within this process. A sub-process node should
+ have one incoming connection and one outgoing connection. When a SubFlow
+ node is reached in the ruleflow, the engine will start the process with the
+ given id. It contains the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique within
+ one node container).</para></listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>ProcessId</emphasis>: The id of the process that should
+ be executed.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Wait for completion</emphasis>: If this property is true,
+ the SubFlow node will only continue if that SubFlow process has
+ terminated its execution (completed or aborted); otherwise it will continue
+ immediately after starting the subprocess.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Independent</emphasis>: If this property is true, the
+ subprocess is started as an independent process, which means that the
+ SubFlow process will not be terminated if this process reaches an end node;
+ otherwise the active sub-process will be cancelled on termination (or abortion)
+ of the process.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>On-entry and on-exit actions</emphasis>: Actions that are
+ executed upon entry or exit of this node, respectively.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Parameter in/out mapping</emphasis>: A SubFlow node can
+ also define in- and out-mappings for variables. The value of variables
+ in this process with variable names given in the "in" mapping will be used
+ as parameters (with the associated parameter name) when starting the process.
+ The value of the variables in the subprocess with the given variable name
+ in the "out" mappings will be copied to the variables of this process when the
+ subprocess has been completed. Note that you can use "out" mappings only when
+ "Wait for completion" is set to true.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timers</emphasis>: Timers that are linked to this node.
+ See section
+ <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
+ for details.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- ACTION -->
+ <listitem>
+ <para><emphasis role="strong">Script Task (or Action)</emphasis>: represents an action that
+ should be executed in this ruleflow. An Action node should have one incoming
+ connection and one outgoing connection. The associated action specifies what
+ should be executed, the dialect used for coding the action (i.e., Java or MVEL),
+ and the actual action code. This code can access any globals, the predefined
+ variable <code>drools</code> referring to a <code>KnowledgeHelper</code> object
+ (which can, for example,
+ be used to retrieve the Working Memory by calling
+ <code>drools.getWorkingMemory()</code>), and the variable <code>kcontext</code>
+ that references the <code>ProcessContext</code> object (which can,
+ for example, be used to access the current <code>ProcessInstance</code> or
+ <code>NodeInstance</code>, and to get and set variables). When an Action node
+ is reached in the ruleflow, it will execute the action and then continue with the
+ next node. It contains the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique within
+ one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Action</emphasis>: The action associated with this
+ action node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- TIMER -->
+ <listitem>
+ <para><emphasis role="strong">Timer Event</emphasis>: represents a timer that can
+ trigger one or multiple times after a given period of time. A Timer node
+ should have one incoming connection and one outgoing connection. The timer
+ delay specifies how long (in milliseconds) the timer should wait before
+ triggering the first time. The timer period specifies the time between two
+ subsequent triggers. A period of 0 means that the timer should only be
+ triggered once. When a Timer node is reached in the ruleflow, it will
+ start the associated timer. The timer is cancelled if the timer node is
+ cancelled (e.g., by completing or aborting the process). Consult the
+ section <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
+ for more information. - The Timer node contains the
+ following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timer delay</emphasis>: The delay (in milliseconds)
+ that the node should wait before triggering the first time.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timer period</emphasis>: The period (in milliseconds)
+ between two subsequent triggers. If the period is 0, the timer should
+ only be triggered once.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- FAULT -->
+ <listitem>
+ <para><emphasis role="strong">Error Event (or Fault)</emphasis>: A Fault node can be used
+ to signal an exceptional condition in the process. It should
+ have one incoming connection and no outgoing connections. When a Fault
+ node is reached in the ruleflow, it will throw a fault with the given name.
+ The process will search for an appropriate exception handler that is
+ capable of handling this kind of fault. If no fault handler is found,
+ the process instance will be aborted. A Fault node contains the following
+ properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>FaultName</emphasis>: The name of the fault. This
+ name is used to search for appriopriate exception handlers that is
+ capable of handling this kind of fault.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>FaultVariable</emphasis>: The name of the variable
+ that contains the data associated with this fault. This data is also
+ passed on to the exception handler (if one is found).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- EVENT -->
+ <listitem>
+ <para><emphasis role="strong">(Message) Event</emphasis>: An Event node can be used
+ to respond to internal or external events during the execution of the process.
+ An Event node should have no incoming connections and one outgoing
+ connection. It specifies the type of event that is expected. Whenever
+ that type of event is detected, the node connected to this Event node will
+ be triggered. It contains the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>EventType</emphasis>: The type of event that is
+ expected.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>VariableName</emphasis>: The name of the variable that
+ will contain the data associated with this event (if any) when this
+ event occurs.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Scope</emphasis>: An event could be used to listen
+ to internal events only, i.e., events that are signalled to this
+ process instance directly, using
+ <code>processInstance.signalEvent(String type, Object data)</code>.
+ When an Event node is defined as external, it will also be listening
+ to external events that are signalled to the process engine directly,
+ using <code>workingMemory.signalEvent(String type, Object event)</code>.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- HUMAN TASK -->
+ <listitem>
+ <para><emphasis role="strong">User Task (or Human Task)</emphasis>: Processes can also
+ involve tasks that need to be executed by human actors. A Human Task node
+ represents an atomic task to be executed by a human actor. It
+ should have one incoming connection and one outgoing connection.
+ Human Task nodes can be used in combination with Swimlanes to assign multiple
+ human tasks to similar actors. Refer to chapter
+ <quote><link linkend='ch.Human_Tasks' endterm="ch.Human_Tasks.title"/></quote>
+ for more details. A Human Task node is actually nothing more than a specific
+ type of work item node (of type "Human Task"). A Human Task node contains
+ the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>TaskName</emphasis>: The name of the human task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Priority</emphasis>: An integer indicating the priority
+ of the human task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Comment</emphasis>: A comment associated with the human
+ task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>ActorId</emphasis>: The actor id that is responsible for
+ executing the human task. A list of actor id's can be specified using
+ a comma (',') as separator.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Skippable</emphasis>: Specifies whether the human task
+ can be skipped, i.e., whether the actor may decide not to execute the
+ task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Content</emphasis>: The data associated with this task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Swimlane</emphasis>: The swimlane this human task node
+ is part of. Swimlanes make it easy to assign multiple human tasks to
+ the same actor. See the human tasks chapter for more detail on how to
+ use swimlanes.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Wait for completion</emphasis>: If this property is true,
+ the human task node will only continue if the human task has been
+ terminated (i.e., by completing or reaching any other terminal state);
+ otherwise it will continue immediately after creating the human task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>On.entry and on-exit actions</emphasis>: Actions that are
+ executed upon entry and exit of this node, respectively.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Parameter mapping</emphasis>: Allows copying the value
+ of process variables to parameters of the human task. Upon creation of
+ the human tasks, the values will be copied.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Result mapping</emphasis>: Allows copying the value
+ of result parameters of the human task to a process variable. Upon
+ completion of the human task, the values will be copied. Note that
+ you can use result mappings only when "Wait for completion" is set to
+ true. A human task has a result variable "Result" that contains
+ the data returned by the human actor. The variable "ActorId" contains
+ the id of the actor that actually executed the task.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timers</emphasis>: Timers that are linked to this
+ node. Consult the section
+ <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
+ for details.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- COMPOSITE -->
+ <listitem>
+ <para><emphasis role="strong">Sub-Process (or Composite)</emphasis>: A Composite node is
+ a node that can contain other nodes so that it acts as a node container.
+ This allows not only the embedding of a part of the flow within such
+ a Composite node, but also the definition of additional variables and
+ exception handlers that are accessible for all nodes inside this
+ container. A Composite node should have one incoming connection and one
+ outgoing connection. It contains the following properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>StartNodeId</emphasis>: The id of the node (within
+ this node container) that should be triggered when this node is
+ triggered.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>EndNodeId</emphasis>: The id of the node (within
+ this node container) that represents the end of the flow contained
+ in this node. When this node is completed, the composite node will
+ also be completed and trigger its outgoing connection. All other
+ executing nodes within this composite node will be cancelled.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Variables</emphasis>: Additional variables can be
+ defined to store data during the execution of this node. See section
+ <quote><link linkend='sec.data' endterm="sec.data.title"/></quote>
+ for details.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Exception Handlers</emphasis>: Specify the behavior
+ when a fault occurs in this node container. See section
+ <quote><link linkend='sec.exceptions' endterm="sec.exceptions.title"/></quote>
+ for details.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- FOR EACH -->
+ <listitem>
+ <para><emphasis role="strong">Multiple Instance (or ForEach)</emphasis>: A ForEach node is a
+ special kind of composite node that allows you to execute the contained
+ flow multiple times, once for each element in a collection. A ForEach
+ node should have one incoming connection and one outgoing connection. A
+ ForEach node awaits the completion of the embedded flow for each of the
+ collection''s elements before continuing. It contains the following
+ properties:</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which
+ is unique within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>StartNodeId</emphasis>: The id of the node (within
+ this node container) that should be triggered for each of the
+ elements in a collection.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>EndNodeId</emphasis>: The id of the node (within
+ this node container) that represents the end of the flow contained
+ in this node. When this node is completed, the execution of the
+ ForEach node will also be completed for the current collection element.
+ The outgoing connection is triggered if the collection is exhausted.
+ All other executing nodes within this composite node will be cancelled.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>CollectionExpression</emphasis>: The name of a
+ variable that represents the collection of elements that should
+ be iterated over. The collection variable should be of type
+ <code>java.util.Collection</code>.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>VariableName</emphasis>: The name of the variable
+ to contain the current element from the collection. This
+ gives nodes within the composite node access to the selected
+ element.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <!-- WORK ITEMS -->
+ <listitem>
+ <para><emphasis role="strong">WorkItem (or Service Task)</emphasis>: Represents an (abstract)
+ unit of work that should be executed in this process. All work that is
+ executed outside the process engine should be represented (in a declarative
+ way) using a WorkItem node. Different types of work items are predefined, e.g.,
+ sending an email, logging a message, etc. Users can define domain-specific
+ work items, using a unique name and by defining
+ the parameters (input) and results (output) that are associated with this
+ type of work. Refer to the chapter
+ <quote><link linkend='ch.Domain_Specific_Processes'
+ endterm="ch.Domain_Specific_Processes.title"/></quote> for a
+ detailed explanation and illustrative examples of how to define and use
+ work items in your processes. When a WorkItem node is reached in the
+ process, the associated work item is executed. A WorkItem node should
+ have one incoming connection and one outgoing connection.</para>
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>Id</emphasis>: The id of the node (which is unique
+ within one node container).</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Name</emphasis>: The display name of the node.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Wait for completion</emphasis>: If the property
+ "Wait for completion" is true, the WorkItem node will only continue
+ if the created work item has terminated (completed or aborted)
+ its execution; otherwise it will continue immediately after
+ starting the work item.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Parameter mapping</emphasis>: Allows copying the
+ value of process variables to parameters of the work item. Upon
+ creation of the work item, the values will be copied.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Result mapping</emphasis>: Allows copying the value
+ of result parameters of the work item to a process variable. Each
+ type of work can define result parameters that will (potentially)
+ be returned after the work item has been completed. A result
+ mapping can be used to copy the value of the given result parameter
+ to the given variable in this process. For example, the "FileFinder"
+ work item returns a list of files that match the given search
+ criteria within the result parameter <code>Files</code>. This list
+ of files can then be bound to a process variable for use within the
+ process. Upon completion of the work item, the values will be copied.
+ Note that you can use result mappings only when "Wait for completion"
+ is set to true.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>On-entry and on-exit actions</emphasis>: Actions that are
+ executed upon entry or exit of this node, respectively.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Timers</emphasis>: Timers that are linked to this
+ node. See the section
+ <quote><link linkend='sec.timers' endterm="sec.timers.title"/></quote>
+ for details.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>Additional parameters</emphasis>: Each type of work
+ item can define additional parameters that are relevant for that
+ type of work. For example, the "Email" work item defines additional
+ parameters such as <code>From</code>, <code>To</code>, <code>Subject</code>
+ and <code>Body</code>. The user can either provide values for these
+ parameters directly, or define a
+ parameter mapping that will copy the value of the given variable
+ in this process to the given parameter; if both are specified, the
+ mapping will have precedence. Parameters of type <code>String</code> can use
+ <emphasis><code>#{expression}</code></emphasis> to embed a value in the
+ string. The value will be retrieved when creating the work item, and the
+ substitution expression will be replaced by the result of calling
+ <code>toString()</code> on the variable. The expression could
+ simply be the name of a variable (in which case it resolves
+ to the value of the variable), but more advanced MVEL expressions
+ are possible as well, e.g., <code>#{person.name.firstname}</code>.</para>
+ </listitem>
+ <listitem>
+ <para><emphasis>MetaData</emphasis>: Metadata related to this node.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ </orderedlist>
+ </para>
+ </section>
+
+ <section id='sec.data'>
+ <title id='sec.data.title'>Data</title>
+
+ <para>While the flow graph focusses on specifying the control flow of the
+ process, it is usually also necessary to look at the process from a data
+ perspective. Throughout the execution of a process, data can retrieved,
+ stored, passed on and used.</para>
+
+ <para>For storing runtime data, during the execution of the process,
+ you use variables. A variable is defined by a name and a data type. This
+ could be a basic data type, such as boolean, int, or String, or any kind of
+ Object subclass. Variables can be defined inside a variable
+ <emphasis>scope</emphasis>. The top-level
+ scope is the variable scope of the process itself. Subscopes can be
+ defined using a Composite node. Variables that are defined in a subscope
+ are only accessible for nodes within that scope.</para>
+
+ <para>Whenever a variable is accessed, the process will search for the
+ appropriate variable scope that defines the variable. Nesting of variable
+ scopes is allowed. A node will always search for a variable in its parent
+ container. If the variable cannot be found, it will look in that one's
+ parent container, and so on, until the process instance itself is reached.
+ If the variable cannot be found, a read access yields null, and a write
+ access produces an error message, with the process continuing its
+ execution.</para>
+
+ <para>Variables can be used in various ways:</para>
+ <itemizedlist>
+ <listitem><para>Process-level variables can be set when starting a process
+ by providing a map of parameters to the invocation of the
+ <code>startProcess</code> method. These parameters will be set as
+ variables on the process scope.</para>
+ </listitem>
+ <listitem><para>Actions can access variables directly, simply by using the
+ name of the variable as a parameter name.</para>
+ <programlisting role="JAVA">
+// call method on the process variable "person"
+person.setAge(10);</programlisting>
+ <para>Changing the value of a variable can be done through the Knowledge Context:</para>
+ <programlisting role="JAVA">
+kcontext.setVariable(variableName, value);</programlisting>
+ </listitem>
+ <listitem><para>WorkItem and SubFlow nodes can pass the value of parameters
+ to the outside world by mapping the variable to one of the work item
+ parameters, either by using a parameter mapping or by interpolating
+ it into a String parameter, using
+ <emphasis><code>#{expression}</code></emphasis>. The results of a WorkItem
+ can also be copied to a variable using a result mapping.</para>
+ </listitem>
+ <listitem><para>Various other nodes can also access data. Event nodes, for
+ example, can store the data associated to the event in a variable,
+ exception handlers can read error data from a specific variable, etc.
+ Check the properties of the different node types for more information.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Finally, processes and rules all have access to globals, i.e.,
+ globally defined variables that are considered immutable with regard
+ to rule evaluation, and data in the Knowledge Session. The Knowledge Session
+ can be accessed in actions using the Knowledge Context:</para>
+ <programlisting role="JAVA">
+kcontext.getKnowledgeRuntime().insert( new Person(...) );</programlisting>
+
+ </section>
+
+ <section>
+ <title>Constraints</title>
+
+ <para>Constraints can be used in various locations in your processes,
+ for example in a Split node using OR or XOR decisions, or as a
+ constraint for a State node. Drools Flow supports two types of constraints:</para>
+ <itemizedlist>
+ <listitem><para><emphasis>Code constraints</emphasis> are boolean expressions,
+ evaluated directly whenever they are reached. We currently support two
+ dialects for expressing these code constraints: Java and MVEL.
+ Both Java and MVEL code constraints have direct access
+ to the globals and variables defined in the process. Here is an example
+ of a valid Java code constraint, <code>person</code> being a variable
+ in the process:</para>
+ <programlisting role="JAVA">
+return person.getAge() > 20;</programlisting>
+ <para>A similar example of a valid MVEL code constraint is:</para>
+ <programlisting>
+return person.age > 20;</programlisting>
+ </listitem>
+ <listitem><para><emphasis>Rule constraints</emphasis> are equals to normal
+ Drools rule conditions. They use the Drools Rule Language syntax to
+ express possibly complex constraints. These rules can, like any other
+ rule, refer to data in the Working Memory. They can also refer to
+ globals directly. Here is an example of a valid rule constraint:</para>
+ <programlisting
+>Person( age > 20 )</programlisting>
+ <para>This tests for a person older than 20 being in the Working
+ Memory.</para></listitem>
+ </itemizedlist>
+
+ <para>Rule constraints do not have direct access to variables defined
+ inside the process. It is however possible to refer to the current process
+ instance inside a rule constraint, by adding the process instance to the
+ Working Memory and matching for the process instance in your rule
+ constraint. We have added special logic to make sure that a variable
+ <code>processInstance</code> of type <code>WorkflowProcessInstance</code>
+ will only match to the current process instance and not to other process
+ instances in the Working Memory. Note that you are however responsible
+ yourself to insert the process instance into the session and, possibly,
+ to update it, for example, using Java code or an on-entry or on-exit or
+ explicit action in your process. The following example of a rule
+ constraint will search for a person with the same name as the value
+ stored in the variable "name" of the process:</para>
+
+ <programlisting>processInstance : WorkflowProcessInstance()
+Person( name == ( processInstance.getVariable("name") ) )
+# add more constraints here ...</programlisting>
+ </section>
+
+
+ <section>
+ <title>Actions</title>
+
+ <para>Actions can be used in different ways:
+ <itemizedlist>
+ <listitem>Within an Action node,</listitem>
+ <listitem>As entry or exit actions, with a number of nodes,</listitem>
+ <listitem>Actions specifying the behavior of exception handlers.</listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Actions have access to globals and the variables that are defined
+ for the process and the predefined variable <code>context</code>. This
+ variable is of type
+ <code>org.drools.runtime.process.ProcessContext</code> and can be used for
+ several tasks:</para>
+ <itemizedlist>
+ <listitem><para>Getting the current node instance (if applicable). The node
+ instance could be queried for data, such as its name and type. You can
+ also cancel the current node instance.</para>
+ <programlisting role="JAVA">
+NodeInstance node = context.getNodeInstance();
+String name = node.getNodeName();</programlisting>
+ </listitem>
+ <listitem><para>Getting the current process instance. A process instance
+ can be queried for data (name, id, processId, etc.), aborted or
+ signalled an internal event.</para>
+ <programlisting role="JAVA">
+WorkflowProcessInstance proc = context.getProcessInstance();
+proc.signalEvent( type, eventObject );</programlisting>
+ </listitem>
+ <listitem><para>Getting or setting the value of variables.</para></listitem>
+ <listitem><para>Accessing the Knowledge Runtime allows you do things
+ like starting a process, signalling external events, inserting data,
+ etc.</para></listitem>
+ </itemizedlist>
+
+ <para>Drools currently supports two dialects, Java and MVEL.
+ Java actions should be valid Java code. MVEL actions can use the business
+ scripting language MVEL to express the action. MVEL accepts any valid Java
+ code but additionally provides support for nested accesses of parameters
+ (e.g., <code>person.name</code> instead of <code>person.getName()</code>),
+ and many other scripting improvements. Thus, MVEL expressions are more
+ convenient for the business user. For example, an action that prints out
+ the name of the person in the "requester" variable of the process would
+ look like this:</para>
+
+ <programlisting>
+// Java dialect
+System.out.println( person.getName() );
+
+// MVEL dialect
+System.out.println( person.name );
+ </programlisting>
+ </section>
+
+ <section>
+ <title>Events</title>
+
+ <figure>
+ <title>A sample process using events</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/EventProcess.png" format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>During the execution of a process, the process engine makes sure that all the relevant
+ tasks are executed according to the process plan, by requesting the execution of work items
+ and waiting for the results. However, it is also possible that the process should respond to
+ events that were not directly requested by the process engine. Explicitly representing these
+ events in a process allows the process author to specify how the process should react
+ to such events.</para>
+
+ <para>Events have a type and possibly data associated with them. Users are free to define
+ their own event types and their associated data.</para>
+
+ <para>A process can specify how to respond to events by using Event nodes. An Event
+ node needs to specify the type of event the node is interested in. It can also define
+ the name of a variable, which will receive the data that is associated with the event.
+ This allows subsequent nodes in the process to access the event data and take appropriate
+ action based on this data.</para>
+
+ <para>An event can be signalled to a running instance of a process in a number of ways:</para>
+ <itemizedlist>
+ <listitem><para>Internal event: Any action inside a process (e.g., the action of an
+ action node, or an on-entry or on-exit action of some node) can signal the
+ occurence of an internal event to the surrounding process instance, using code
+ like the following:</para>
+ <programlisting role="JAVA">
+context.getProcessInstance().signalEvent(type, eventData);</programlisting></listitem>
+ <listitem><para>External event: A process instance can be notified of an event
+ from outside using code such as:</para>
+ <programlisting role="JAVA">
+processInstance.signalEvent(type, eventData);</programlisting></listitem>
+ <listitem><para>External event using event correlation: Instead of notifying a
+ process instance directly, it is also possible to have the engine
+ automatically determine which process instances might be interested
+ in an event using <emphasis>event correlation</emphasis>, which is based
+ on the event type. A process instance that contains an event node
+ listening to external events of some type is notified whenever such
+ an event occurs. To signal such an event to the process engine, write
+ code such as:</para>
+ <programlisting role="JAVA">
+workingMemory.signalEvent(type, eventData);</programlisting></listitem>
+ </itemizedlist>
+
+ <para>Events could also be used to start a process. Whenever a Start node
+ defines an event trigger of a specific type, a new process instance will be
+ started every time that type of event is signalled to the process engine.</para>
+
+ </section>
+
+ <section id="sec.exceptions">
+ <title id="sec.exceptions.title">Exceptions</title>
+
+ <figure>
+ <title>A sample process using exception handlers</title>
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/FaultProcess.png" format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>Whenever an exceptional condition occurs during the execution of
+ a process, a fault could be raised to signal the occurrence of this exception.
+ The process will then search for an appropriate exception handler
+ that is capable of handling such a fault.</para>
+
+ <para>Similar to events, faults also have a type and possibly data
+ associated with the fault. Users are free to define their own types of
+ faults, together with their data.</para>
+
+ <para>Faults are effected by a Fault node, generating a fault of the
+ given type, indicated by the fault name. If the Fault node
+ specifies a fault variable, the value of the given variable will be
+ associated with the fault.</para>
+
+ <para>Whenever a fault is created, the process will search for an
+ appropriate exception handler that is capable of handling the given type
+ of fault. Processes and Composite nodes both can define exception handlers
+ for handling faults. Nesting of exception handlers is allowed; a node
+ will always search for an appropriate exception handler in its parent
+ container. If none is found, it will look in that one's parent container,
+ and so on, until the process instance itself is reached. If no exception
+ handler can be found, the process instance will be aborted, resulting
+ in the cancellation of all nodes inside the process.</para>
+
+ <para>Exception handlers can also specify a fault variable. The data
+ associated with the fault (if any) will be copied to this variable
+ whenever an exception handler is selected to handle a fault. This
+ allows subsequent Action nodes in the process to access the fault data
+ and take appropriate action based on this data.</para>
+
+ <para>Exception handlers need to define an action that specifies how
+ to respond to the given fault. In most cases, the behavior that is
+ needed to react to the given fault cannot be expressed in one action.
+ It is therefore recommended to have the exception handler signal an
+ event of a specific type (in this case "Fault") using</para>
+ <programlisting role="JAVA">
+context.getProcessInstance().signalEvent("FaultType", context.getVariable("FaultVariable");</programlisting>
+
+ </section>
+
+ <section id="sec.timers">
+ <title id="sec.timers.title">Timers</title>
+
+ <para>Timers wait for a predefined amount of time, before triggering, once
+ or repeatedly. They cou be used to specify time supervision, or to trigger
+ certain logic after a certain period, or to repeat some action at regular
+ intervals.</para>
+
+ <para>A Timer node is set up with a delay and a period. The delay specifies
+ the amount of time (in milliseconds) to wait after node activation before
+ triggering the timer the first time. The period defines the time between
+ subsequent trigger activations. A period of 0 results in a one-shot timer.</para>
+
+ <para>The timer service is responsible for making sure that timers get
+ triggered at the appropriate times. Timers can also be cancelled, meaning
+ that the timer will no longer be triggered.</para>
+
+ <para>Timers can be used in two ways inside a process:</para>
+ <itemizedlist>
+ <listitem><para>A Timer node may be added to the process flow. Its activation
+ starts the timer, and its triggers, once or repeatedly, activate the
+ Timer node's successor. This means that the outgoing connection of a
+ timer with a positive perios is triggered multiple times. Cancelling a
+ Timer node also cancels the associated timer, whereafter no more triggerings
+ will occur.</para></listitem>
+ <listitem><para>Timers may be associated with event-based nodes like WorkItem,
+ SubFlow, etc. A timer associated with a node is activated whenever
+ the node becomes active. The associated action is executed whenever
+ the timer triggers. You may use this, for instance, to send out
+ notifications, at regular intervals, when the execution of a task takes
+ too long, or to signal an event or a fault in case a time supervision
+ expires. When the node owning the timer completes, the timer is
+ automatically cancelled.</para></listitem>
+ </itemizedlist>
+
+ </section>
+
+ <section>
+ <title>Updating processes</title>
+
+ <para>Over time, processes may evolve, for example because the process itself
+ needs to be improved, or due to changing requirements. Actually, you cannot really
+ update a process, you can only deploy a new version of the process, the old process
+ will still exist. That is because existing process instances might still need that
+ process definition. So the new process should have a different id, though the name
+ could be the same, and you can use the version parameter to show when a process is
+ updated (the version parameter is just a String and is not validated by the process
+ framework itself, so you can select your own format for specifying minor/major
+ updates, etc.).</para>
+
+ <para>Whenever a process is updated, it is important to determine what should happen
+ to the already running process instances. There are various strategies one could
+ consider for each running instance:</para>
+ <itemizedlist>
+ <listitem><para><emphasis>Proceed</emphasis>: The running process instance proceeds as
+ normal, following the process (definition) as it was defined when the process
+ instance was started. As a result, the already running instance will proceed as
+ if the process was never updated. New instances can be started using the updated
+ process.</para></listitem>
+ <listitem><para><emphasis>Abort (and restart)</emphasis>: The already running instance
+ is aborted. If necessary, the process instance can be restarted using the new
+ process definition.</para></listitem>
+ <listitem><para><emphasis>Transfer</emphasis>: The process instance is migrated to the
+ new process definition, meaning that - once it has been migrated successfully -
+ it will continue executing based on the updated process logic.</para></listitem>
+ </itemizedlist>
+
+ <para>By default, Drools Flow uses the proceed approach, meaning that multiple
+ versions of the same process can be deployed, but existing process instances will
+ simply continue executing based on the process definition that was used when starting
+ the process instance. Running process instances could always be aborted as well of
+ course, using the process management API. Process instance migration is more difficult
+ and is explained in the following paragraphs.</para>
+
+ <section>
+ <title>Process instance migration</title>
+
+ <para>A process instance contains all the runtime information needed to continue
+ execution at some later point in time. This includes all the data linked to this
+ process instance (as variables), but also the current state in the process diagram.
+ For each node that is currently active, a node instance is used to represent this.
+ This node instance can also contain additional state linked to the execution of that
+ specific node only. There are different types of node instances, one for each type
+ of node.</para>
+
+ <para>A process instance only contains the runtime state and is linked to a particular
+ process (indirectly, using id references) that represents the process logic that needs
+ to be followed when executing this process instance (this clear separation of definition
+ and runtime state allows reuse of the definition accross all process instances based
+ on this process and minimizes runtime state). As a result, updating a running process
+ instance to a newer version so it used the new process logic instead of the old one is
+ simply a matter of changing the referenced process id from the old to the new id.</para>
+
+ <para>However, this does not take into account that the state of the process instance (the
+ variable instances and the node instances) might need to be migrated as well. In cases
+ where the process is only extended and all existing wait states are kept, this is pretty
+ straightforward, the runtime state of the process instance does not need to change at all.
+ However, it is also possible that a more sofisticated mapping is necessary. For example,
+ when an existing wait state is removed, or split into multiple wait states, an existing
+ process instance that is waiting in that state cannot simply be updated. Or when a new
+ process variable is introduced, that variable might need to be initiazed correctly so it
+ can be used in the remainder of the (updated) process.</para>
+
+ <para>The WorkflowProcessInstanceUpgrader can be used to upgrade a workflow process
+ instance to a newer process instance. Of course, you need to provide the process instance
+ and the new process id. By default, Drools Flow will automatically map old node instances
+ to new node instances with the same id. But you can provide a mapping of the old (unique)
+ node id to the new node id. The unique node id is the node id, preceded by the node ids
+ of its parents (with a colon inbetween), to allow to uniquely identify a node when composite
+ nodes are used (as a node id is only unique within its node container. The new node id
+ is simply the new node id in the node container (so no unique node id here, simply the new
+ node id). The following code snippet shows a simple example.</para>
+
+ <programlisting role="JAVA">
+// create the session and start the process "com.sample.ruleflow"
+KnowledgeBuilder kbuilder = ...
+StatefulKnowledgeSession ksession = ...
+ProcessInstance processInstance = ksession.startProcess("com.sample.ruleflow");
+
+// add a new version of the process "com.sample.ruleflow2"
+kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+kbuilder.add(..., ResourceType.DRF);
+kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
+
+// migrate process instance to new version
+Map<String, Long> mapping = new HashMap<String, Long>();
+// top level node 2 is mapped to a new node with id 3
+mapping.put("2", 3L);
+// node 2, which is part of composite node 5, is mapped to a new node with id 4
+mapping.put("5.2", 4L);
+WorkflowProcessInstanceUpgrader.upgradeProcessInstance(
+ ksession, processInstance.getId(),
+ "com.sample.ruleflow2", mapping);</programlisting>
+
+ <para>If this kind of mapping is still insufficient, you can still describe your own custom
+ mappers for specific situations. Be sure to first disconnect the process instance, change
+ the state accordingly and then reconnect the process instance, similar to how the
+ WorkflowProcessinstanceUpgrader does it.</para>
+
+ </section>
+
+ </section>
+
+ <section>
+ <title>Assigning Rules to a Ruleflow Group</title>
+
+ <para>Drools already provides some functionality to define the order in
+ which rules should be executed, like salience, activation groups, etc. When
+ dealing with potentially many large rule-sets, managing the order in
+ which rules are evaluated might become complex. Ruleflow allows you to
+ specify the order in which rule sets should be evaluated by using a flow
+ chart. This allows you to define which rule sets should be evaluated in
+ sequence or in parallel, to specify conditions under which rule sets should
+ be evaluated. This chapter contains a few ruleflow examples.</para>
+
+ <para>A ruleflow is a graphical description of a sequence of steps that the
+ rule engine needs to take, where the order is important. The ruleflow can
+ also deal with conditional branching, parallelism, and synchonization.</para>
+
+ <para>To use a ruleflow to describe the order in which rules should be
+ evaluated, you should first group rules into ruleflow groups using the
+ <literal>ruleflow-group</literal> rule attribute ("options" in the GUI). Then you
+ should create a ruleflow graph (which is a flow chart) that graphically
+ describe the order in which the rules should be considered, by specifying
+ the order in which the ruleflow-groups should be evaluated.</para>
+
+ <programlisting>
+rule 'YourRule'
+ ruleflow-group 'group1'
+when
+ ...
+then
+ ...
+end</programlisting>
+
+ <para>This rule belongs to the ruleflow-group called "group1".</para>
+
+ <para>Rules that are executing as part of a ruleflow-group that is triggered
+ by a process, can also access the process context in the rule consequence.
+ Through the process context, the process instance or node instance that triggered
+ the ruleflow-group can be accessed, or variables could be set or retrieved, e.g.</para>
+ <programlisting role="JAVA">drools.getContext(ProcessContext.class).getProcessInstance()</programlisting>
+ </section>
+
+ <section>
+ <title>A Simple Ruleflow</title>
+
+ <figure>
+ <title>Ruleflow</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/RuleFlowSimple.png" format="PNG"
+ role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>The above rule flow specifies that the rules in the group "Check Order" must be
+ executed before the rules in the group "Process Order". This means that first only
+ rules which are marked as having a ruleflow-group of "Check Order" will be
+ considered, and then, only if there aren't any more of those, the rules of
+ "Process Order". That's about it. You could achieve similar results with either
+ using salience, but this is harder to maintain and makes the time-relationship
+ implicit in the rules, or Agenda groups. However, using a ruleflow makes the
+ order of processing explicit, in a layer on top of the rule structure, so that
+ managing more complex situations becomes much easier.</para>
+
+ <para>In practice, if you are using ruleflow, you will most likely be
+ doing more than setting a simple sequence of groups to progress though.
+ You'll use Split and Join nodes for modeling branches of processing, and
+ define the flows of control by connections, from the Start to ruleflow
+ groups, to Splits and then on to more groups, Joins, and so on. All this
+ is done in a grphic editor.</para>
+
+ <figure>
+ <title>Complex ruleflow</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" width="100%"
+ fileref="images/Chapter-Flow/RFComplex.png" format="PNG"
+ role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>The above flow is a more complex example, representing the rule
+ flow for processing an insurance claim. Initially the claim
+ data validation rules are processed, checking for data integrity,
+ consistency and completeness. Next, in a Split node, there is a decision
+ based on a condition based on the value ofthe claim. Processing will
+ either move on to an "auto-settlement" group, or to another Split node,
+ which checks whether there was a fatality in the incident. If so, it
+ determines whether the "regular" of fatality specific rules should take
+ effect, with more processing to follow. Based on a few conditions, many
+ different control flows are possible. Note that all the rules can be in
+ one package, with the control flow definition being separated from the
+ actual rules.</para>
+
+ <figure>
+ <title>Split types</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" width="100%"
+ fileref="images/Chapter-Flow/RFSplitType.png" format="PNG"
+ role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>To edit Split nodes you click on the node, which will show you
+ a properties panel as shown above. You then have to choose the type:
+ AND, OR, and XOR. If you choose OR, then any of the "outputs" of the
+ split can happen, so that processing can proceed, in parallel, along
+ two or more paths. If you chose XOR, then only one path is chosen.</para>
+
+ <para>If you choose OR or XOR, the "Constraints" row will have a
+ square button on the right hand side. Clickin on this button opens
+ the Constraint editor, where you set the conditions deciding which
+ outgoing path to follow.</para>
+
+ <figure>
+ <title>Edit constraints</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/RFEditConstraints.png"
+ format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>Choose the output path you want to set the constraints for (e.g.
+ Autosettlement), and then you should see the following constraint
+ editor:</para>
+
+ <figure>
+ <title>Constraint editor</title>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center" fileref="images/Chapter-Flow/RFConstraintEditor.png"
+ format="PNG" role="" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>This is a text editor where the constraints - which are like the
+ condition part of a rule - are entered. These constraints operate on facts
+ in the working memory. In the above example, there is a check for claims
+ with a value of less than 250. Should this condition be true, then the
+ associated path will be followed.</para>
+ </section>
+
+ <section>
+ <title>Using Drools 4.x RuleFlow Processes</title>
+
+ <para>The XML format that was used in Drools4 to store RuleFlow processes
+ was generated automatically, using XStream. As a result, it was hard to
+ read by human readers and difficult to maintain and extend. The
+ new Drools Flow XML format has been created to simplify this. This however
+ means that, by default, old RuleFlow processes cannot simply be executed on
+ the Drools5 engine.</para>
+
+ <para>We do however provide a Rule Flow Migrator that allows you to transform
+ your old .rf file to the new format. It uses an XSLT transformation to
+ generate the new XML based on the old content. You can use this class to
+ manually transform your old processes to the new format once when upgrading
+ from Drools4.x to Drools5.x. You can however also let the KnowledgeBuilder
+ automatically upgrade your processes to the new format when they are
+ loaded into the Knowledge Base. While this requires a conversion every time
+ the process is loaded into the Knowledge Base, it does support a more
+ seamless upgrade. To enact this automatic upgrade you need to set the
+ "drools.ruleflow.port" system property to "true", for example by adding
+ <code>-Ddrools.ruleflow.port=true</code> when starting your application,
+ or by calling <code>System.setProperty("drools.ruleflow.port", "true")</code>.</para>
+
+ <para>The Drools Eclipse plugin also automatically detects if an old RuleFlow
+ file is opened. At that point, it will automatically perform the conversion
+ and show the result in the graphical editor. You then need to save this result,
+ either in a new file or overwriting the old one, to retain the old process
+ in the new format. Note that the plugin does not support editing and saving
+ processes in the old Drools4.x format.</para>
+ </section>
+
+
+</chapter>
Added: labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Installer/Chapter-Installer.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Installer/Chapter-Installer.xml (rev 0)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/Chapter-Installer/Chapter-Installer.xml 2010-07-29 00:09:29 UTC (rev 34270)
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.0"
+ xsi:schemaLocation="http://docbook.org/ns/docbook http://www.docbook.org/xml/5.0/xsd/docbook.xsd http://www.w3.org/1999/xlink http://www.docbook.org/xml/5.0/xsd/xlink.xsd"
+ xml:base="../" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
+ <title>Installer</title>
+
+ <para>Drools now comes with an installer.</para>
+
+ <section>
+ <title>Prerequisites</title>
+
+ <para>This script assumes you have Java JDK 1.5+ (set as JAVA_HOME), and Ant 1.7+ installed. If you don't,
+ use the following links to download and install them:</para>
+
+ <para>Java: <ulink url="http://java.sun.com/javase/downloads/index.jsp">http://java.sun.com/javase/downloads/index.jsp</ulink></para>
+ <para>Ant: <ulink url="http://ant.apache.org/bindownload.cgi">http://ant.apache.org/bindownload.cgi</ulink></para>
+ </section>
+
+ <section>
+ <title>Download the installer</title>
+
+ <para>First of all, you need to download the installer: drools-{version}-install.zip</para>
+
+ <para>You can for example find the latest snapshot release here.</para>
+ <para><ulink url="http://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/">http://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/</ulink></para>
+
+ </section>
+
+ <section>
+ <title>Download the installer</title>
+
+ <para>The easiest way to get started is to simply run the installation script to install the demo setup. Simply go into the install folder and run:</para>
+
+ <programlisting>ant install.demo</programlisting>
+
+ <para>This will:
+ <itemizedlist>
+ <listitem>Download JBoss AS</listitem>
+ <listitem>Download Eclipse</listitem>
+ <listitem>Install Guvnor into JBoss AS</listitem>
+ <listitem>Install the gwt-console into JBoss AS</listitem>
+ <listitem>Install the Eclipse plugins</listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Once the demo setup has finished (this could take a while as it might have to download the various components),
+ you can start playing with the various components by starting the demo setup:</para>
+
+ <programlisting>ant start.demo</programlisting>
+
+ <para>This will:
+ <itemizedlist>
+ <listitem>Start the H2 database</listitem>
+ <listitem>Start the JBoss AS</listitem>
+ <listitem>Start Eclipse</listitem>
+ <listitem>Start the Human Task Service</listitem>
+ </itemizedlist>
+ </para>
+
+ <para>Once everything is started, you can start playing with the Eclipse tooling, Guvnor and gwt-console, as explained in the next three sections.</para>
+
+ </section>
+
+ <section>
+ <title>Using Eclipse Tooling</title>
+
+ <para>The <ulink url="http://people.redhat.com/kverlaen/install-eclipse.swf">following screencast</ulink> gives an overview of how to run a simple demo process in Eclipse. It shows you:
+ <itemizedlist>
+ <listitem>How to import an existing example project into your workspace, containing
+ <itemizedlist>
+ <listitem>a sample BPMN2 process for requesting a performance evaluation</listitem>
+ <listitem>a sample Java class to start the process</listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>How to start the process</listitem>
+ <listitem>How to complete human tasks using the test human task client in Eclipse</listitem>
+ </itemizedlist>
+ </para>
+
+ <para>If you want to know more, we recommend you take a look at the rest of the Drools documentation.</para>
+
+ </section>
+
+ <section>
+ <title>Using Guvnor repository</title>
+
+ <para>Open up Drools Guvnor:</para>
+ <para><ulink url="http://localhost:8080/drools-guvnor">http://localhost:8080/drools-guvnor</ulink></para>
+
+ <para>Log in, using any non-empty username / password (we disabled authentication for demo purposes).
+ The <ulink url="http://people.redhat.com/kverlaen/install-guvnor.swf">following screencast</ulink> gives an overview of how to manage your repository. It shows you:
+ <itemizedlist>
+ <listitem>How to import an existing sample repository, containing the performance evaluation process as shown in the previous section</listitem>
+ <listitem>How to look up the processes that are part of a package</listitem>
+ <listitem>How to build a package so it can be used for creating a session (like for example in the gwt-console as shown in the next section)</listitem>
+ </itemizedlist>
+ </para>
+
+ <para>If you want to know more, we recommend you take a look at the rest of the Drools documentation.</para>
+
+ </section>
+
+ <section>
+ <title>Using web management consoles</title>
+
+ <para>First make sure you have imported the sample repository and built the defaultPackage in Guvnor first (see previous section).
+Open up the process management console:</para>
+ <para><ulink url="http://localhost:8080/gwt-console">http://localhost:8080/gwt-console</ulink></para>
+
+ <para>Log in, using krisv / krisv as username / password. The <ulink url="http://people.redhat.com/kverlaen/install-gwt-console.swf">following screencast</ulink> gives an overview of how to manage your
+ process instances. It shows you:
+ <itemizedlist>
+ <listitem>How to start a new process</listitem>
+ <listitem>How to look up the current status of a running process instance</listitem>
+ <listitem>How to look up your tasks</listitem>
+ <listitem>How to complete a task</listitem>
+ <listitem>How to generate reports to monitor your process execution</listitem>
+ </itemizedlist>
+ </para>
+
+ <para>If you want to know more, we recommend you take a look at the rest of the Drools documentation.</para>
+
+ <para>Once you're done playing:</para>
+ <programlisting>ant stop.demo</programlisting>
+ <para>and simply close all the rest.</para>
+
+ </section>
+
+</chapter>
Modified: labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/master.xml
===================================================================
--- labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/master.xml 2010-07-28 21:11:40 UTC (rev 34269)
+++ labs/jbossrules/trunk/drools-docs/drools-docs-flow/src/main/docbook/en-US/master.xml 2010-07-29 00:09:29 UTC (rev 34270)
@@ -33,6 +33,7 @@
</preface>
<xi:include href="Chapter-Introduction/Chapter-Introduction.xml" />
+ <xi:include href="Chapter-Installer/Chapter-Installer.xml" />
<xi:include href="Chapter-GettingStarted/Chapter-GettingStarted.xml" />
<xi:include href="Chapter-Flow/Chapter-RuleFlow.xml" />
<xi:include href="Chapter-API/Chapter-API.xml" />
More information about the jboss-svn-commits
mailing list