This bm-sim repository is a Maven Multiple Module project. The Maven Reactor mechanism makes sure to collect all modules and assert correct build order with every mvn command executed. It assures that any project is build as required by another.

We use the Maven multi-module project approach for managing distributed applications where different components need to be developed, versioned, and deployed independently while maintaining coherent dependencies centralized. This simplifies and standardizes a consistent build process and scaling with a clear separation of concerns.

This is a Java project and the development cycle is defined by the major components:

Maven build tool

Implies major versioning, dependency management, plugin configuration, build lifecycle and finally release management. If available and feasible external tools, i.e. plugins, like the OpenAPI Generator are integrated into the lifecycle to generate code for subsequent modules.

Camel Integration Framework

Apache Camel has a very powerful bean injection framework to allow developers to focus on solving business problems. At its core, Apache Camel is an integration engine, which can be used to facilitate interactions between a wide and varied array of technologies. These bridges between service- and technology Endpoints, the Routes are implemented on an engine - the CamelContext, and they communicate with Exchange Messages.

In this repository Camel is used to glue independantly developed Units together.

Camel & Spring

Camel allows you to define your data flow as a declarative route for complex integration and routing work, and then handing off the final business logic to standard Spring components like Controllers or Services. While Spring Boot handles the lifecycle and dependency injection in the Spring context, dependency injection, and application startup.

Note
Spring Boot will auto-configure Camel for you.

check out camel-spring-boot

Spring Boot component provides auto-configuration for Apache Camel. Our opinionated auto-configuration of the Camel context auto-detects Camel routes available in the Spring context and registers the key Camel utilities (like producer and consumer templates, type converters etc.) as @Bean.

Multi Module projects structure

A Maven Multiple Module Project supports project aggregation in addition to project inheritance. The mechanism in Maven that handles multi-module projects is referred to as the Reactor.

The Reactor or root pom ..

  • Collects all the available modules to build

  • Sorts the projects into the correct build order

  • Builds the selected projects in order

  • Should contain: <modules> section listing all submodules (bm-parent, bm-traccar, etc.).

  • Should NOT contain dependencies or build plugins that are meant to be inherited by modules.

  • Basic project metadata (groupId, artifactId, version, packaging=pom).

  • Common properties (if needed).

  • Plugin management (optional, but usually placed in parent).

and simply is a POM that refers to other Maven projects.

Note the output line at the beginning of every Maven Build

[INFO] Reactor Build Order:

The Parent pom defines common <dependencies> and <plugins> (and <pluginManagement>) inherited by all submodules and does not create a JAR or a WAR.

The bm-parent/pom.xml ..

  • Serves as the parent for all submodules (bm-traccar, etc.).

  • Should contain: <dependencyManagement> for shared dependency versions.
    <build> section for shared plugins (like asciidoctor-maven-plugin, compiler plugin, surefire, etc.).

  • Should NOT contain <modules> (that’s for the aggregator/root pom).

  • Shared properties (Java version, encoding, etc.).

For a quick overview on the complete project you can always run mvn clean to see the processing order.

root project bm-sim

The Maven Bill of Materials (BOM) is collected the root pom.xml file, i.e. aggregator POM that defines common dependencies, versions, properties and other dependent Maven Projects. It is considered good development practice to run mvn clean install in the repository root directory in order to create all artifacts in the local .m2/repository. This substitutes a Nexus Server usually providing released artifacts. After that the developer can exclusively focus on the project s/he is assigned to.

For team development you should work with the -SNAPSHOT tag and a central (Nexus) Server over your personal .m2 repo. This way all team members are accessing the same (continuously changeing) artifact and the complete build process can be reduced to the module and artifact in focus.

<modules>

This approach reduces duplication and allows to share configurations between modules. Practically the parent pom can be seen as the cover sheet with project information and most important - the list of submodules.

compare to JeeTS repository

    <modules>
        <module>bm-parent</module>
        <module>bm-tracker</module>
        <module>bm-traccar</module>
                ...
    </modules

bm-parent project

