camunda-community-hub / micronaut-camunda-platform-7

Integration between Micronaut and Camunda (Workflow Engine). We configure Camunda with sensible defaults, so that you can get started with minimum configuration: simply add a dependency in your Micronaut project to embed the workflow engine!
https://camunda.com/blog/2021/07/automate-any-process-on-micronaut/
Apache License 2.0
75 stars 31 forks source link
bpm bpmn business-process camunda dmn hacktoberfest java kotlin micronaut process process-engine workflow workflow-engine

micronaut-camunda-platform-7

Release License Continuous Integration GitHub Discussions

Compatible with: Camunda Platform 7

This open source project allows you to easily integrate Camunda Platform 7 into Micronaut projects.

The Micronaut Framework is known for its efficient use of resources. With this integration you embed the BPMN 2.0 compliant and developer friendly Camunda process engine with minimal memory footprint into your application.

The integration is preconfigured with sensible defaults, so that you can get started with minimal configuration: simply add a dependency in your Micronaut project!

If you are interested in using Camunda's cloud native solution Zeebe on a Micronaut application instead, have a look at our open source project micronaut-zeebe-client.


We're not aware of all installations of our Open Source project. However, we love

📨 Please contact us!


Do you want to try it out? Please jump to the Getting Started section.

Do you want to contribute to our open source project? Please read the Contribution Guidelines and contact us.

If you also want to run your External Task Client on a Micronaut application, have a look at the open source project micronaut-camunda-external-client.

Micronaut Framework + Camunda = :heart:

Table of Contents

✨Features

🚀Getting Started

This section describes what needs to be done to use micronaut-camunda-bpm-feature in a Micronaut project.

Create Project with Micronaut Launch

Create a new Micronaut project using Micronaut Launch and check that the "camunda-platform7" feature is selected.

This will take care of the following:

All you need to do is save a process model in the resources, see the following section.

Deploying Models

BPMN process models (*.bpmn), DMN decision tables (*.dmn), and Camunda Forms (*.form) should be created with the Camunda Modeler and saved in the resources.

By default, only the root of the resources will be scanned, but with the property camunda.locations you can configure the locations.

When starting the application you'll see the log output: Deploying model: classpath:xxxxxxx.bpmn

If you deploy Camunda Forms then you can reference these from your user tasks by either

Camunda Integration

Process Engine and Services

Inject the process engine or any of the Camunda services using constructor injection:

import jakarta.inject.Singleton;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.RuntimeService;

@Singleton
public class MyComponent {

    private final ProcessEngine processEngine;
    private final RuntimeService runtimeService;

    public MyComponent(ProcessEngine processEngine, RuntimeService runtimeService) {
        this.processEngine = processEngine;
        this.runtimeService = runtimeService;
    }

    // ...
}

Alternatively to constructor injection, you can also use field injection, Java bean property injection, or method parameter injection.

You can then for example use the runtimeService to start new processes instances or correlate existing process instances.

Java Delegates

To invoke a Java delegate create a bean and reference it in your process model using an expression, e.g. ${loggerDelegate}:

import jakarta.inject.Singleton;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;

@Singleton
public class LoggerDelegate implements JavaDelegate {

    private static final Logger log = LoggerFactory.getLogger(LoggerDelegate.class);

    @Override
    public void execute(DelegateExecution delegateExecution) {
        log.info("Hello World: {}", delegateExecution);
    }
}

Internally, the bean will be resolved using io.micronaut.inject.qualifiers.Qualifiers.byName(...). Therefore, you can use the annotation jakarta.inject.Named to define an explicit bean name and use that name in your expression.

Configuration

Data Source

By default, an in-memory H2 data source is preconfigured. Remember to add the runtime dependency com.h2database:h2 mentioned in Dependency Management.

However, you can configure any other database supported by Camunda, e.g. in application.yml:

