sexta-feira, 29 de abril de 2016

A jBPM 6 JPA Work Item Handler implementation

When we work with jBPM, we can already invoke REST and SOAP Web Services, send email without the need of writing a single line of Java code. You can simply drag and drop a component and configure it to perform the action.

Using the REST Task from jBPM 6

Behind a component (tasks), we have a Work Item Handler(WIH):

Creating custom Work Item Handler in BPM Suite/jBPM 6
A Parser work item handler for jbpm 6

In this post I will briefly talk about a work item handler I recently created to perform JPA(Java Persistence API) operations.

Persistence and jBPM


The jBPM process runs on a transaction. Once it reaches a safe point (start a subprocess, human task, timer and others), the transaction is commited. If we do operations that requires a transaction, it is important to these operations to be part of the running jBPM transaction.

To persist process variables, we can use a JPAPlaceholderResolverStrategy and the process variables will be also persisted as part of the process. However, we might want to do operations on a database and don't want specifically to store process variables. For example, you might want to query the database or delete an entity based on some data from the process, that's the reason a JPA task is needed.

An implementation of a JPA work item handler


To allow users to access a database from their business process, we created a JPA work item handler! And what it does is basically allow you to make JPA operations from your business process.

These are the supported parameter input parameters:

  • Action: A String parameter that can have some of the following values:
    • get: Retrieves an entity of type Type from the database by the given Id;
    • delete: Delete the given Entity;
    • create: Create the given Entity in the database;
    • update: Update the given Entity;
    • query: Execute a JPA query passed by the Query parameter with the parameters passed by the QueryParameters
  • Entity: This parameter of type Object is the target entity. Must be provided if using the create, update or delete actions;
  • Type: If you use the get action, you must provide the fully qualified name of the type of the class you are loading in the format of a String;
  • Id: This parameter of type Object is used with the get action to represent the entity Id;
  • Query:  This param of type String must be a JPA valid query that will ran against the database;
  • QueryParameters: The type of this parameter is a java.util.Map that must contains the possible parameters for the query specifiec by Query.
And it may return the following
  • QueryResults: A java.util.List of objects with the result of your query. Only present when using the Query parameter
  • Result: When you do an create, update or delete against an entity, the updated entity will be available in this output parameter. If you use get, you can have the entity that was recovered from the database using ths out param.


Notice that the only obligatory parameter is Action. The other parameters depends on the actin you chose: If you chose delete, create or update, you must provide an Entity parameter. If you choose get, you must provide a Type and an Id parameter. The action query requires you to provide the Query parameter and you *may*  provide the Map QueryParameters param.

Another thing to notice is that this WIH will throw exceptions if something goes wrong, so you can attach an error event to handle it.

Using the JPA WIH

To use it, follow the steps below:

  • Let's consider you are a jBPM user and you are familiar with its concepts: projects, maven and other concepts related to jBPM and also has some experience with jbpm-console web app;
  • Clone the WIH repository locally in your machine: https://github.com/jesuino/jbpm-jpa-wih
  • Go to jpa-wih directory and run $ mvn clean install  (or install it in the maven repository used by jBPM)
  • In a jBPM project, add a dependency to the following module org.fxapps.jbpm: jpa-wih:1.0:
The WIH artifact dependency

  • Now register the WIH using kie-deployment-descriptor.xml. If you open the project editor, you can find a link to the project editor. Register it passing a String which is the persistence unit that the WIH will use, and the classloader reference:
Registering the WIH
  • Now we must add it to the WorkDefinitions file if you want to have it available in the jBPM editor to drag and drop. This can be done by adding a new declaration of a WIH:
  [
    "name" : "JPA",
    "parameters" : [
        "Entity" : new ObjectDataType(),
        "Action" : new StringDataType(),
        "Type" : new StringDataType(),
        "Id" : new ObjectDataType(),
        "Query" : new StringDataType(),
        "QueryParameters" : new ObjectDataType()
    ],
    "results" : [
        "Result" : new ObjectDataType(),
        // Remember to import the List data type: org.drools.core.process.core.datatype.impl.type.ListDataType;
        "QueryResults" : new ListDataType()
    ],
    "displayName" : "JPA",
    "icon" : "defaultservicenodeicon.png"
  ]

How the WIH declaration looks like in the editor

Now we are almost ready to use this WIH, but first we need to configure the persistence and create our persistence unit with the same name we configured in kie-deployment-structure.xml.


The next step is to create the persistence unit we set in kie-deployment-descriptor.xml.The simplest way is:

  • Go to project editor and select Persistence Descriptor. Then configure your persistence descriptor by entering the persistence information. Here's an example:


Persistence configuration
One thing to notice here is that you must use a XA datasource. The reasons is that the datasource transactino will be part of the jBPM transaction, when we involve two databases in the same transaction, we must use a XA datasource. You can avoid issues with it by setting the system property com.arjuna.ats.arjuna.allowMultipleLastResources to true if you are on JBoss EAP/Widlfly, but it not recommended for production environments.

  • When you configure the persistence, jbpm-console will try to be kind with you and will configure the Marshalling Strategy to use the JPAPlaceholderResolverStrategy. Well, we don't need that, so go Project Editor, then Deployment Descriptor and remove it.

Finally we are able to use the JPA work item handler in our project!

Sample project


You will find in my github a really simple sample project with everything I have described here. Below is a video showing it in action.

Boring, right? Ok, next post I will show you an entire CRUD application that even have a web interface using jBPM forms. Stay tuned! 






6 comentários:

  1. Hi sir, I'm having trouble using xa database, can you give me some instructions about configuration (I'm using oracle 12c and jBPM 6.3)? Thank you so much!

    ResponderExcluir
    Respostas
    1. Hello,

      In this case you can simply remove the mentioned property "com.arjuna.ats.arjuna.allowMultipleLastResources" and it should work!

      Excluir
  2. HI william
    this post and your source was very helpful to me. very thanks and regards...

    ResponderExcluir
  3. Thanks for the tutorial, but I have a problem when the server restarts or displays another version, all data is erased.

    As I can make data tables are always maintained?

    Thank you for your contribution.

    regards

    ResponderExcluir
    Respostas
    1. Hello, by default the database will persist only in memory - you must configure a new database in wildfly to persist it - like a mysql database - or configure the ExampleDS to persist to a file - just change the connection URL to file:{path to the file}

      Excluir