The parent project is the first module called in the build process.
It starts by running the os-maven-plugin (actually a Maven <extension>)

    [INFO] Scanning for projects...
    [INFO] ---------------------------------------------------
    [INFO] Detecting the operating system and CPU architecture
    [INFO] ---------------------------------------------------
    [INFO] os.detected.name: linux
    [INFO] os.detected.arch: x86_64
    [INFO] os.detected.bitness: 64
    [INFO] os.detected.version: 6.11
    [INFO] os.detected.version.major: 6
    [INFO] os.detected.version.minor: 11
    [INFO] os.detected.release: tuxedo
    [INFO] os.detected.release.version: 22.04
    [INFO] os.detected.release.like.tuxedo: true
    [INFO] os.detected.release.like.ubuntu: true
    [INFO] os.detected.release.like.debian: true
    [INFO] os.detected.classifier: linux-x86_64

which provides Maven parameters, like ${os.detected.name},
to direct the build lifecycle as required for your targeted system.

And it helps to detect and identify problems in different environments.
For exmple the build on github actions is running on ubuntu-latest and
the build on the local machine (above) is running on ubuntu 22.04.
If you look at the build on github actions you can locate differences in the build-and-release workflow

  [INFO] os.detected.version: 6.14
  [INFO] os.detected.release: ubuntu
  [INFO] os.detected.release.version: 24.04
Caution

These subtle differences can raise subtle problems!

project setup

<properties>

The properties of the parent project are applied to the full repo. Here the main parameters for Java, JDK, Maven with components and plugins, the driving Camel version in conjunction with spring boot.

<dependencyMgm> and top level BOM

The repository versioning of Java archives is defined by

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.camel.springboot</groupId>
            <artifactId>camel-spring-boot-bom</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
        </dependency>
    </dependencies>
</dependencyManagement>

It is recommended to import Camel Spring Boot BOM before Spring Boot BOM to ensure Camel dependencies are using supported JARs from the release.

compare to JeeTS repository

   <groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-dependencies</artifactId>

Dotfiles

Dotfiles are text-based configuration files (e.g. .gitignore) for Unix-like systems,
named after the "." prefix that hides them.

Important

Make sure you have set your file browser tool to show hidden files.

Dotfiles are also part of this repository to serve various purposes.

.github/workflows/

This directory contains the YAML files for GitHub Actions, which automate workflows for the repository.

TODO: java-version: '21' is currently hardcoded in both files

build.yml

This workflow is triggered on every push or pull request to the main branches.
Its primary role is to build the project and run tests to ensure code quality and integration.

release.yml

This workflow automates the release process. It is triggered when a new version tag (e.g., v1.0.0) is pushed. The workflow builds the project, creates a new GitHub release, and attaches the generated JAR files as release assets.

.mvn/wrapper/

maven-wrapper.properties

todo (locate existing descriptions)

.gitignore

todo (locate existing descriptions)

Maven <plugins>

Each section provides a short introduction to each tool with links to lookup and learn more details.

Asciidoctor

The complete project is documented in AsciiDoc or .adoc files. This is the broader approach to technical documents than markdown and you can find everything in the AsciiDoc Language Documentation:

AsciiDoc is a lightweight and semantic markup language primarily designed for writing technical documentation. The language can be used to produce a variety of presentation-rich output formats, such as HTML, PDF, EPUB3, man(ual) page, or DocBook. This capability enables it to be used in static site generators, IDEs, git tools and services, CI/CD systems, and other software.

— see https://docs.asciidoctor.org/asciidoc/latest

It is important to understand that .adoc files are source files that should be processed to some target format. This processor is called the Asciidoctor and described in the AsciiDoctor Documentation:

Asciidoctor is a fast text processor for parsing AsciiDoc into a document model, then converting it to output formats.

— see https://docs.asciidoctor.org/asciidoctor/latest

Mermaid Chart

Mermaid lets you create diagrams and visualizations using text and code.

— see https://docs.mermaidchart.com/mermaid-oss/intro/index.html#about-mermaid

that’s about all there is to say about this software.

Find more at github

The idea is to describe charts with the mermaid syntax

    flowchart TD
            A(["Start"])
            A --> B{"Decision"}
            B --> C["Option A"]
            B --> D["Option B"]

and our Maven Plugin combination of AsciiDoc and Mermaid will generate html pages with SVG graphics on the fly:

Diagram

There is also a live editor for interactive chart creation.

The Maven Installation is part of the Maven AsciiDoc installation and details can be found in its description AsciiDoctor implementation and usage.

openapi-generator-maven

The complete Traccar REST API is defined in a single openapi.yaml file This file is used with the OpenAPI Generator to generate a plain Java Client. The generation is controlled and configured via openapi-generator-maven-plugin and produces a traccar-api-generated-x.y.z.jar (in two steps).

Google Code Style

