<?xml version="1.0" encoding="UTF-8"?>
<chapter id="ch.domain-specific-processes"
         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 id="ch.domain-specific-processes.title">Domain-specific processes</title>

<section>
  <title>Introduction</title>

<para>One of the goals of jBPM is to allow users to extend the default process constructs with 
domain-specific extensions that simplify development in a particular application domain.  This
tutorial describes how to take your first steps towards domain-specific processes.  Note that you
don't need to be a jBPM expert to define your own domain-specific nodes, this should be considered
integration code that a normal developer with some experience in jBPM can do himself.</para>

<para>Most process languages offer some generic action (node) construct that allows plugging in
custom user actions.  However, these actions are usually low-level, where the user is required
to write custom code to implement the work that should be incorporated in the process.  The code
is also closely linked to a specific target environment, making it difficult to reuse the process
in different contexts.</para>

<para>Domain-specific languages are targeted to one particular application domain and therefore
can offer constructs that are closely related to the problem the user is trying to solve.  This
makes the processes and easier to understand and self-documenting.  We will show you how to 
define domain-specific work items (also called service nodes), which represent atomic units of
work that need to be executed.  These service nodes specify the work that should be executed in
the context of a process in a declarative manner, i.e. specifying what should be executed (and
 not how) on a higher level (no code) and hiding implementation details.</para>

<para>So we want service nodes that are:
  <orderedlist>
    <listitem>
      <para>domain-specific</para>
    </listitem>
    <listitem>
      <para>declarative (what, not how)</para>
    </listitem>
    <listitem>
      <para>high-level (no code)</para>
    </listitem>
    <listitem>
      <para>customizable to the context</para>
    </listitem>
  </orderedlist>
</para>

<para>Users can easily define their own set of domain-specific service nodes and integrate them
in our process language.  For example, the next figure shows an example of a process in a 
healthcare context.  The process includes domain-specific service nodes for ordering nursing
tasks (e.g. measuring blood pressure), prescribing medication and notifying care providers.</para>

<mediaobject>
  <imageobject>
    <imagedata align="center" format="PNG" role="" 
               fileref="images/Chapter-DomainSpecificProcesses/CDSSExample.png"/>
  </imageobject>
</mediaobject>
</section>

  <section>
    <title>Example: Notifications</title>

<para>Let's start by showing you how to include a simple work item for sending notifications.
A work item represent an atomic unit of work in a declarative way.  It is defined by a unique
name and additional parameters that can be used to describe the work in more detail.  Work items
can also return information after they have been executed, specified as results.  Our notification
work item could thus be defined using a work definition with four parameters and no results:</para>

<programlisting>
  Name: "Notification"
  Parameters
  From [String]
  To [String]
  Message [String]
  Priority [String]
</programlisting>

  <section>
    <title>Creating the work definition</title>

<para>All work definitions must be specified in one or more configuration files in the project
classpath, where all the properties are specified as name-value pairs. Parameters and results are
maps where each parameter name is also mapped to the expected data type. Note that this
configuration file also includes some additional user interface information, like the icon
and the display name of the work item.</para>

<para> In our example we will use MVEL for reading in the configuration file,
which allows us to do more advanced configuration files. This file must be placed in the project
classpath in a directory called META-INF. Our MyWorkDefinitions.wid file
looks like this:</para>

<programlisting>
import org.drools.process.core.datatype.impl.type.StringDataType;
[
  // the Notification work item
  [
    "name" : "Notification",
    "parameters" : [
      "Message" : new StringDataType(),
      "From" : new StringDataType(),
      "To" : new StringDataType(),
      "Priority" : new StringDataType(),
    ],
    "displayName" : "Notification",
    "icon" : "icons/notification.gif"
  ]

]
</programlisting>

<para>The project directory structure could then look something like this:</para>

<programlisting>
project/src/main/resources/META-INF/MyWorkDefinitions.wid
</programlisting>

<para>You might now want to create your own icons to go along with your new work definition.
To add these you will need .gif or .png images with a pixel size of 16x16. Place them in a directory
outside of the META-INF directory, for example as follows:</para>

<programlisting>
project/src/main/resources/icons/notification.gif
</programlisting>

  </section>

  <section>
    <title>Registering the work definition</title>

