2018/11/27

Audit log mode applied to all audit data

jBPM allows to store so called audit logs in various modes

  • JPA (default)
  • JMS
  • None
JPA mode means that data will be stored directly and within the same transaction as process execution. That usually have some additional performance overhead although it's certainly not significant and unless huge volume is expected is a sound default setting.

JMS mode means that all audit data will be stored in background and the engine will push all required data via JMS layer. That allows to offload main thread from being responsible for storing audit logs and then allow to process more process instances while JMS listener will deal with storing audit logs in background.

None mode means that audit logs won't be stored at all, which might make sense in some cases (usually straight through processes) so the audit data is not required. Keep in mind that with disabled audit logs (set to None mode) both jBPM console and Kie Server features are limited as they do rely on audit data.

Until 7.15 audit mode applied only to process related audit data and that consists of
  • ProcessInstanceLog
  • NodeInstanceLog
  • VariableInstanceLog
it has been improved to cover all audit logs that span across processes, user tasks and cases. With that said it covers (in addition to listed above) following
  • AuditTaskImpl
  • TaskEvent
  • TaskVariableImpl
  • CaseFileDataLog
  • CaseRoleAssignmentLog
BAMTaskSummary is not covered with audit mode except for NONE mode which also disables BAM logging.

Configuration

JPA and NONE mode do not require additional configuration and can be used directly after installation. JMS does need a bit of configuration to allow to take advantage of JMS layer.

This sample configuration assumes the runtime environment is based on WildFly (or EAP) as application server.

Enable JMS queue creation in kie-server-jms.xml

First you need to enable dedicated JMS queue for sending audit data through. To do so, go to  kie-server.war/META-INF and edit kie-server-jms.xml file. Locate the commended queue named KIE.SERVER.AUDIT and uncomment the entire queue configuration, it should look like

<messaging-deployment xmlns="urn:jboss:messaging-activemq-deployment:1.0">
  <server name="default">
    <jms-destinations>

      <!-- Kie Server REQUEST queue -->
      <jms-queue name="KIE.SERVER.REQUEST">
        <entry name="queue/KIE.SERVER.REQUEST" />
        <entry name="java:jboss/exported/jms/queue/KIE.SERVER.REQUEST" />
      </jms-queue>

      <!-- Kie Server RESPONSE queue -->
      <jms-queue name="KIE.SERVER.RESPONSE">
        <entry name="queue/KIE.SERVER.RESPONSE" />
        <entry name="java:jboss/exported/jms/queue/KIE.SERVER.RESPONSE" />
      </jms-queue>

      <!-- Kie Server EXECUTOR queue -->
      <jms-queue name="KIE.SERVER.EXECUTOR">
        <entry name="queue/KIE.SERVER.EXECUTOR" />
      </jms-queue>

      <!-- JMS queue for signals -->
      <!-- enable when external signals are required -->
      <!--
      <jms-queue name="KIE.SERVER.SIGNAL.QUEUE">
        <entry name="queue/KIE.SERVER.SIGNAL" />
        <entry name="java:jboss/exported/jms/queue/KIE.SERVER.SIGNAL" />
      </jms-queue>
      -->

      <!-- JMS queue for audit -->
      <!-- enable when jms mode for audit is required -->
      <!---->
      <jms-queue name="KIE.SERVER.AUDIT">
        <entry name="queue/KIE.SERVER.AUDIT"/>
        <entry name="java:jboss/exported/jms/queue/KIE.SERVER.AUDIT"/>
      </jms-queue>

    </jms-destinations>
  </server>
</messaging-deployment>

Enable message listener in ejb-jar.xml

