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.
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.
Goto projects AsciiDoctor implementation and usage
Mermaid Chart
Mermaid lets you create diagrams and visualizations using text and code.
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:
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.
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.
https://maven.apache.org/surefire/maven-failsafe-plugin/
https://maven.apache.org/surefire/maven-failsafe-plugin/usage.html
-> 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-versioninbm/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!
goto
traccar-api-client
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
-
check pom structure and build order (
mvn clean) -
update
bm.adocandreleases.adocversioning -
generate documentation
-
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 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