<para>The configuration API can be used to register work definition files for your project
using the drools.workDefinitions property, which represents a list of files containing work
definitions (separated usings spaces). For example, include a drools.rulebase.conf file in
the META-INF directory of your project and add the following line:</para>

<programlisting>
  drools.workDefinitions = MyWorkDefinitions.wid
</programlisting>

<para>This will replace the default domain specific node types EMAIL and LOG with the newly 
defined NOTIFICATION node in the process editor. Should you wish to just add a newly created
node definition to the existing palette nodes, adjust the drools.workDefinitions property
as follows including the default set configuration file:</para>

<programlisting>
  drools.workDefinitions = MyWorkDefinitions.wid WorkDefinitions.conf
</programlisting>

<para>It is recommended to use extension .wid for your own definitions of domain specific nodes.
Do not be confused with extension .conf, it is used only for backward compatibility.</para>

  </section>

  <section>
    <title>Using your new work item in your processes</title>

<para>Once our work definition has been created and registered, we can start using it in
our processes.  The process editor contains a separate section in the palette where the
different service nodes that have been defined for the project appear.</para>

<mediaobject>
  <imageobject>
    <imagedata align="center" format="BMP" role="" 
               fileref="images/Chapter-DomainSpecificProcesses/NotificationPalette.png"/>
  </imageobject>
</mediaobject>

<para>Using drag and drop, a notification node can be created inside your process.  The
properties can be filled in using the properties view.</para>

<para>Apart from the properties defined by this work item, all work items also have
these three properties:</para>
<orderedlist>
  <listitem>
    <para>Parameter Mapping: Allows you to map the value of a variable in the process to a
    parameter of the work item.  This allows you to customize the work item based on the
    current state of the actual process instance (for example, the priority of the
    notification could be dependent of some process-specific information).</para>
  </listitem>
  <listitem>
    <para>Result Mapping: Allows you to map a result (returned once a work item has been
    executed) to a variable of the process.  This allows you to use results in the remainder
    of the process.</para>
  </listitem>
  <listitem>
    <para>Wait for completion: By default, the process waits until the requested work
    item has been completed before continuing with the process.  It is also possible to
    continue immediately after the work item has been requested (and not waiting for the
    results) by setting "wait for completion" to false.</para>
  </listitem>
</orderedlist>

<para>Here is an example that creates a domain specific node to execute Java, asking for
the class and method parameters. It includes a custom java.gif icon and consists of the 
following files and resulting screenshot:</para>

<programlisting>
import org.drools.process.core.datatype.impl.type.StringDataType;
[
  // the Java Node work item located in:
  // project/src/main/resources/META-INF/JavaNodeDefinition.conf
  [
    "name" : "JavaNode",
    "parameters" : [
      "class" : new StringDataType(),
      "method" : new StringDataType(),
    ],
    "displayName" : "Java Node",
    "icon" : "icons/java.gif"
  ]

]
</programlisting>


<programlisting>
// located in: project/src/main/resources/META-INF/drools.rulebase.conf
//
  drools.workDefinitions = JavaNodeDefinition.conf WorkDefinitions.conf

// icon for java.gif located in:
// project/src/main/resources/icons/java.gif
</programlisting>

<mediaobject>
  <imageobject>
    <imagedata align="center" format="BMP" role="" 

               fileref="images/Chapter-DomainSpecificProcesses/JavaNode.png"/>
  </imageobject>
</mediaobject>


  </section>

  <section>
    <title>Executing service nodes</title>

<para>The jBPM engine contains a WorkItemManager that is responsible for executing 
work items whenever necessary.  The WorkItemManager is responsible for delegating the
work items to WorkItemHandlers that execute the work item and notify the WorkItemManager
when the work item has been completed.  For executing notification work items, a 
NotificationWorkItemHandler should be created (implementing the WorkItemHandler interface):</para>

<programlisting language="java">package com.sample;

import org.drools.runtime.process.WorkItem;
import org.drools.runtime.process.WorkItemHandler;
import org.drools.runtime.process.WorkItemManager;

public class NotificationWorkItemHandler implements WorkItemHandler {

  public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
    // extract parameters
    String from = (String) workItem.getParameter("From");
    String to = (String) workItem.getParameter("To");
    String message = (String) workItem.getParameter("Message");
    String priority = (String) workItem.getParameter("Priority");
    // send email
    EmailService service = ServiceRegistry.getInstance().getEmailService();
    service.sendEmail(from, to, "Notification", message);
    // notify manager that work item has been completed
    manager.completeWorkItem(workItem.getId(), null);
  }

  public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
    // Do nothing, notifications cannot be aborted
  }

}
</programlisting>