Next, go to kie-server.war/WEB-INF and edit ejb-jar.xml file. Locate  CompositeAsyncAuditLogReceiver and uncomment entire section for that message driven bean. Also uncomment the enterprise-beans tags for the document.
It should look like below
<ejb-jar id="ejb-jar_ID" version="3.1"
      xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                          http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd">


  <!---->
  <enterprise-beans>

  <!-- enable when external signals are required and queue and connection factory is defined
    <message-driven>
      <ejb-name>JMSSignalReceiver</ejb-name>
      <ejb-class>org.jbpm.process.workitem.jms.JMSSignalReceiver</ejb-class>
      <transaction-type>Bean</transaction-type>
      <activation-config>
        <activation-config-property>
          <activation-config-property-name>destinationType</activation-config-property-name>
          <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
        </activation-config-property>
        <activation-config-property>
          <activation-config-property-name>destination</activation-config-property-name>
          <activation-config-property-value>java:/queue/KIE.SERVER.SIGNAL</activation-config-property-value>
        </activation-config-property>
      </activation-config>
    </message-driven>
    -->

    <!-- enable when jms mode for audit is required and queue and connection factory is defined-->
    <message-driven>
      <ejb-name>CompositeAsyncAuditLogReceiver</ejb-name>
      <ejb-class>org.jbpm.kie.services.impl.CompositeAsyncAuditLogReceiver</ejb-class>
      <transaction-type>Container</transaction-type>
      <activation-config>
        <activation-config-property>
          <activation-config-property-name>destinationType</activation-config-property-name>
          <activation-config-property-value>javax.jms.Queue</activation-config-property-value>
        </activation-config-property>
        <activation-config-property>
          <activation-config-property-name>destination</activation-config-property-name>
          <activation-config-property-value>java:/queue/KIE.SERVER.AUDIT</activation-config-property-value>
        </activation-config-property>
        <activation-config-property>
          <activation-config-property-name>maxSession</activation-config-property-name>
          <activation-config-property-value>1</activation-config-property-value>
        </activation-config-property>
      </activation-config>
    </message-driven>

  <!---->
  </enterprise-beans>

</ejb-jar>


Configure JMS related config for audit logs

Lastly, go to kie-server.war/WEB-INF/classes and rename the wildfly-jbpm.audit.jms.properties to jbpm.audit.jms.properties

And that's all that is required to make use of JMS audit logging in jBPM. For other applications servers, make sure to create JMS queue (and then refer to it in ejb-jar.xml file) according to application server guides for JMS.

2018/11/16

jBPM empowered by Camel to integrate with ... everything!

Apache Camel is extremely powerful integration library, comes with hundreds of components to integrate with 3rd party systems. jBPM on the other hand provides great support for business processes and cases. In many situations data produced by jBPM is required to be pushed to external systems or business processes would need to be informed about changes in external systems that can influence business logic.

So why not combine these two and provide state of the art business solution that can focus on business goals and yet integrate with pretty much anything in the world.

Improved camel-jbpm component

camel-jbpm component has been added in 2.6 version of Camel. At that time it was based on jBPM 6.5 and provided only producer based on kie-remote-client that interacts with jBPM console (aka workbench) REST api. It's been a while since then and even more important jBPM Console REST api for execution does not exists any more and same applies for kie-remote-client. It has been replaced completely with way more powerful kie server client.

So it was high time to improve the camel-jbpm component to first of all upgrade to latest version (7.14) and replace use of kie-remote-client with kie-server-client for producer usage. And to provide consumer support as well that will enable simple integration with outside world for pushing out data from jBPM.

So when it comes to consumer of camel-jbpm component users can now take advantage of following integrations of jBPM empowered by Camel
  • ProcessEventListeners
  • TaskLifeCycleEventListeners
  • CaseEventListeners
  • EventEmitter
All of these can be easily configured as Camel routes, here is a simple example that will be triggered upon process events being generated by jBPM

<routes xmlns="http://camel.apache.org/schema/spring">
    <route id="processes">
        <from uri="jbpm:events:process"/>
        <filter>
          <simple>${in.header.EventType} == 'beforeProcessStarted'</simple>
          <to uri="log:kjar.processes?level=INFO&amp;showBody=true&amp;showHeaders=true"/>
        </filter>
    </route>
</routes>

as you can see as soon as there will be events produced on the jbpm:events:processes a new exchange will be processed that will simply go over filter and get only beforeProcessStarted events (each event type is set as header) and the body is actual event produced by jBPM.

