Write your Spring Boot (3.x) starter with Kotlin & Maven

Write your Spring Boot (3.x) starter with Kotlin & Maven

January 23, 2023

Some companies use Camunda(TM) BPMN Engine for managing the business automatization process. Most of the functionality provided out of the box is enough for most cases. But recently I have realized that we have always written our service to send messages to the engine. So, I decided to write my starter. The native language for Camunda is Java, but it supports many other languages. Since I want programming experience in Java, I have decided to write my starter with Kotlin. For those who are already tired — the full code is available on the GitHub There are no breaking backward capability changes in writing spring boot starters.

Changes:

Now auto configurations load from another file placed at resources/META-INF/spring/packageName.className.imports. Don’t worry old way of spring.factories work too I decided to use Maven as a build tool, so it is my pom.xml file

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.vrnsky</groupId>
    <artifactId>camunda-messaging-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>camunda-messaging-starter</name>
    <description>Message Camunda without overhead</description>

    <properties>
        <java.version>17</java.version>
        <kotlin.version>1.7.22</kotlin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>3.0.2</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.0.2</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
            <version>1.8.0</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>1.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-lombok</artifactId>
            <version>${kotlin.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.19.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.2.1</version>
            </plugin>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>1.7.22</version>
                <configuration>
                    <sourceDirs>
                        <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
                    </sourceDirs>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                    </args>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <annotationProcessorPaths>
                        <annotationProcessorPath>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.24</version>
                        </annotationProcessorPath>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

We use some dependency as spring-boot-web-starter because we need RestTemplate class for HTTP calls. There are dependencies for Kotlin and Logging. For building projects, I use the following command

mvn clean kotlin:compile install

So, let’s start with defining model classes of objects which start will be working with. Before we start writing code — I strongly advise checking the actual documentation of Camunda messaging.

enum class VariableType {
    Json, String
}

So we can have two types of variables — json and string types

data class ProcessVariable(
    val value: String,
    val type: VariableType
) {}

This class describes process variables — which widely used in Camunda

data class CamundaMessage(
    val businessKey: String,
    val messageName: String,
    val correlationKeys: Map<String, VariableType>,
    val processVariables: Map<String, VariableType>
) {
}

Access full article