There are many code formatters and formats out there. Just like in the jeets project we chose the fmt-maven-plugin

   <groupId>com.coveo</groupId>
<artifactId>fmt-maven-plugin</artifactId>

The choice is based on simplicity and the most common code style with Google Java Style.
The plugin is strict about styling, cannot be configured by design and automatically formats the code before compilation.

Testing with Traccar Server

The Traccar Clients are basically an interface between REST and Java passing Entities. Therefor there is no need for cumbersom JUnit test setups or mocking to test the technology we rely on. The functionality is achieved by wiring diffent technology components together, configure and run them.

The Traccar Client is not a software with complex implementations of Java Units. Actually it is merely an interface between REST and Java passing Entities. The functionality is achieved by wiring diffent technology components together, configure and run them.

For example the Camel RestOpenApiComponent is already being tested with each Camel build. These tests should not be repeated. see RestOpenApiComponent JUnit tests

surefire vs failsafe testing with docker

The aim of this project is to remote control a Traccar Server by reacting to live information.
So we can take a broader approach to testing by setting up a Traccar Server for tests. This makes the actual build of the Traccar Client software faster. We use the Maven lifecycle to start a traccar docker container and apply failsafe to make sure the container is stoped after testing:

[INFO] --- docker-maven-plugin:0.46.0:stop (stop) @ traccar-api-client ---
[INFO] DOCKER> [traccar/traccar:6.7.1-ubuntu] "traccar":
                Stop and removed container 7ef24f3a8f58 after 0 ms

To speed up test development the traccar container can be started via command line and the Integration Tests (*IT) can be run as JUnit Tests against a running server. This is a one liner inside the bm-traccar branch

~/git/bm/bm-traccar$ mvn docker:run
[INFO] --- docker-maven-plugin:0.46.0:run (default-cli) @ bm-traccar ---
[INFO] DOCKER> [traccar/traccar:6.10.0-ubuntu] "traccar": Start container 6083b17b2da9
[INFO] DOCKER> [traccar/traccar:6.10.0-ubuntu] "traccar": Waiting on url http://localhost with method HEAD for status 200..399.
[INFO] DOCKER> [traccar/traccar:6.10.0-ubuntu] "traccar": Waited  on url http://localhost 4954 ms

The developer can login to the Traccar Frontend to inspect test results and more.

The botton line is that emphasis is placed on integration testing using Maven’s Failsafe plugin in combination with Docker.

docker-maven

Requirements to docker are dead simple: We need a traccar container out of the box, configure it to our needs, introspect the logs at runtime and finally using the traccar UI to visualize what’s going on!

Since the project does not dockerize anything, the plugin should not be to fancy about docker, kubernetes, cloud etc. After setting up the project once, the focus is on using Spring Test framework and Camel’s testing utilities to mvn verify integration logic and not unit-level.

There is no need to integrate Docker into the source code with Docker :: Apache Camel or the like, since this is not a docker project.

The choice is fabric8’s docker-maven-plugin

This is a Maven plugin for managing Docker images and containers.
It focuses on two major aspects for a Docker build integration:
Building Images and Running Containers.

— fabric8io/docker-maven-plugin

maven-failsafe

specifically for integration testing, focusing on lifecycle and reporting for integration tests.

Run Docker containers during the integration test phase to manage container lifecycle.

Failsafe and Docker Integration: Combining Failsafe plugin with Docker management to execute tests within a Dockerized environment and ensure proper test lifecycle.

-> Usage in multi-module projects
  <pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
-> Reporting integration test results   LATER
  <reporting>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-report-plugin</artifactId>

flatten-maven

Maven maintenance

upgrades and updates

The following steps cover the vital coordinates.

step 1 - Maven versions

Upgrade maven versions with

mvn versions:display-plugin-updates

until you get

[INFO] --- versions-maven-plugin:2.17.1:display-plugin-updates (default-cli) @ bm-sim ---
[INFO]
[INFO] All plugins with a version specified are using the latest versions.
[INFO] All plugins have a version specified.
[INFO]
[INFO] Project requires minimum Maven version for build of: 3.8.8
[INFO] Plugins require  minimum Maven version of: 3.8.8
[INFO]
[INFO] No plugins require a newer version of Maven than specified by the pom.

And you are also informed to upgrade the major Maven version

[INFO] Require Maven 4.0.0-beta-3 to use the following plugin updates:
[INFO]   maven-source-plugin ......................... 3.4.0 -> 4.0.0-beta-1

