Hey
Wanted to share a new prototype we have been working on.
Still very much a work in progress and an experimental exercise, but it is showing interesting progress.
The goal was the leverage the power of Eclipse Vertx.io’s polyglot/multi-language capabilities and provide a very flexible way to add API Endpoints to Camunda’s engine.
So a developer could build new endpoints in Javascript, Ruby, Kotlin, Java, Scala, etc, and they all seamlessly interact directly with the Java API of the engine, allowing more flexibility.
Additionally we could take advantage of Vertx’s HTTP verticle factory capabilities to allow endpoints to be added or removed during runtime / no downtime:
which allows deploying “verticles” in a format such as: vertx.deployVerticle("https://myserver.net/myverticle.zip::my-service", ...)
With the great working going on with the Spring Boot support for Camunda, the goal/use case was fairly trivial to test:
Creating a Spring Boot Application (with WebApps and Rest API), and our Application Class such as:
package io.digitalstate.vertxcamunda;
import org.camunda.bpm.spring.boot.starter.annotation.EnableProcessApplication;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import io.vertx.core.Vertx;
@SpringBootApplication
@EnableProcessApplication
public class VertxCamundaApplication {
final static Vertx vertx = Vertx.vertx();
public static void main(String... args) {
vertx.executeBlocking(future -> {
SpringApplication.run(VertxCamundaApplication.class, args);
future.complete();
}, res -> {
System.out.println("Camunda has been deployed!!!");
deployVerticle();
});
}
public static void deployVerticle() {
vertx.deployVerticle("myVerticle.js");
}
}
and a myVerticle.js file in the resources folder (this “entrypoint verticle” would be abstracted outside of the Jar in actual use cases. The Entrypoint would be completely configurabled as a Jar argument during java -jar myCamunda.jar -entrypoint /path/to/myVerticle.js
:
// vertxStart and vertxStop are functions that are automatically
// called when the verticle is Deployed and UnDeployed
exports.vertxStart = function() {
console.log('Primary Javascript Vertx Verticle is Deployed')
}
exports.vertxStop = function() {
console.log('Primary Javascript Vertx Verticle has UnDeployed')
}
// Get the Default Process Engine
// ProcessEngines: https://docs.camunda.org/javadoc/camunda-bpm-platform/7.8/org/camunda/bpm/engine/ProcessEngines.html
var ProcessEngines = Java.type('org.camunda.bpm.engine.ProcessEngines')
var processEngine = ProcessEngines.getDefaultProcessEngine()
// Get the Repository Service
var repositoryService = processEngine.getRepositoryService()
// See the following for other services you can access:
// Engine Services: https://docs.camunda.org/javadoc/camunda-bpm-platform/7.8/org/camunda/bpm/engine/ProcessEngineServices.html
// Json handling using Camunda Json Util library. See link for more details:
// https://docs.camunda.org/javadoc/camunda-bpm-platform/7.8/org/camunda/bpm/engine/impl/util/json/package-tree.html
var JSONObject = Java.type('org.camunda.bpm.engine.impl.util.json.JSONObject')
var JSONArray = Java.type('org.camunda.bpm.engine.impl.util.json.JSONArray')
// Setup the Vertx Web Router
var Router = require("vertx-web-js/router")
// Create a Vertx HTTP Server and set the router for the server
var server = vertx.createHttpServer()
var router = Router.router(vertx)
// Setup a /my-deployments route:
router.route('/my-deployments').handler(function (routingContext) {
var response = routingContext.response();
response.putHeader("content-type", "application/json");
// Runs a Deployment Query in the repositoryService
var deploymentList = repositoryService.createDeploymentQuery().list()
// Uses the JSONArray json util to convert the list of deployments
// into a pretty string
var prettyDeploymentList = new JSONArray(deploymentList).toString(2)
// Returns the pretty string as the response for the route
response.end(prettyDeploymentList);
});
// Has the defined server use the defined router and listen on port 8081
server.requestHandler(router.accept).listen(8081);
// Returns a response such as:
/*
[{
"deployedArtifacts": null,
"deployedCaseDefinitions": null,
"deployedDecisionDefinitions": null,
"deployedDecisionRequirementsDefinitions": null,
"deployedProcessDefinitions": null,
"deploymentTime": "Tue Apr 03 16:45:51 EDT 2018",
"id": "ff48de6a-377f-11e8-95e6-60c547076970",
"name": "vertxCamundaApplication",
"new": false,
"persistentState": "class org.camunda.bpm.engine.impl.persistence.entity.DeploymentEntity",
"source": "process application",
"tenantId": null,
"validatingSchema": true
}]
*/
You can see we can directly tap into the active Camunda engine.
So a Endpoint for HTTP is generated: /my-deployments
on port 8081.
When this route is called we run the following:
var deploymentList = repositoryService.createDeploymentQuery().list()
var prettyDeploymentList = new JSONArray(deploymentList).toString(2)
So we can interact with the same Java API but do so with Javascript and Vertx to generate endpoints without the need to recompile the primary Jar.
Our response is:
[{
"deployedArtifacts": null,
"deployedCaseDefinitions": null,
"deployedDecisionDefinitions": null,
"deployedDecisionRequirementsDefinitions": null,
"deployedProcessDefinitions": null,
"deploymentTime": "Tue Apr 03 16:45:51 EDT 2018",
"id": "ff48de6a-377f-11e8-95e6-60c547076970",
"name": "vertxCamundaApplication",
"new": false,
"persistentState": "class org.camunda.bpm.engine.impl.persistence.entity.DeploymentEntity",
"source": "process application",
"tenantId": null,
"validatingSchema": true
}]
This opens up some interesting use cases for Shared Process Engines, where a Deployment to Camunda could also have deployments of “Verticles” which extend the API specifically for the use by specific Process Definitions.
Will be wrapping this up in a docker container example for testing and sharing shortly.
If you have interesting use cases, please share
Code for testing: