Chapter 13. Domain-specific processes
- 13.1. Introduction
- 13.2. Example: Notifications
-
- 13.2.1. Creating the work definition
- 13.2.2. Registering the work definition
- 13.2.3. Using your new work item in your processes
- 13.2.4. Executing service nodes
13.1. Introduction
Most process languages offer some generic action (node) construct that allows plugging in custum 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.
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.
So we want service nodes that are:
- domain-specific
- declarative (what, not how)
- high-level (no code)
- customizable to the context
13.2. Example: Notifications
Name: "Notification" Parameters From [String] To [String] Message [String] Priority [String]
13.2.1. Creating the work definition
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:
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" ] ]The project directory structure could then look something like this:
project/src/main/resources/META-INF/MyWorkDefinitions.widYou 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:
project/src/main/resources/icons/notification.gif
13.2.2. Registering the work definition
drools.workDefinitions = MyWorkDefinitions.widThis 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:
drools.workDefinitions = MyWorkDefinitions.conf WorkDefinitions.conf
13.2.3. Using your new work item in your processes
Apart from the properties defined by for this work item, all work items also have these three properties:
- Parameter Mapping: Allows you 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).
- 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.
- 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.
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" ] ]
// 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
13.2.4. Executing service nodes
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 } }This WorkItemHandler sends a notification as an email and then immediate 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.
WorkItemHandlers should be registered at the WorkItemManager, using the following API:
ksession.getWorkItemManager().registerWorkItemHandler( "Notification", new NotificationWorkItemHandler());Decoupling the execution of work items from the process itself has the following advantages:
- The process is more declarative, specifying what should be executed, not how.
- 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.
- 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).
- 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.
For more information follow my Tutorial online @ http://jbpmmaster.blogspot.com/
No comments:
Post a Comment