domingo, 22 de abril de 2018

Using jBPM embedded and CDI in a JavaFX application

A few years ago I wrote about using jBPM remote API from JavaFX. That was straightforward because the remote APIs are usually simply wrappers to REST APIs running on server side.
Since then a few things happened:

  • jBPM is in version 7.7, that article was for jBPM 6.3.0!
  • In version 7 the Business Central execution server was replaced by Kie Server (we even wrote a JavaFX client for Kie Server)
  • A new jBPM services API was introduced and it is mature and ready for production use.
  • CDI 2.0 was released and it allows the use of CDI in standalone Java applications ( and in a JavaFX application as we described).

We could use jbpm embedded at that time, but we would have to make use of underlying Kie APIs (RuntimeManager, KieSession, etc), which I was not willing to use at that time. With services API we can easily bring jbpm to every Java application, just just one of its flavors: CDI, EJB, Spring or pure Java.

But what is different from using embedded jbpm from Kie Server? Basically the engine will run inside the Java client application, which means that it will not rely on a central server to execute the business processes:

There might be the case where you don't want to maintain a central server and put the execution on the client. It is hard to defend such model in Cloud Computing days. create docker image and orchestrate it on Openshift. And I agree with it, 96.9% (made up statistic) of the cases will be better handled by this model. However, with an embedded client the jbpm engine execution will happen on the client, which means that we will remove the server for processes execution and we will optionally share a database between the clients:

In this model you may have a shared database or a shared maven repository. The jBPM API is very flexible, you can run it without a database and loading process definitions from the file system. The use cases for it may be:
  • Small business: they may not want to maintain a server or contract a cloud service, but they know the advantages of using jBPM to model their processes;
  • IoT: you may want to have local processes execution in IoT devices and avoid a single point of access;
  • Apartment complex: control garage, residents, apartment occupancy, visitants flow and other aspects of an apartment complex  may be done using BPM tools.
In any case, I managed to run jBPM on a JavaFX application with CDI and I would like to share it with you. The source is already on my github and it uses the same view from the Rewards Client we used with the Business Central remote API. This is what you need to know:
  • We use CDI, which means that after configuring jBPM (see package ) we can simply inject jBPM service in our application (ProcessService, UserTaskService, RuntimeDataService and more);
  • You have two datasource: in memory H2 or MySQL, by default it will connect to MySQL, see the class DatasourceSetup for more information;
  • It is JavaFX and Java 8. in Java 11 JavaFX will be removed from the JDK and you may use OpenJFX and OpenJDK in your commercial application, get JavaFX support from Gluon (if you want) and jBPM embedded support from Red Hat (if you want). If you don't want it, you should (hopefully) be free to build your commercial application based on these APIs.
The application structure show us that we need a few classes to configure jBPM (see conf directory). The API usage happens on RewardsServiceEmbeddedCDI.

That is all I wanted to share. Usually BPM users are big company, but embedded jBPM is a flexible and lightweight alternative for those who don't want to use a central server for processes execution. Of course the same API can be used in a Web application, but we will talk about it in future posts.

sexta-feira, 16 de fevereiro de 2018

Getting Started with Red Hat Decision Manager

Red Hat released Red Hat Decision Manager and we already have a few resources for those who want to quickly get starting with RHDM.  For those who are not familiar, RHDM is based on the community project called Drools, so what you see here will probably work with Drools 7 as well.

Here's our mandatory hello world application from rule authoring to deployment:

More applications like this can be found in my github.

Of course, there is always the great RHDM documentation.

quarta-feira, 24 de janeiro de 2018

Detecting objects using JavaFX and Deep Learning

Computer vision meets Deep Learning mainly due the use of Convolutional Neural Networks. We have used it in our blog already for labeling images. Another challenging area of Deep Learning and computer vision is to identify the position of objects and for this we have a great neural network technique (or architecture - you choose the best) called YOLO. The following video will show you the power of YOLO neural networks:

The output of a neural network such as Resnet50 is a vector with probabilities of labels. So you feed it with an image that contains a cat, it will output various float numbers in an array, each position of that array is a label and the value on that position is the possibility of that label. As an example let's think about a neural network that should recognize dogs (0) and cats (1), and you feed it with an image of a cat, it should output an array of two positions and 0% in position 0 (which represents dog) and 100% in position 1 (which represents cat). The different with YOLO is that it will also output bounding box for the objects detected on an image. So if you show it an image with dogs and cats it will show the label for a given detected object and also the position of that object in a bounding box.