NOTE: if you need more than one on the same consumer type you should suffix it with sort of classifier to make the endpoints unique jbpm:events:process:startedOnly

Similar endpoints can be used for user tasks and cases

  • jbpm:events:tasks
  • jbpm:events:cases

Configure routes

Routes can be configured either on application level (kie server or business app) or kjar level. 

camel-jbpm component comes with KIE server extension that will be automatically registered in KIE Server when the jar file is present - see Installation section for more details on it.

Global routes should be created in the root of the application class path (kie-server.war/WEB-INF/classes) in a file name global-camel-routes.xml

Such global routes will apply to all deployed kjars in KIE Server.

KJAR specific routes can also be used by placing camel-routes.xml file in the root of kjar class path (src/main/resources folder of the kjar source). When such file is found new (kjar scoped) CamelContext is created with all routes defined in that file. These routes will only apply to that specific KIE Container.


Installation

Installation is really simple, it requires to drop two jar files into kie-server.war/WEB-INF/lib
  • camel-core
  • camel-jbpm
and that's it, start the server and you will see that Camel KIE Server extensions boots and does its thing :)

In case you would like to use another component to interact with, you need to do the same, drop the component jar file and its runtime dependencies. For the sake of example we use camel-kafka that requires these jar files to be placed in kie-server.war/WEB-INF/lib
  • camel-kafka-2.19.0.jar
  • kafka-clients-0.10.2.0.jar
  • lz4-1.3.0.jar
  • snappy-java-1.1.2.6.jar
NOTE: Make sure to use camel-kafka and kafka-clients matching your Kafka cluster.

Example

A simple use case to illustrate is to take advantage of the camel-jbpm consumer to react to events produced by jBPM for both tasks and processes
  • for tasks we just log them to console
  • for processes we push them out to Kafka
here is the camel-routes.xml for this example
<routes xmlns="http://camel.apache.org/schema/spring">    
    <route id="processes">
        <from uri="jbpm:events:process:test"/>
        <filter>
          <simple>${in.header.EventType} starts with 'before'</simple>
          <transform>
            <simple>${in.header.EventType} for process instance ${body.processInstance.id}</simple>
          </transform>
          <to uri="kafka:TestLog?brokers=localhost:9092"/>
        </filter>
    </route>
    
    <route id="tasks">
        <from uri="jbpm:events:task:test"/>
        <filter>
          <simple>${in.header.EventType} starts with 'before'</simple>
          <to uri="log:kjar.tasks?level=INFO&amp;showBody=true&amp;showHeaders=true"/>
        </filter>
    </route>
</routes>

and here is just a short screencast showing this in action


IMPORTANT: This improved camel-jbpm component is not yet released, it will go out with Apache Camel 2.23.0 release that is expected to be out in couple of days from now. So prepare yourself and make sure to give it a go.


A sample project with just camel logging the events can be found here.

Implement your own form renderer for KIE Server

As it was described in this article, KIE Server now provides form renderers for process and task forms built in jBPM Console (aka workbench). Out of the box there are two renderers provided

  • based on PatterFly to provide same look and feel as entire jBPM tooling - it's the default renderer
  • based on Bootstrap to provide a simple alternative that utilises well established framework for building web and mobile UIs
This obviously won't cover all possible needs of users and thus the renderers are actually pluggable. In this article we build a custom one from scratch to illustrate what it takes to have your own.

Create project with dependencies

First of all, a new maven project needs to be created. It should be most basic project with packaging jar. Then let's add required dependencies to pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.kie.server.samples</groupId>
  <artifactId>custom-form-renderer</artifactId>
  <version>1.0.0</version>
  <name>Custom Form Renderer</name>
  
  <properties>
    <version.org.kie>7.14.0.Final</version.org.kie>
  </properties>
  
  <dependencies>
    <dependency>
      <groupId>org.kie.server</groupId>
      <artifactId>kie-server-services-jbpm-ui</artifactId>
      <version>${version.org.kie}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