datasources:
  default:
    url: jdbc:postgresql://localhost:5432/postgres
    username: postgres
    password: secret
    driver-class-name: org.postgresql.Driver

after adding the appropriate driver as a dependency:

runtimeOnly("org.postgresql:postgresql:42.3.1")

Connection Pool with HikariCP

This integration uses HikariCP as a database connection pool to optimize performance. By default, the following configuration is applied:

Properties

You may use the following properties (typically in application.yml) to configure the Camunda integration.

Prefix Property Default Description
camunda .locations classpath:. List of locations to scan for model files (default is the resources's root only)
camunda.admin-user .id If present, a Camunda admin account will be created by this id (including admin group and authorizations)
.password Admin's password (mandatory if the id is present)
.firstname Admin's first name (optional, defaults to the capitalized id)
.lastname Admin's last name (optional, defaults to the capitalized id)
.email Admin's email address (optional, defaults to <id>@localhost)
camunda.rest .enabled false Enable the REST API
.context-path /engine-rest Context path for the REST API
.basic-auth-enabled false Enables basic authentication for the REST API
.authentication-provider org.camunda.bpm.engine. rest.security.auth.impl. HttpBasicAuthenticationProvider Authentication Provider to use for the REST API
camunda.webapps .enabled false Enable the Webapps (Cockpit, Task list, Admin)
.context-path /camunda Context path for the Webapps
.index-redirect-enabled true Registers a redirect from / to the Webapps
camunda.filter .create Name of a "show all" filter for the task list
camunda .license-file Provide a URL to a license file; if no URL is present it will check your classpath for a file called "camunda-license.txt"

Generic Properties

The process engine can be configured using generic properties listed in Camunda's Documentation: Configuration Properties.

The properties can be set in kebab case (lowercase and hyphen separated) or camel case (indicating the separation of words with a single capitalized letter as written in Camunda's documentation). Kebab case is preferred when setting properties.

Some of the most relevant properties are:

Example:

camunda:
  generic-properties:
    properties:
      history: audit

Examples

Here are some example applications:

Supported JDKs

We officially support the following JDKs:

🏆Advanced Topics

Dependency Management

The Camunda integration works with both Gradle and Maven, but we recommend using Gradle because it has better Micronaut Support.

If you create a new project then simply use the feature features=camunda-platform7 as described in Getting Started section. However, you can also manage the dependencies yourself as described here:

Click to show Gradle configuration Add the dependency to the build.gradle file: ```groovy implementation("info.novatec:micronaut-camunda-bpm-feature:2.18.1") runtimeOnly("com.h2database:h2") ```
Click to show Maven configuration Add the dependency to the pom.xml file: ```xml info.novatec micronaut-camunda-bpm-feature 2.18.1 com.h2database h2 runtime ```

Note: The module micronaut-camunda-bpm-feature includes the dependency org.camunda.bpm:camunda-engine which will be resolved transitively.

Camunda REST API and Webapps

Currently, the Camunda REST API and Webapps (Cockpit, Task list, and Admin) are only supported on the server runtime Jetty.

If you create your project with Micronaut Launch the jetty feature will be preselected for you.

However, if you have an existing project, you have to set the micronaut runtime of your project to jetty, e.g.

Click to show Gradle configuration micronaut-gradle-plugin configuration in build.gradle: ```groovy micronaut { runtime("jetty") [...] } ```
Click to show Maven configuration micronaut-maven-plugin configuration in pom.xml: ```xml [...] jetty ``` You have to remove this dependency in the pom.xml: ```xml io.micronaut micronaut-http-server-netty compile ``` and replace it with ```xml io.micronaut.servlet micronaut-http-server-jetty ```

Configuration of REST API and Webapps

By default, REST API and the Webapps are not enabled. You have to configure them e.g. in the application.yaml as follows:

camunda:
  webapps:
    enabled: true
  rest:
    enabled: true

Further Information:

Advanced Webapps Configuration

The security of the Webapps can be configured with the following properties:

Click to show configuration options. | Prefix | Property | Default | Description | |-----------------------|------------------|----------------------------------------------|------------------------| | camunda.webapps.header-security | .xss-protection-disabled | false | The header can be entirely disabled if set to true. | | | .xss-protection-option| BLOCK | The allowed set of values: BLOCK - If the browser detects a cross-site scripting attack, the page is blocked completely; SANITIZE - If the browser detects a cross-site scripting attack, the page is sanitized from suspicious parts (value 0). Note: Is ignored when xss-protection-disabled is set to true and cannot be set in conjunction with xss-protection-value | | | .xss-protection-value| 1; mode=block | A custom value for the header can be specified. Is ignored when xss-protection-disabled is set to true and cannot be set in conjunction with xss-protection-option. | | | .content-security-policy-disabled | false| The header can be entirely disabled if set to true. | | | .content-security-policy-value | base-uri 'self' | A custom value for the header can be specified. Note: Property is ignored when content-security-policy-disabled is set to true. | | | .content-type-options-disabled | false | The header can be entirely disabled if set to true. | | | .content-type-options-value | | A custom value for the header can be specified. Note: Property is ignored when content-security-policy-disabled is set to true. | | | .hsts-disabled | true | Set to false to enable the header. | | | .hsts-max-age | 31536000 | Amount of seconds, the browser should remember to access the webapp via HTTPS. Note: Is ignored when hstsDisabled is true, Cannot be set in conjunction with hstsValue, and allows a maximum value of 2^31-1. | | | .hsts-include-subdomains-disabled | true | HSTS is additionally to the domain of the webapp enabled for all its subdomains. Note: Is ignored when hstsDisabled is true and cannot be set in conjunction with hstsValue. | | | .hsts-value | max-age=31536000 | A custom value for the header can be specified. Note: Is ignored when hstsDisabled is true and cannot be set in conjunction with hstsMaxAge or hstsIncludeSubdomainsDisabled. | | camunda.webapps.csrf | .target-origin | | Sets the application expected deployment domain. | | | .deny-status | | Sets the HTTP response status code used for a denied request. | | | .random-class | | Sets the name of the class used to generate tokens. | | | .entry-points | | Sets additional URLs that will not be tested for the presence of a valid token. | | | .enable-secure-cookie | false | If true, the cookie flag Secure is enabled. | | | .enable-same-site-cookie | true | If set to false, the cookie flag SameSite is disabled. The default value of the cookie is LAX and it can be changed via same-site-cookie-option configuration property. | | | .same-site-cookie-option | | Can be configured either to STRICT or LAX. Note: Is ignored when enable-same-site-cookie is set to false and cannot be set in conjunction with same-site-cookie-value. | | | .same-site-cookie-value | | A custom value for the cookie property. Note: Is ignored when enable-same-site-cookie is set to false and cannot be set in conjunction with same-site-cookie-option. | | | .cookie-name | | A custom value to change the cookie name. Default ist 'XSRF-Token'. Note: Please make sure to additionally change the cookie name for each webapp (e.g. Cockpit) separately. |

Camunda Enterprise Edition (EE)

Add Maven Coordinates

To use the Camunda Enterprise Edition you have to add the Camunda Enterprise repository:

Click to show Gradle configuration In `build.gradle`: ```groovy repositories { maven { url "https://artifacts.camunda.com/artifactory/camunda-bpm-ee/" credentials(PasswordCredentials) { username "YOUR_USERNAME" password "YOUR_PASSWORD" } } } ```
Click to show Maven configuration In `pom.xml`: ```xml camunda-bpm-nexus-ee camunda-bpm-nexus https://artifacts.camunda.com/artifactory/camunda-bpm-ee/ ``` Furthermore, you have to add your credentials in `~/.m2/settings.xml`: ```xml camunda-bpm-nexus-ee YOUR_USERNAME YOUR_PASSWORD ```

Replace CE with EE Dependencies

Then remove the CE dependencies and replace them with the EE ones. Here are some example snippets on how to do that. Keep in mind using the correct version of the libraries.

Click to show Gradle configuration In `build.gradle`: ```groovy implementation("info.novatec:micronaut-camunda-bpm-feature:2.18.1") { exclude group: 'org.camunda.bpm.webapp', module: 'camunda-webapp-webjar' exclude group: 'org.camunda.bpm', module: 'camunda-engine' } implementation("org.camunda.bpm.webapp:camunda-webapp-webjar-ee:7.21.0-ee") implementation("org.camunda.bpm:camunda-engine:7.21.0-ee") ```
Click to show Maven configuration In `pom.xml`: ```xml info.novatec micronaut-camunda-bpm-feature 2.18.1 org.camunda.bpm.webapp camunda-webapp-webjar org.camunda.bpm camunda-engine org.camunda.bpm.webapp camunda-webapp-webjar-ee 7.21.0-ee org.camunda.bpm camunda-engine 7.21.0-ee ```

Configure your EE license

Camunda will use the license configured in the Cockpit.

If no license is registered, then the following locations will be checked during startup to register the license:

  1. The URL referenced by the property camunda.license-file
  2. The file camunda-license.txt in the resource's root if the property camunda.license-file has an empty value
  3. The path .camunda/license.txt in the user's home directory

If you want to update your license key, use the Camunda Cockpit.

Process Engine Plugins

Every bean that implements the interface org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin is automatically added to the process engine's configuration on start.

You can either

Example with the LDAP plugin:

implementation("org.camunda.bpm.identity:camunda-identity-ldap:7.21.0")
import io.micronaut.context.annotation.Factory;
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.camunda.bpm.identity.impl.ldap.plugin.LdapIdentityProviderPlugin;
import jakarta.inject.Singleton;

@Factory
public class PluginConfiguration {

    @Singleton
    public ProcessEnginePlugin ldap() {
        // Using a public online LDAP:
        // https://www.forumsys.com/tutorials/integration-how-to/ldap/online-ldap-test-server/
        LdapIdentityProviderPlugin ldap = new LdapIdentityProviderPlugin();
        ldap.setServerUrl("ldap://ldap.forumsys.com:389");
        ldap.setManagerDn("cn=read-only-admin,dc=example,dc=com");
        ldap.setManagerPassword("password");
        ldap.setBaseDn("dc=example,dc=com");
        return ldap;
    }
}

You can now log in with "einstein" / "password". Note: the automatic creation of the admin user with the property camunda.admin-user conflicts with a read-only LDAP and must not be set!

Custom Process Engine Configuration

With the following bean it's possible to customize the process engine configuration:

import info.novatec.micronaut.camunda.bpm.feature.MnProcessEngineConfiguration;
import info.novatec.micronaut.camunda.bpm.feature.ProcessEngineConfigurationCustomizer;
import io.micronaut.context.annotation.Replaces;
import jakarta.inject.Singleton;

@Singleton
@Replaces(ProcessEngineConfigurationCustomizer.class)
public class MyProcessEngineConfigurationCustomizer implements ProcessEngineConfigurationCustomizer {
    @Override
    public void customize(MnProcessEngineConfiguration processEngineConfiguration) {
        processEngineConfiguration.setProcessEngineName("CustomizedEngine");
    }
}

Custom Job Executor Configuration

With the following bean it's possible to customize the job executor:

import info.novatec.micronaut.camunda.bpm.feature.JobExecutorCustomizer;
import info.novatec.micronaut.camunda.bpm.feature.MnJobExecutor;
import io.micronaut.context.annotation.Replaces;
import jakarta.inject.Singleton;

@Singleton
@Replaces(JobExecutorCustomizer.class)
public class MyJobExecutorCustomizer implements JobExecutorCustomizer {
    @Override
    public void customize(MnJobExecutor jobExecutor) {
        jobExecutor.setWaitTimeInMillis(300);
    }
}

Transaction management

By default the process engine integrates with Micronaut's transaction manager and uses a Hikari connection pool:

Optionally, micronaut-data-jdbc or micronaut-data-jpa are supported.

Using micronaut-data-jdbc

To enable embedded transactions management support with micronaut-data-jdbc please add the following dependencies to your project:

Click to show Gradle dependencies ```groovy annotationProcessor("io.micronaut.data:micronaut-data-processor") implementation("io.micronaut.data:micronaut-data-jdbc") ```
Click to show Maven dependencies ```xml io.micronaut.data micronaut-data-jdbc ``` And also add the annotation processor to every (!) `annotationProcessorPaths` element: ```xml io.micronaut.data micronaut-data-processor ${micronaut.data.version} ```

and then configure the JDBC properties as described micronaut-sql documentation.

Using micronaut-data-jpa

To enable embedded transactions management support with micronaut-data-jpa please add the following dependencies to your project:

Click to show Gradle dependencies ```groovy annotationProcessor("io.micronaut.data:micronaut-data-processor") implementation("io.micronaut.data:micronaut-hibernate-jpa") ```
Click to show Maven dependencies ```xml io.micronaut.data micronaut-data-hibernate-jpa ``` And also add the annotation processor to every (!) `annotationProcessorPaths` element: ```xml io.micronaut.data micronaut-data-processor ${micronaut.data.version} ```

and then configure JPA as described in micronaut-sql documentation.

Performance

The Time to First Response (TTFR) is mainly influenced by the (slow) bootstrapping of the process engine - the bottleneck is the sequential parsing of over 50 MyBatis mappings. But the REST api and WebApps also take time.

This Micronaut Camunda Integration includes some optimizations that come into play especially in multi-core environments.

Some hints:

Most discussions regarding startup time discuss the relevance during deployment or scaling up applications.

However, there is more: for a developer startup times are also relevant when test suites are executed - either locally or in a CI environment. If the application context is created often (e.g. @MockBean dirties the context in Spring Boot...) then integration tests run quite long.

If unit and integration tests are more of a conceptional difference (and not so much regarding performance) then the developer has more freedom of choice to decide if a unit or integration test is more appropriate for his scenario.

The documentation of Micronaut Test actually says: "One of the design goals of Micronaut was to eliminate the artificial separation imposed by traditional frameworks between function and unit tests due to slow startup times and memory consumption."

Architectural Design

Separating Process Engine from Webapps/REST

If you want to activate the Webapps and/or REST it might be an option to do this in a separate application. Both are connected via a common database.

Possible aspects:

Embedding External Workers

If you're intending to use the External Task Pattern it might be an option embedding them (at first) in your main application - and having them to communicate via REST on localhost.

Possible aspects:

Here is an example application: https://github.com/tobiasschaefer/micronaut-embedded-worker

Keycloak

You can enable the Keycloak integration to

  1. Start Keycloak, e.g. docker run -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin -e DB_VENDOR="h2" quay.io/keycloak/keycloak:12.0.4
  2. Configure Keycloak and add a test user.
  3. Add the dependency implementation("org.camunda.bpm.extension:camunda-bpm-identity-keycloak:2.2.3") to your Micronaut project
  4. Add the plugin:
    @Singleton
    @ConfigurationProperties("plugin.identity.keycloak")
    public class KeyCloakPlugin extends KeycloakIdentityProviderPlugin {
    }
  5. Configure the application.yml
    plugin.identity.keycloak:
    keycloakIssuerUrl: http://localhost:8080/auth/realms/master
    keycloakAdminUrl: http://localhost:8080/auth/admin/realms/master
    clientId: camunda-identity-service
    clientSecret: 42aa42bb-1234-4242-a24a-42a2b420cde1 # you get this from keycloak
    useEmailAsCamundaUserId: true
    administratorGroupName: camunda-admin
  6. Start the application and log in with your created test user. Keep in mind that your user needs an e-mail address.

Eventing Bridge

The Eventing Bridge maps Camunda Events to Micronaut ApplicationEvents. It's possible to configure three different event streams:

Configuration of Eventing Bridge

camunda:
  eventing:
    task: true
    execution: true
    history: true

Event Listener Implementation

To consume Micronaut ApplicationEvents you can implement the interface ApplicationEventListener or use the @EventListener annotation.

Click to show example with ApplicationEventListener interface ```java public class SampleEventListener implements ApplicationEventListener { private static final Logger log = LoggerFactory.getLogger(SampleEventListener.class); @Override public void onApplicationEvent(TaskEvent event) { log.info("new TaskEvent: EventName={}, Assignee={}", event.getEventName(), event.getAssignee()); } } ```
Click to show example with @EventListener ```java @Singleton public class SampleEventListener { private static final Logger log = LoggerFactory.getLogger(SampleEventListener.class); @EventListener public void onExecutionEvent(ExecutionEvent event) { log.info("new ExecutionEvent: {}", event.getEventName()); } @EventListener public void onTaskEvent(TaskEvent event) { log.info("new TaskEvent: {}", event.getEventName()); } @EventListener public void onTaskEvent(HistoryEvent event) { log.info("new HistoryEvent: {}", event.getEventType()); } } ```

Process Tests

Process tests can easily be implemented with JUnit 5 by adding the camunda-bpm-assert library as a dependency:

Click to show Gradle dependencies ```groovy testImplementation("org.camunda.bpm:camunda-bpm-assert:7.21.0") testImplementation("org.assertj:assertj-core") ```
Click to show Maven dependencies ```xml org.camunda.bpm camunda-bpm-assert 7.21.0 test org.assertj assertj-core 3.21.0 test ```

and then implement the test using the usual @MicronautTest annotation:

import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import jakarta.inject.Inject;

import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.*;

@MicronautTest
class HelloWorldProcessTest {

    @Inject
    ProcessEngine processEngine;

    @Inject
    RuntimeService runtimeService;

    @BeforeEach
    void setUp() {
        init(processEngine);
    }

    @Test
    void happyPath() {
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("HelloWorld");
        assertThat(processInstance).isStarted();

        assertThat(processInstance).isWaitingAt("TimerEvent_Wait");
        execute(job());

        assertThat(processInstance).isEnded();
    }
}

See also a test in our example application: HelloWorldProcessTest

Docker

When using Gradle we recommend the Micronaut Application Plugin's dockerBuild task to create a layered Docker image.

Build the Docker image:

./gradlew dockerBuild

Run the Docker image:

docker run -p 8080:8080 <IMAGE>

Updating Camunda

Generally, follow Camunda's instructions regarding Update to the next Minor Version.

If you want to automate the database schema migration you can use Liquibase or Flyway together with the migration sql scripts provided by Camunda.

The following examples are based on Liquibase.

When starting on an empty database, e.g. when using H2 for tests:

<changeSet author="Tobias" id="1a" >
  <comment>Create common baseline Camunda 7.14 for H2 based on https://artifacts.camunda.com/artifactory/public/org/camunda/bpm/distro/camunda-sql-scripts/7.14.0/camunda-sql-scripts-7.14.0.zip in directory create</comment>
  <sqlFile path="camunda/h2_engine_7.14.0.sql" relativeToChangelogFile="true" dbms="h2" />
  <sqlFile path="camunda/h2_identity_7.14.0.sql" relativeToChangelogFile="true" dbms="h2" />
</changeSet>

If you already have a persistent database with the database schema of 7.14 which is not yet managed by Liquibase, e.g. PostgreSQL:

<changeSet author="Tobias" id="1b" >
  <comment>Create common baseline Camunda 7.14 for PostgreSQL (even if schema already exists) based on https://artifacts.camunda.com/artifactory/public/org/camunda/bpm/distro/camunda-sql-scripts/7.14.0/camunda-sql-scripts-7.14.0.zip in directory create</comment>
  <preConditions onFail="MARK_RAN">
    <not>
      <tableExists tableName="ACT_RU_JOB" />
    </not>
  </preConditions>
  <sqlFile path="camunda/postgres_engine_7.14.0.sql" relativeToChangelogFile="true" dbms="postgresql" />
  <sqlFile path="camunda/postgres_identity_7.14.0.sql" relativeToChangelogFile="true" dbms="postgresql" />
</changeSet>

When updating to a new Camunda version first apply all patch updates (if available) and then update to the next minor version:

<changeSet author="Tobias" id="2" >
  <comment>Update to Camunda 7.15 based on https://artifacts.camunda.com/artifactory/public/org/camunda/bpm/distro/camunda-sql-scripts/7.15.0/camunda-sql-scripts-7.15.0.zip in directory upgrade</comment>
  <!-- no patch files available for 7.14.x ... -->
  <sqlFile path="camunda/h2_engine_7.14_to_7.15.sql" relativeToChangelogFile="true" dbms="h2" />
  <sqlFile path="camunda/postgres_engine_7.14_to_7.15.sql" relativeToChangelogFile="true" dbms="postgresql" />
</changeSet>

Pitfalls

No version information in Fat/Uber/Shadow JAR

If you create a Fat/Uber/Shadow JAR and run that you will see a warning:

WARN i.n.m.c.b.f.MnProcessEngineConfiguration - The Camunda version cannot be determined. If you created a Fat/Uber/Shadow JAR then please consider using the Micronaut Application Plugin's 'dockerBuild' task to create a Docker image.

This is because the repackaging of the jars implicitly removes the META-INF information.

Without version information the EE license cannot be configured.

Instead, of creating a Fat/Uber/Shadow JAR, please see instructions on creating a Docker image and use the resulting image to run a Docker container.

Executing Blocking Operations on Netty's I/O Thread Pool

When using the default server implementation Netty, blocking operations must be performed on I/O instead of Netty threads to avoid possible deadlocks. Therefore, as soon as Camunda "borrows a client thread" you have to make sure that the event loop is not blocked. A frequently occurring example is the implementation of a REST endpoint which interacts with the process engine. By default, Micronaut would use a Netty thread for this blocking operation. To prevent the use of a Netty thread it is recommended to use the annotation @ExecuteOn(TaskExecutors.IO). This will make sure that an I/O thread is used.

@Post("/hello-world-process")
@ExecuteOn(TaskExecutors.IO)
public String startHelloWorldProcess() {
    return runtimeService.startProcessInstanceByKey("HelloWorld").getId();
}

Camunda Platform Assertions - Multiple process tests

If you create multiple process tests, you need to add the following initialisation code in each test:

@Inject
ProcessEngine processEngine;

@BeforeEach
void setUp() {
    init(processEngine);
}

This makes the assertions aware of your process engine. Otherwise, it tries to reuse the engine of the test that got executed first and that may already be shut down, see Camunda Platform 7's Assert User Guide.

Here is a complete example: HelloWorldProcessTest.

📚Releases

The list of releases contains a detailed changelog.

We use Semantic Versioning.

The following compatibility matrix shows the officially supported Micronaut and Camunda versions for each release. Other combinations might also work but have not been tested.

Release Micronaut Camunda
2.18.0 3.9.4 7.22.0
Click to see older releases | Release | Micronaut | Camunda | |--------|-----------|--------| | 2.17.0 | 3.9.4 | 7.21.0 | | 2.16.0 | 3.9.4 | 7.20.0 | | 2.15.0 | 3.9.4 | 7.19.0 | | 2.14.0 | 3.9.0 | 7.19.0 | | 2.13.0 | 3.8.9 | 7.19.0 | | 2.12.0 | 3.8.0 | 7.18.0 | | 2.11.1 | 3.7.3 | 7.18.0 | | 2.11.0 | 3.7.3 | 7.18.0 | | 2.10.0 | 3.7.1 | 7.18.0 | | 2.9.0 | 3.6.1 | 7.17.0 | | 2.8.0 | 3.5.2 | 7.17.0 | | 2.7.2 | 3.4.4 | 7.17.0 | | 2.7.1 | 3.4.4 | 7.17.0 | | 2.7.0 | 3.4.1 | 7.17.0 | | 2.6.0 | 3.4.0 | 7.16.0 | | 2.5.0 | 3.3.3 | 7.16.0 | | 2.4.1 | 3.3.3 | 7.16.0 | | 2.4.0 | 3.3.0 | 7.16.0 | | 2.3.2 | 3.2.0 | 7.16.0 | | 2.3.1 | 3.2.0 | 7.16.0 | | 2.3.0 | 3.2.0 | 7.16.0 | | 2.2.0 | 3.1.1 | 7.16.0 | | 2.1.0 | 3.1.0 | 7.16.0 | | 2.0.0 | 3.0.0 | 7.15.0 | | 1.1.0 | 2.5.12 | 7.15.0 | | 1.0.1 | 2.5.12 | 7.15.0 | | 1.0.0 | 2.5.9 | 7.15.0 | | 0.24.0 | 2.5.1 | 7.15.0 | | 0.23.0 | 2.4.3 | 7.15.0 | | 0.22.0 | 2.4.1 | 7.14.0 | | 0.21.0 | 2.4.1 | 7.14.0 | | 0.20.0 | 2.4.0 | 7.14.0 | | 0.19.0 | 2.3.4 | 7.14.0 | | 0.18.1 | 2.3.3 | 7.14.0 | | 0.18.0 | 2.3.2 | 7.14.0 | | 0.17.0 | 2.3.2 | 7.14.0 | | 0.16.1 | 2.3.1 | 7.14.0 | | 0.16.0 | 2.3.0 | 7.14.0 | | 0.15.0 | 2.3.0 | 7.14.0 | | 0.14.0 | 2.2.3 | 7.14.0 | | 0.13.0 | 2.2.2 | 7.14.0 | | 0.12.0 | 2.2.1 | 7.14.0 | | 0.11.0 | 2.2.1 | 7.14.0 | | 0.10.1 | 2.2.0 | 7.14.0 | | 0.10.0 | 2.2.0 | 7.14.0 | | 0.9.0 | 2.1.3 | 7.14.0 | | 0.8.0 | 2.1.2 | 7.13.0 | | 0.7.0 | 2.1.1 | 7.13.0 | | 0.6.0 | 2.1.0 | 7.13.0 | | 0.5.3 | 2.0.1 | 7.13.0 | | 0.5.2 | 2.0.0 | 7.13.0 | | 0.5.1 | 2.0.0 | 7.13.0 | | 0.5.0 | 2.0.0 | 7.13.0 | | 0.4.2 | 1.3.6 | 7.13.0 | | 0.3.1 | 1.3.5 | 7.12.0 | | 0.2.2 | 1.3.3 | 7.12.0 | | 0.2.1 | 1.3.3 | 7.12.0 | | 0.2.0 | 1.3.3 | 7.12.0 | | 0.1.0 | 1.3.3 | 7.12.0 |

Download of Releases:

📆Publications

📨Contact

If you have any questions or ideas feel free to create an issue or contact us via GitHub Discussions.

We love listening to your feedback, and of course also discussing the project roadmap and possible use cases with you!

This open source project is being developed by envite consulting GmbH and Novatec Consulting GmbH with the support of the open source community.


envite consulting GmbH envite consulting GmbH

Novatec Consulting GmbH