Working on improve our knowledge about the Drools platform and to give something back to the community. This time we’ll discuss a language extension called Work Items. The official documentation says: “[Drools Flow] offers constructs that are closely related to the problem the user is trying to solve”. In other words, creating your own WorkItems lets you extend the business modeling language to a domain oriented way.
Creating a language for your process gives you an enormous flexibility in what you can express. The funny thing is that with this great power doesn’t come a great responsibility, meaning there is no more responsibility than needed to write any bored and unflexible process language.
Creating Work Items
As I’m talking to business analysts that have everything organized, I can ask you to look at your white boards closely and think which nodes have actions that involve the process itself. What needs to be achieved in every node, not how it will be made. Once you have your palette in mind you can refer to 8.2. Example: Notifications of the official documentation to learn how to integrate it with the Eclipse Flow Editor.
If you are a sharp vi-editor pal and want to get your hands dirty writing BPMN2 xmls on your own, you have to know that Work Items in Drools Flow are represented with Task nodes and they use its taskName atributte to relate it with the WorkItemHandler (a.k.a “where action happens”).
In this example you can see it
<definition> ... <process> ... <task id="_2" name="SafePoint" tns:taskName="SafePoint" /> ... </process> ... </definition>
To get more information about Task nodes you can refer to the BPMN2 draft specification here, chapter 10.2.3
It’s important to note that you only define what has to be done, not how. Keep reading if you are curious about that :)
Running your own solution for a given Work Item is as easy as telling the KnowledgeSession which handler will react when the process reaches one of this nodes. This is done through the WorkItemManager obtained from the ksession.
ksession.getWorkItemManager().registerWorkItemHandler(“MyVerySpecialWorkDomainAttached”, new MyVerySpecialWorkDomainAttachedHandler());
MyVerySpecialWorkDomainAttachedHandler implements org.drools.runtime.process.WorkItemHandler which has two methods: executeWorkItem and abortWorkItem, pretty autodescriptive names.
Now every time your session runs the process, it will execute your registered handler. Cool huh?
Only one caveat! Remember to reregister the handlers if you load the session from a persistent storage, because this information doesn’t belong to the runtime of the session thus is not persisted
Work Items behind the scenes
As the business analyst defines the semantics about Work Item, it is up to the developer to define how this will be implemented. Part of this decision involves dealing with the flow of the process, meaning if it should or should not be paused until the action finishes its execution. To inform the session that the Work Item has been completed, this has to be done through WorkItemManager, usually as follows:
• if you are inside WorkItemHandler, manager.completeWorkItem(workItem.getId());
• if you are at StatefulKnowledgeSession level, ksession.getWorkItemManager().completeWorkItem(workItemId)
As you notice here, you will need the id of the managed work item.
To get the list of uncompleted work item ids, it’ll depend on a contract between your application and the implementation of the handler. There have been some discussions recently in the mailing list about who should be responsible for getting the list. From the Drools point of view Salaboy makes a good point and Kris gives a summary of the idea.
The main idea is, if you have an specific node in your domain, you are the only one who knows what information is needed to achieve the task and who you should ask for this information. Furthermore, your long-running-remote-asynchronous task is going to need information collected along your process to complete it, all this information is part of the protocol between your application/process and the outside world to react when the process reaches its node. When these external part of your system completes, the execution will alert you about the completion and should be able to inject new information to the process. Again, it is up to you to push the results into the session and continue execution.
This is the general way used for implementing Human Tasks but it is the subject of some next post.
Work Items in action
As a teeny-weeny example of this concepts we have developed a web application that you can download from here and simple run it with ‘mvn jetty:run’.
Any feedback is absolutely welcome and rewarded with a glass of cold beer at a bar in my town (only applies for people with more than two degrees of separation from me :P)