</project>

Create configuration folders

Create folders in the project that will configure the renderer - all should be done src/main/resources
  • form-templates-providers - folder that will contain templates, css and java script files used to render the form
  • META-INF/services/org.kie.server.services.jbpm.ui.form.render.FormRenderer - an empty file that will be used as discovery mechanism to find and register the renderer - it will be edited a bit later to provide actual implementation details

Create form renderer implementation

In src/main/java create a class (e.g. org.kie.server.samples.CustomFormRenderer) that will extend org.kie.server.services.jbpm.ui.form.render.AbstractFormRenderer and implement the required methods 
  • getName - provide the name of the template that shall be used as reference when rendering
  • loadTemplates - main implementation that loads different types of templates to be used by renderer
  • default constructor
IMPORTANT: this new class must be configured as the implementation of the renderer so add its fully qualified class name into 
META-INF/services/org.kie.server.services.jbpm.ui.form.render.FormRenderer

There are several types of templates that renderer must provide (and load on startup)
  • master - main template that builds the HTML page
  • header - header template that creates header of the form
  • form-group - form input fields template
  • case-layout - layout for case forms
  • process-layout - layout for process forms
  • task-layout - layout for user task forms
  • table - table to be build for multi subforms
The easiest way is to base your customisation on top of the out of the box templates (either patternfly or bootstrap). In this example I will use bootstrap templates that can be found here.

Copy all resources from the linked directory into 
src/main/resources/form-templates-providers/custom

and then implement the loadTemplates method of the CustomFormRenderer class
package org.kie.server.samples;

import org.kie.server.services.jbpm.ui.form.render.AbstractFormRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class CustomFormRenderer extends AbstractFormRenderer {
    
    private static final Logger logger = LoggerFactory.getLogger(CustomFormRenderer.class);

    public CustomFormRenderer() {
        super(null,  null);
    }
    
    public CustomFormRenderer(String serverPath, String resources) {
        super(serverPath, resources);
    }
    
    public String getName() {
        return "custom";
    }

    @Override
    protected void loadTemplates() {
        loadTemplate(MASTER_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/master-template.html"));
        loadTemplate(PROCESS_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/process-layout-template.html"));
        loadTemplate(TASK_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/task-layout-template.html"));
        loadTemplate(FORM_GROUP_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/input-form-group-template.html"));
        loadTemplate(HEADER_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/header-template.html"));
        loadTemplate(CASE_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/case-layout-template.html"));
        loadTemplate(TABLE_LAYOUT_TEMPLATE, this.getClass().getResourceAsStream("/form-templates-providers/custom/table-template.html"));
        
        logger.info("Custom Form renderer templates loaded successfully.");
    }

}

Customise your templates

Since the templates where copied from another renderer we need to customise it, let's start with master template. Open it and replace ${serverPath}/bootstrap with ${serverPath}/custom  
This will ensure that our customised files will be loaded.

Make any additional changes to the master template as needed. I will just add custom text next to header.

Master template is the place where you can add additional scripts or stylesheets. There is main js file called kieserver-ui.js that provide all the logic required to manage and submit forms. It also includes validation, so in case you need extensions to that logic consider to create new file with your changes and replace the location of it to point to your new file.

Make additional customisation to other templates as needed.

Build and deploy renderer to KIE Server

Implementation is completed so now it's time to build the project and deploy to KIE Server.
  • Build the project with maven - mvn clean package
  • Deploy the project to KIE Server by coping the jar file to kie-server.war/WEB-INF/lib
Start the server and take advantage of your custom renderer by using following URL that works for one of the sample projects - Evaluation (make sure to deploy it before using the renderer).

http://localhost:8080/kie-server/services/rest/server/containers/evaluation/forms/processes/evaluation/content?renderer=custom

http://localhost:8080/kie-server/services/rest/server/containers/evaluation/forms/tasks/1/content?renderer=custom

As you can see new renderer is fully operational and customised to your needs.

That's it, you have now your custom form renderer. The sample described in this article can be found in GitHub.