From YOLO web site:

The following presentation from Siraj explains more about YOLO and there's also the AndrewNG coursera classes about object detection.

Ok, how do I use it in Java? As you know Eclipse DeepLearning4J is one of the best framework for deep learning with Java and I found in their git that they are working on a YOLO Zoo model! So we have it already trained out of the box for our use. This is what we are going to use today.

Note: We can also import Keras model - but I didn't find a good keras YOLO model that actually worked with the DL4J import API.


This amazing tool called DL4J has a TinyYOLO (less precise than YOLO, but faster),  model ready for use. Thanks for Samuel Audet on DL4J gitter channel I found great utility tools that quickly helped me to get the YOLO output information without having to maintain my (at that moment) cumbersome code.

The TinyYOLO model will likely be in DL4J 0.9.2. At the time of this writing it was not yet released, but we can use the SNAPSHOT version!

The model is just like any other. The output is also a INDArray, and you can read it manually or use the great utility method from org.deeplearning4j.nn.layers.objdetect.Yolo2OutputLayer:

INDArray output = yoloModel.outputSingle(img);
Yolo2OutputLayer outputLayer = (Yolo2OutputLayer) yoloModel.getOutputLayer(0);
outputLayer.getPredictedObjects(output, threshold);

The object returned by getPredictedObjects is a DetectedObject which contains all the information about the position of the detected object. The position is relative to the box that it is located (YOLO divides the image and X, Y squares). We must calculate the position in the image. I took this code againt from saudet: (and modified it):

for (DetectedObject obj : predictedObjects) {
String cl = yoloModel.getModelClasses()[obj.getPredictedClass()];
double[] xy1 = obj.getTopLeftXY();
double[] xy2 = obj.getBottomRightXY();
int x1 = (int) Math.round(w * xy1[0] / gridW);
int y1 = (int) Math.round(h * xy1[1] / gridH);
int x2 = (int) Math.round(w * xy2[0] / gridW);
int y2 = (int) Math.round(h * xy2[1] / gridH);
int rectW = x2 - x1;
int rectH = y2 - y1;
ctx.strokeRect(x1, y1, rectW, rectH);
ctx.strokeText(cl, x1 + (rectW / 2), y1 - 2);
ctx.fillText(cl, x1 + (rectW / 2), y1 - 2);

This is our simply application that allow you to play with TinyYOLO model or any other YOLO model, which means you can train your own YOLO model and use the app to analyse any image you want. Make sure to set the following system properties, otherwise the default TinyYOLO will be used

model.path: The full path to the model file in your disk
model.classes: the comma separated classes, for example: person,bike,car The input info in a format width,height,channels, for example: 416,416,3
model.grid: The grids in format w,h, for example: 13,13.

Our application also allow us to set the threshold to remove objects which confidence is too low. With a low threshold we have many boxes, with a high threshold a many predictions are discarded:

Adjusted the threshold and it detected a few objects with precision

Smallest threshold and what we have is a mess!

High threshold and we lose some detections

The application allow zoom and scrolling using a code I found in a JavaFX forum. I just made a few changes and it works really well!

Zoom in the image

That's just a small PoC with the YOLO model. There are improvements. I was initially planning to bring a video with object detection in real time, but the model is too slow on my machine (1 frame per second). If I have a machine with GPU I will make a test and post to this blog again.

In a new version we could remove redundant boxes!

Finally this is it, guys. DL4J developers are doing such amazing job bringing deep learning for Java. I think DL4J will be one of the most important library for Java once the market start to understand how deep learning will change their business!

Find the application code in my github.

sábado, 30 de dezembro de 2017

MicroProfile Config from a JavaFX application

Most of you probably heard about Eclipse Microprofile, including Microprofile Config. A quick try from a desktop application that uses JavaFX shows that it works without any additional configuration: just add a implementation dependency to your classpath and you can use microprofile config. See below a simple example.

This results in:


Microprofile config works with JavaFX and this is great news. Microprofile is evolving quickly and JavaFX being able to work with it will give Java developers the ability to easily integrate desktop applications with java microservices.