Thursday, July 12, 2012

Working with jBPM 5


I just wanted to say a few words about jBPM. jBPM is a great product that comes from JBoss and used with several other technologies we can use it to make effective and easy to understand workflow. Our task was to replace current Java based back-end and integrate it loosely with jBPM with possibility to replace BPM engine with some other vendor in the future, if needed. Together with this we would need to modularize our back-end and expose it to BPM adding greatly to the ability for our customers to custom craft and change processes to the way that best fits their business. We already have a great platform for insurance and BPM should make it even better and more versatile. Time to change the process flow and to apply new design should be dramatically cut after BPM is introduced.

After some time of using it I have to say that it is a great product that comes free and that will add a lot of value to already established backend.

In this blog I want to point out to several problems that costed me a lot of time to figure it out and hopefuly this should make understanding jBPM easier.

To start of we needed some documentation and found some basic usages on the JBoss site. It should be enough to start using jBPM but I have to say that initially I was not pleased with the amount of details and some complex usages requirements that we had. We needed following components to make this work:

  1. jBPM libraries
  2. Drools libraries 
  3. Guvnor and Designer setup
  4. Database setup for jBPM

Our deployment and usage was for JBoss 5.1 and Lifray 6. Database version was not much important except that we needed three extra data sources.

  1. Data source to load users from Liferay into BPM database so we can use it to assign human tasks to our users and verify user roles and groups when accessing MINA server
  2. Data source for BPM
  3. Data source for Human Task Service

Please note that all three data sources were implemented using JPA as this is JBoss implementation. The difference in our application is that we needed to combine such approach with Hibernate mapping files that we already had. One of the big issues that I have faced was initiating EntityManagerFactory. Initiating this factory in the middle of the EJB call was not an option, so creating JNDI connection when JBoss started was a way to go.

Sample code:

In persistence.xml:

<property name="jboss.entity.manager.factory.jndi.name" value="java:/jBPMManagerFactory"/>


In your code:

try {
   emf = (EntityManagerFactory) new javax.naming.InitialContext().lookup("java:/jBPMManagerFactory");
} catch (NamingException e) {
   e.printStackTrace();
}



Our code structure was also a bit different from the examples as we had this call structure: Web->Business Delegate->EJB (Stateless)->BPM->Java back-end. The problem is that command based listener is coded in such a way that is has asynchronous code inside that assumes that your session is stateful. In our case this was not good and we needed to rewrite this listener into two classes, one that would create human tasks and other that would process messages with blocking handler. Otherwise, you would need to create some loop to wait for the execution of the code (checking status of the process) in some cases or your EJB call would end up sooner than BPM call.

Some of the other things that need to be watched for is that when you create knowledge base (talking about KnowledgeBuilderFactory), you would preferably do it as a singleton, as creating and importing resources every time takes valuable time. We chose not to bind our application to Guvnor and we decided to use Guvnor only as a development resource (we already have plenty of repositories to worry about).

JBPMHelper is a nice class to start with and I used most of it while rewriting some parts to offer better separation when doing unit tests (during Maven builds) and production usage. We also needed to integrate our configuration engine there and to apply custom created command based listener.

When developing for jBPM pay close attention to ksession.dispose();. You need to call this when you no longer want to work with BPM as resources are not automatically disposed.

Creating custom work item handler is a must in BPM when you have much back-end code, so here are couple of tips that might save you some time. When handling Exceptions, pay close attention to nesting in BPM depending on your structure as you might end up messing up some of the transactions. BPM code executes like this A->B->C->code->C->B->A. In the middle of that you should properly completeWorkItem or abortWorkItem. It is important that you catch your exception and know what to do with it rather that let BPM decide. In our case letting BPM decide what to do was not a good option.

One of the things that I like to do is to group work items so I do not have to write same code over and over again. This means that I would have one input parameter called "function" that would indicate which peace of code would I like to execute once the work item is called. If you have dozens of function, this will save you a lot of time.

Finally, I would like to say a few words about a Designer. A developer from JBoss helped me a lot (Tihomir Surdilovic) with understanding and I wish to thank him for that. For a free product, it offers great possibilities and it is very easy to work with. Your developers and customers will enjoy using it. I say customers as you can expose this directly to them to create shell of a processes that can be later passed on to developer to implement some basic "plumbing". Customer->BA->Developer integration was never more easier.

Designer comes as separate WAR that is deployed together with Guvnor. Guvnor is a repository and the Designer is a tool to craft your processes. Here are a few tips for using and deploying it. When deploying, rename wars to guvnor.war and designer.war Guvnor can find Designer. When creating processes, you can rollback to previous version. Just open process, go to Attributes->Version History and select which version do you want. If you need to delete anything, you need to archive it first and then delete it from the archive. When deploying your resources, I strongly advise you to deploy them as a package (you need to compile them and then package all resources). This way, it will be easy to bundle all the data in a single file and give it a version. The only problem that you might have is the migration of the current processes to the new version if there are saved processes in the database. This means that you will need to convert those manually as they will not be able to deserialize into a new process structure.

These are just a few tips and I intend to write more about BPM and Drools as we progress with development and integration of the BPM into our own platform.

Here are some of the useful links:

  1. BPM User Guide
  2. Guvnor Manual
  3. Drools Introduction
  4. Tihomir's Blog


Thanks

2 comments:

  1. Hi Branislav Cavlin, can you please tell me how to manage versioning in JBPM5.4 new flow chart for new and old flow chart for old

    ReplyDelete
  2. When you are adding resources to KnowledgeBuilder you need to add old and new bpmn2 files if that is how you are loading your process templates (from files). Guvnor will update version of the changed diagram when you check it in but that is only for history purposes. Old versions are needed for already running processes. I was keeping the version as part of the file name. E.g.

    KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
    kbuilder.add(ResourceFactory.newClassPathResource("bpmn/process.v1.bpmn2"), ResourceType.BPMN2);
    kbuilder.add(ResourceFactory.newClassPathResource("bpmn/process.v2.bpmn2"), ResourceType.BPMN2);

    You also need to update process name, if I remember correctly.

    You can do the similar thing with packages but it really depends what you are trying to achieve.

    ReplyDelete