In this case we are not upgrading to Maven 4 yet, since it is still in beta phase: 4.0.0-beta-1

  • ❏ Update the maven wrapper as described below

  • ❏ Update the maven-minimum-version in bm/pom.xml

step 2 - Camel and Spring versions

The above maven command does not check the BOM versions of the two frameworks. Therefor they are incremented one by one until the repository is completly build with mvn install.

      <camel-version>4.18.0</camel-version>
<spring-boot-version>4.0.4</spring-boot-version>

SpringBoot was upgraded from 3 to 4 in v1.1.17. We usually stick to the LTS versions provided.

step 3 - Java and JDK version

Upgrading Java can be fine for the repository. Nevertheless we would like to keep a compromise between highest available and lowest backward compatibility for users of the released jar files.

<jdk.version>21</jdk.version>

step 4 - Traccar version

pull and run new container

Updating the Docker Traccar version is as simple as incrementing to the desired version.
Just change the traccar.version in the bm-parent/pom.xml

<traccar.version>6.12.2</traccar.version>

and run

~/git/bm/bm-parent$ ../mvnw docker:run

and see how the new container is pulled and started

[INFO] --- docker-maven-plugin:0.48.1:run (default-cli) @ bm-parent ---
[INFO] DOCKER> Pulling from traccar/traccar
01d7766a2e4a: Pull complete
e152e288890f: Pull complete
88ba7e9ad9ed: Pull complete
4f4fb700ef54: Pull complete
[INFO] DOCKER> Digest: sha256:cfd9859e85480b75c30f7d2f31a6e45c429322f6e8d04084b2e60d52b390a3eb
[INFO] DOCKER> Status: Downloaded newer image for traccar/traccar:6.12.2-ubuntu
[INFO] DOCKER> Pulled traccar/traccar:6.12.2-ubuntu in 19 seconds
[INFO] DOCKER> [traccar/traccar:6.12.2-ubuntu] "traccar": Start container c779cda54c47
[INFO] DOCKER> [traccar/traccar:6.12.2-ubuntu] "traccar": Waiting on url http://localhost with method HEAD for status 200..399.
[INFO] DOCKER> [traccar/traccar:6.12.2-ubuntu] "traccar": Waited on url http://localhost 5172 ms

All relevant external sources are specified in the docker-maven-plugin.

generate Traccar API

After changing the traccar.version the traccar-openapitools-client needs to be run in order to create a new traccar-api-generated. No changes in the project are required and therfor you can simply start a complete repository install and it should run past the API generation.

fix traccar-api-client

After traccar-openapitools-client the traccar-api-client compilation will probably fail and you have to delve into this project.

It is vital to understand that the traccar-api-client is the fundament for all client implementations. Therefor this layer should be held as constant as possible in order to avoid massive code changes all over the repository!

todo

Version number bumps

The bulk of the OpenAPI additions landed around early 2026 (leading into v6.12 series), including the geofence report, health check, and orders support.

push project

  1. check pom structure and build order (mvn clean)

  2. update bm.adoc and releases.adoc versioning

  3. generate documentation

  4. set skips before releasing

generate documentation

Start kroki-mermaid:

$ docker run -d --name kroki-mermaid --memory=1g --shm-size=1g
             -p 8002:8002 yuzutech/kroki-mermaid

turn ON asciidoc for doc generation:

<asciidoc.process.skip>false</asciidoc.process.skip>

If you want you can delete all html, svg and svg.cache files, but after the first generation you should leave then in your local repo to save build time.

Now you can run

./mvnw generate-resources

to create all html files and mermaid svg files. And you can interactively edit the adoc texts and look at the html files with diagrams. Be sure to check documentation errors and fix and check mermaid diagrams visually.

To run mermaid and asciidoc in a subproject

/gps-osmand-tracker$ ../../mvnw generate-resources

with generate-html-docs in the output

[INFO] --- asciidoctor-maven-plugin:3.2.0:process-asciidoc (generate-html-docs)
           @ gps-osmand-tracker ---
[INFO] Converted /gps-osmand-tracker/src/asciidoc/OsmAndProtocolSpecification.adoc
[INFO] Converted /gps-osmand-tracker/src/asciidoc/gps-osmand-tracker.adoc
[INFO] Converted /gps-osmand-tracker/src/asciidoc/gps-tracker-arc.adoc
[INFO] Converted /gps-osmand-tracker/src/asciidoc/gps-tracker-impl.adoc
[INFO] Converted /gps-osmand-tracker/src/asciidoc/gps-tracker-simu.adoc
[INFO] Converted /gps-osmand-tracker/src/asciidoc/gps-tracker.adoc
[INFO] Converted /gps-osmand-tracker/src/asciidoc/mermaid-test.adoc
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