<para>This WorkItemHandler sends a notification as an email and then immediately notifies
the WorkItemManager that the work item has been completed.  Note that not all work items
can be completed directly.  In cases where executing a work item takes some time, execution
can continue asynchronously and the work item manager can be notified later.  In these
situations, it might also be possible that a work item is being aborted before it has 
been completed.  The abort method can be used to specify how to abort such work items.</para>

<para>WorkItemHandlers should be registered at the WorkItemManager, using the following API:</para>

<programlisting language="java">ksession.getWorkItemManager().registerWorkItemHandler(
    "Notification", new NotificationWorkItemHandler());
</programlisting>

<para>Decoupling the execution of work items from the process itself has the following advantages:</para>
<orderedlist>
  <listitem>
    <para>The process is more declarative, specifying what should be executed, not how.</para>
  </listitem>
  <listitem>
    <para>Changes to the environment can be implemented by adapting the work item handler.
    The process itself should not be changed.  It is also possible to use the same process
    in different environments, where the work item handler is responsible for integrating
    with the right services.</para>
  </listitem>
  <listitem>
    <para>It is easy to share work item handlers across processes and projects (which would
    be more difficult if the code would be embedded in the process itself).</para>
  </listitem>
  <listitem>
    <para>Different work item handlers could be used depending on the context.  For example,
    during testing or simulation, it might not be necessary to actually execute the work items.
    In this case specialized dummy work item handlers could be used during testing.</para>
  </listitem>
</orderedlist>

  </section>

</section>

<section>
  <title>Service repository</title>
  
  <para>A lot of these domain-specific services are generic, and can be reused by a lot of different
  users.  Think for example about integration with Twitter, doing file system operations or sending
  email.  Once such a domain-specific service has been created, you might want to make it available to
  other users so they can easily import and start using it.</para>
  
  <para>A service repository allows you to import services by browsing the repository looking for
  services you might need and importing these services into your workspace. These will then automatically
  be added to your palette and you can start using them in your processes. You can also import additional
  artefacts like for example an icon, any dependencies you might need, a default handler that will be
  used to execute the service (although you're always free to override the default, for example for
  testing), etc.</para>

  <para>To browse the repository, open the wizard to import services, point it to the right location
  (this could be to a directory in your file system but also a public or private URL) and select the
  services you would like to import.  For example, in Eclipse, right-click your project that contains
  your processes and select "Configure ... -> Import jBPM services ...".  This will open up a
  repository browser.  In the URL field, fill in the URL of your repository (see below for the URL of
  the public jBPM repository that hosts some common service implementations out-of-the-box), or use the
  "..." button to browse to a folder on your file system.  Click the Get button to retrieve the
  contents of that repository.</para>

<mediaobject>
  <imageobject>
    <imagedata align="center" format="PNG" role="" 
               fileref="images/Chapter-DomainSpecificProcesses/ImportService.png"/>
  </imageobject>
</mediaobject>

  <para>Select the service you would like to import and then click the Import button.  Note that
  the Eclipse wizard allows you to define whether you would like to automatically configure the
  service (so it shows up in the palette of your processes), whether you would also like to download
  any dependencies that might be needed for executing the service and/or whether you would like to
  automatically register the default handler, so make sure to mark the right checkboxes before importing
  your service (if you are unsure what to do, leaving all check boxes marked is probably best).</para>

  <para>After importing your service, (re)open your process diagram and the new service should show
  up in your palette and you can start using it in your process.  Note that most services also include
  documentation on how to use them (e.g. what the different input and output parameters are) when
  you select them browsing the service repository.</para>
  
  <para>Click on the image below to see a screencast where we import the twitter service in a new jBPM
  project and create a simple process with it that sends an actual tweet.  Note that you need the 
  necessary twitter keys and secrets to be able to programatically send tweets to your twitter account.
  How to create these is explained <ulink url="http://people.redhat.com/kverlaen/repository/Twitter/">here</ulink>,
  but once you have these, you can just drop them in your project using a simple configuration file.</para>

    <ulink url="http://people.redhat.com/kverlaen/twitter-repository.swf">
      <figure>
        <mediaobject>
          <imageobject>
        <imagedata align="center" fileref="images/Chapter-DomainSpecificProcesses/Twitter.png" format="PNG" role="" />
          </imageobject>
        </mediaobject>
      </figure>
    </ulink>
    
<section>
  <title>Public jBPM service repository</title>
  
  <para>We are building a public service repository that contains predefined services that people can
  use out-of-the-box if they want to:</para>
  <para><ulink url="http://people.redhat.com/kverlaen/repository">http://people.redhat.com/kverlaen/repository</ulink></para>
  <para>This repository contains some integrations for common services like Twitter integration or
  file system operations that you can import.  Simply point the import wizard to this URL to start
  browsing the repository.</para>
  
  <para>If you have an implementation of a common service that you would like to contribute to the
  community, do not hesitate to contact someone from the development team.  We are always looking for
  contributions to extend our repository.</para>

</section>

<section>
  <title>Setting up your own service repository</title>
  
  <para>You can set up your own service repository and add your own services by creating a
  configuration file that contains the necessary information (this is an extended version of the
  normal work definition configuration file as described earlier in this chapter) and putting
  the necessary files (like an icon, dependencies, documentation, etc.) in the right folders.</para>
  
  <para>The extended configuration file contains the normal properties (like name, parameters,
  results and icon), with some additional ones.  For example, the following extended configuration file
  describes the Twitter integration service (as shown in the screencast above):</para>

<programlisting>
import org.drools.process.core.datatype.impl.type.StringDataType;
[
  [
    "name" : "Twitter",
    "description" : "Send a twitter message",
    "parameters" : [
    	"Message" : new StringDataType()
    ],
    "displayName" : "Twitter",
    "eclipse:customEditor" : "org.drools.eclipse.flow.common.editor.editpart.work.SampleCustomEditor",
    "icon" : "twitter.gif",
    "category" : "Communication",
    "defaultHandler" : "org.jbpm.process.workitem.twitter.TwitterHandler",
    "documentation" : "index.html",
    "dependencies" : [ 
      "file:./lib/jbpm-twitter.jar", 
      "file:./lib/twitter4j-core-2.2.2.jar"
    ]
  ]
]
</programlisting>

<para>
  <itemizedlist>
    <listitem>The icon property should refer to a file with the given file name in the same folder as
    the extended configuration file (so it can be downloaded by the import wizard and used in the process
    diagrams).  Icons should be 16x16 GIF files.</listitem>
    <listitem>The category property defines the category this service should be placed under when
    browsing the repository.</listitem>
    <listitem>The defaultHandler property defines the default handler implementation (i.e. the Java
    class that implements the <code>WorkItemHandler</code> interface and can be used to execute the
    service).  This can automatically be registered as the handler for that service
    when importing the service from the repository.</listitem>
    <listitem>The documentation property defines a documentation file that describes what the service
    does and how it works.  This property should refer to a HTML file with the given name in the same
    folder as the extended configuration file (so it can be shown by the import wizard when browsing
    the repository).</listitem>
    <listitem>The dependencies property defines additional dependencies that are necessary to execute
    this service.  This usually includes the handler implementation jar, but could also include
    additional external dependencies.  These dependencies should also be located on the repository
    on the given location (relative to the folder where the extended configuration file is located),
    so they can be downloaded by the import wizard when importing the service.</listitem>
  </itemizedlist>
</para>

  <para>The root of your repository should also contain an <filename>index.conf</filename> file that
  references all the folders that should be processed when searching for services on the repository.
  Each of those folders should then contain:
  <itemizedlist>
    <listitem>An extended configuration file with the same name as the folder (e.g.
    <filename>Twitter.conf</filename>)</listitem> that defines the service task
    <listitem>The icon as references in the configuration file</listitem>
    <listitem>The documentation as references in the configuration file</listitem>
    <listitem>The dependencies as references in the configuration file (for example in a lib folder)</listitem>
  </itemizedlist>
  You can create your own hierarchical structure, because if one of those folders also contains an
  <filename>index.conf</filename> file, that will be used to scan additional sub-folders.  Note that the
  hierarchical structure of the repository is not shown when browsing the repository using the import
  wizard, as the category property in the configuration file is used for that.</para>

</section>

</section>

</chapter>