After everything is in place and files are generated you should turn OFF asciidoc for doc generation:

<asciidoc.process.skip>true</asciidoc.process.skip>

Don’t forget to stop the kroki server to save valuable memory and to commit the generated files!

nice2have:
start docker if skip>false

skip Docker Integration Tests for light version

The Docker Integration Tests are invaluable for development. They should only be committed, if they run with a green bar. On the other hand Maven can simply build the code with Unit Tests for a quick start to get into the project. The generated jars can be used - individually in other projects.

Therefor every vx.y.z release in the public repo is set to a light version focussed on building without contributing:

/bm-sim/bm-parent/pom.xml
                <docker.skip.tests>true</docker.skip.tests>
           <integration.tests.skip>true</integration.tests.skip>

maven reactor

If you want to delve into a multi module project you should initially build the complete repo on your machine. Then you will have all artifacts in your .m2 repo and can focus on coding inside a single project domain. The Reactor will pull the required jars for this project.

During development you don’t want to bother building the repo from scratch for every code change.
For example you might create a test-jar which can be used with classifier 'tests' in anthor project. Then this test-jar must be published to local repo to be used elsewhere in the repo.

For example we can produce a test-jar in the gps-osmand-tracker build to provide a TrackerRegistration in higher level tests. Then you can add the test-jar to the test section with with classifier 'tests' to pick up the package.

From the repository root /bm, either:

  • Build the tracker module first to produce the test-jar, then run traccar tests:

    mvn -pl bm-tracker/gps-osmand-tracker package -DskipTests
    mvn -pl bm-traccar/0traccar-realtime-client test
  • Or run the traccar-realtime-client tests in reactor so required modules (including test-jar) are built automatically:

    mvn -pl bm-traccar/traccar-realtime-client -am test
                                               ==== --also-make switch
Note

In earlier releases (before v1.1.16 we had to use the above practice to switch the natural order of repo branches to /tracker before /traccar. This development order was used to provide a GTS, before developing GPS Trackers.

On a short term we wan’t to avoid hooks inside the repo to keep it simple alap

maven wrapper

To make sure that the complete project is build with a specified Maven Version it is possible to add a Maven Wrapper with a determined version.

Simply run this from the root directory

~/git/bm$ mvn wrapper:wrapper -Dmaven=3.8.8

to get

bm/
├── .mvn/
│   └── wrapper/
│       ├── maven-wrapper.jar
│       └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml (Root POM)
├── bm-parent/
│   └── pom.xml
└── etc.

Now we can build the complete multimodule project from the root with

/git/bm$ ./mvnw clean install

And you can build any subproject from the root with

/git/bm$ ./mvnw clean install -pl bm-tracker    -am
/git/bm$ ./mvnw clean install -pl bm:bm-tracker -am

Or, better, if you are working inside a subproject like the gps-osmand-tracker

~/git/bm/bm-tracker/gps-osmand-tracker$ ../../mvnw clean install

Note that you reference the mvnw in the root by going up two folders with ../../
depending on where you are working from the command line.

Since this setup is generally idempotent the wrapper can be upgraded anytime with

~/git/bm$ mvn wrapper:wrapper -Dmaven=3.9.2

Then the next build will pick up the required files.

useful mvn commands

analyse dependencies

Maven also provides

dependency:analyze

plugin goal for analyzing the dependencies: it helps making this best practice more achievable.

Sources and Javadocs

Most Maven plugins have a help goal that prints a description of the plugin and its parameters and types.
For instance, to see help for the javadoc goal, type:

mvn javadoc:help -Ddetail -Dgoal=javadoc

To build jar files with the source code you can run this command from the root folder or from any subfolder for single project sources.

mvn source:jar install

You can check your local repo to verify that the -sources.jar,
i.e. jeets-protocols-traccar-4.2.1-beta-sources.jar has been installed.

Creating -javadoc.jars works the same way by entering:

mvn javadoc:jar install

to create jeets-pu-traccar-4.2-javadoc.jar for every project.

mvn dependency:resolve -Dclassifier=javadoc
mvn dependency:resolve -Dclassifier=sources