The bm-traccar module, i.e. Maven subbranch, is the development environment for integrating with the Traccar GPS Tracking Platform. Traccar is a GPS Tracking System (GTS) written in Java and published as Open Source Software. The System was thoroughly analyzed in the JeeTS Project and JeeTS Book.

This module provides a development environment with different database setups, different server instances: remote, local IDE, local service or dockerized for automated integration testing

Diagram

bm-traccar Architecture

1. Overview

The bm-traccar module is a multi-project Maven build that provides client implementations for interacting with a Traccar server, supporting both REST and real-time (WebSocket) communication.
The architecture is modular, separating OpenAPI-generated, API interface and real-time logic.

2. Project Structure

The parent project bm-traccar aggregates three submodules:

  • traccar-openapitools-client: OpenAPI-based client code for Traccar REST APIs.

  • traccar-api-client: Custom API client logic for RESTful communication.

  • traccar-rt-client: Real-time and WebSocket-based processing, including session management and event routing.

3. Component Interaction

This diagram shows the runtime flow from REST API calls to real-time event processing and WebSocket communication.

Diagram

For simplification the traccar-openapitools-client is not shown. It is shown in the lower level diagram traccar-api-client Component Interaction.

When the client Application starts the RealTimeController which populates the RealTimeManager scenario via REST API calls to the Traccar Server. After this initialization the RealTimeController is automatically and continuously updated via TraccarWebSocketRoute.

Now the client Application can access the DTOs of the RealTimeController and can get notified about every server event.

In conclusion the client Application is only running against the local RealTimeController, which is automatically kept up to date with the Server Status. This is a clear separation of the application from client-server communication.

4. bm-traccar Package Architecture

bm.traccar @SpringbootApplication will scan all subpackages, i.e. the other Maven Projects in the bm-traccar branch.

packages

    bm.traccar
    bm.traccar.rt
    bm.traccar.ws
    bm.traccar.api
    bm.traccar.generated...

Dockerized Traccar Server

The Traccar Client Software is developed with Integration Tests against a Docker Traccar Server.

5. build and run Traccar Docker Container

The traccar project at Github provides instructions to fetch and install the Traccar DockerHub image. This Maven Module leverages the fabric8io docker-maven-plugin to control the Docker container phases to manage a dockerized Traccar server for integration testing.

To avoid the sudo command you can create a docker group to enable non-root user access:

    sudo groupadd -f docker
    sudo usermod -aG docker $USER
    newgrp docker
    groups

6. docker-maven-plugin

You can compare the parameters of the docker-maven-plugin with the four point checklist at Container create example and adopt them to your requirements and system.

6.1. <build>

In the plugin <configuration> of the <image> and <build> section you can find the traccar version and target OS. Please note that this repository was set up with Dockerfile.ubuntu.

    <traccar.version>6.8.0</traccar.version>
    <docker.image.version>${traccar.version}</docker.image.version>
    <docker.image.os>ubuntu</docker.image.os>

You might want to swap with Dockerfile.alpine or Dockerfile.debian for your purposes.

    <artifactId>docker-maven-plugin</artifactId>
     ...
    <image>
        <alias>traccar</alias>
        <name>traccar/traccar:${traccar.version}-${docker.image.os}</name>

creates an image traccar/traccar:6.8.0-ubuntu just like the command line

$ docker pull traccar/traccar:6.8.0-ubuntu

Note that we distinguish project- and ${traccar.version} in order patch versions, when required.

6.1.1. <dockerFile>

The Dockerfile is not part of this project and is directly referenced with its ${traccar.version} from the sources at github

    <dockerFile>Dockerfile.${docker.image.os}</dockerFile>
    <contextDir>https://github.com/traccar/traccar/blob/v${traccar.version}/docker</contextDir>

The docker file …​

  • defines os version image, ie ubuntu:24:04

  • grabs the traccar release from github and unzips

  • provides entry point, ie java cmdline

  • expects a WORKDIR /opt/traccar on your machine!
    which we will provide next.

7. docker:run

Now we are almost ready create a container from the image and run it.
Back to the traccar instructions we are asked to create workdirectories and chmod as you like.

7.1. create work directories

… and set permissions according to your policies.

sudo mkdir -p /opt/traccar/
sudo chmod 777 traccar

7.2. cat default traccar.xml

cat the traccar.xml file to your local file system.
Make sure you pick the correct name, version and flavor for traccar/traccar:6.6-ubuntu .
This time we are directly applying the docker run command without mvn !

$ docker run --rm --entrypoint cat traccar/traccar:x.y.z-ubuntu \
   /opt/traccar/conf/traccar.xml > /opt/traccar/traccar.xml

Now you should find the traccar.xml file as specified. As an experienced traccar admin you can now configure traccar according to your production server. Keep in mind that this project does not require Tracker information nor opening the ports as described in <port> below.

The focus of this project is on interacting with the Traccar API in the Traccar container.

7.3. create container

The last step creating the traccar container on the traccar Github page is to run direcly with docker docker run. We do not want to run docker via command line, we want to start and stop the container for integration testing. So we will use mvn docker:run to make sure everything is in place.

7.4. <run>

Next you should check the parameters of the <run> section for your personal preferences

        <run>
            <hostname>traccar</hostname>
            <ports>
                <port>80:8082</port>
            </ports>
            <volumes>
                <bind>
                    <volume>/opt/traccar/logs:/opt/traccar/logs:rw</volume>
                    <volume>/opt/traccar/traccar.xml:/opt/traccar/conf/traccar.xml:ro</volume>
                    <volume>/opt/traccar/data:/opt/traccar/data:rw</volume>
                </bind>
            </volumes>
            <log><!-- do not remove --></log>
            <wait>
                <http>
                    <url>http://localhost</url>
                </http>
            </wait>
        </run>

7.4.1. <port>

Set the external port to 80 simplify the http url of the traccar UI to http://localhost.

Please note that this project is for OpenAPI development and the access is restricted to the port (default 80) of the UI.
The Tracker Protocol TCP and UDP Ports

--publish 5000-5150:5000-5150 \
--publish 5000-5150:5000-5150/udp \

are not required nor configured for API testing in this project.

In order to test your Traccar Server in Docker with an Android or iPhone Traccar Client you can open the relevant port with

<ports>
    <port>80:8082</port>
    <port>5055:5055</port>
</ports>

7.4.2. <wait>

Wait for availabity of the container, before running tests.

Once the container has started you can also access the traccar UI in you local browser with http://localhost .

7.4.3. <volumes>

The volumes define the mapped traccar folders on your local system.

  1. we want to tail the logfile to see what’s going on on server side.

  2. we want to configure the traccar.xml analog to the production server.

  3. we want to see what’s going on in the database.

These volumes represent the standard installation of traccar and <traccar/data> was added for development support.

7.4.4. <traccar/data>

In the <volumes> section above you will find an additional volume

<volume>/opt/traccar/data:/opt/traccar/data:rw</volume>

This way developers can always peak into traccar’s data model.
Different options to work with the Database are explained here

Also note the Database heading at the bottom of

https://hub.docker.com/r/traccar/traccar

The default when executing the above docker run command is an internal H2 database. The docker run command also doesn’t create a mount point on the host for the data folder which will cause the database to be lost when the container is recreated. This point can be mitigated by adding the line

-v /var/docker/traccar/data:/opt/traccar/data:rw \

7.4.5. <log>

Note that the empty

`<log><!-- do not remove --></log>`

section is required as described in 5.2.10. Logging:

Logging is enabled by default if a <log> section is given!

This way you can always keep a console or editor open to auto reload, i.e. tail the tracker-server.log file.

7.5. mvn docker:run

Now we can execute: mvn docker:run and container start, wait, stop and remove should look something like this:

~/git/bm/bm-traccar/traccar-api-camel$ mvn docker:run
                                       ==============
[INFO] --- docker-maven-plugin:0.46.0:run (default-cli) @ traccar-api-camel ---
[INFO] DOCKER> Pulling from traccar/traccar
 b08e2ff4391e: Pull complete
 0b823ac9e80a: Pull complete
 66fe9131b572: Pull complete
 4f4fb700ef54: Pull complete
[INFO] DOCKER> Digest: sha256:5bd7e3a8d059b1ca0e86004f747f6bebe9206f5b2da61b380f70c2a6285e59f5
[INFO] DOCKER> Status: Downloaded newer image for traccar/traccar:6.8.0-ubuntu
[INFO] DOCKER> Pulled traccar/traccar:6.8.0-ubuntu in 49 seconds
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar": Start container 7ad9a7c7a649
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar":
               Waiting on url http://localhost with method HEAD for status 200..399.
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar": Waited on url http://localhost 5900 ms

Looks good: Container started and waited five seconds for the localhost. We have manually started mvn docker:run, now we can manually stop the container with the familiar key combination <Ctrl><c> :

^C
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar":
               Stop and removed container 7ad9a7c7a649 after 0 ms

Now you can check your local system with docker command:

~/git/bm/bm-traccar/traccar-api-camel$ docker images -a
                                       ================
REPOSITORY        TAG            IMAGE ID       CREATED       SIZE
traccar/traccar   6.8.0-ubuntu   5fdf770fa10b   6 weeks ago   298MB

8. validate development environment

Let’s check, if everything is in place.

8.1. Traccar Frontend

If you run mvn docker:run again (and over and over) the docker pull should not show as long as the docker image is on your machine. After waiting for startup (5.69 seconds in this case) …

[INFO] --- docker-maven-plugin:0.46.0:run (default-cli) @ traccar-api-camel ---
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar": Start container 6b39263a1f9c
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar":
               Waiting on url http://localhost with method HEAD for status 200..399.
[INFO] DOCKER> [traccar/traccar:6.8.0-ubuntu] "traccar": Waited on url http://localhost 5690 ms

… you can open the url in your browser.

At the development time you can open a console, execute mvn docker:run and leave it open. This way you can execute Integration Tests (*IT) as Unit Tests against the Traccar Server in your IDE! As good practice each test should clean up the server for subsequent tests in random order.

As an example you can debug a JUnit Test in your IDE, set a debug point after creating a new user and then log as this user in on the Frontend. Then continue the test to clean up.

Much more complex scenarios can be observed step by step in details.

8.2. tracker-server.log

In your local folder you should find the logfile

/opt/traccar/logs/tracker-server.log

There you should see the server start and the database setup by liquibase.

INFO: Operating system name: Linux version: 6.11.0-109019-tuxedo architecture: amd64
INFO: Java runtime name: OpenJDK 64-Bit Server VM vendor: Ubuntu version: 17.0.14+7-Ubuntu-124.04
INFO: Memory limit heap: 1024mb non-heap: 0mb
INFO: Character encoding: US-ASCII
INFO: Version: 6.6
INFO: Starting server...
INFO: HikariPool-1 - Starting...

INFO: Set default schema name to PUBLIC
INFO: Creating database history table with name: PUBLIC.DATABASECHANGELOG

INFO: Table tc_attributes created

INFO: Foreign key constraint added to tc_device_command (deviceid)

INFO: New row inserted into tc_servers
INFO: ChangeSet changelog-4.0-clean::changelog-4.0-clean::author ran successfully in 214ms

INFO: Index user_device_user_id created

INFO: Column tc_orders.toAddress renamed to toaddresstmp

INFO: UPDATE SUMMARY
INFO: Run:                         50
INFO: Previously run:               0
INFO: Filtered out:                 0
INFO: -------------------------------
INFO: Total change sets:           50

INFO: Update summary generated

INFO: Started Server@c18dcc4{STARTING}[11.0.24,sto=0] @4926ms

INFO: Stopping server...

INFO: Version: 6.6
INFO: Starting server...

INFO: UPDATE SUMMARY
INFO: Run:                          0
INFO: Previously run:              50
INFO: Filtered out:                 0
INFO: -------------------------------
INFO: Total change sets:           50

Note that the second start is faster, since the database is already there - which is exactely what we wanted.

8.2.1. debugging

We are creating traccar client software without modifying the traccar server. We are starting the traccar server docker image out of the box to develop against it (and save a lot of mocking etc.).

One way to check the server is the tracker-server.log. As one example you can debug one of the bm.traccar.api.*IT integration tests. Most of them extend BaseIntegrationTest which uses the preconfigured system administrator to log in.

In the log you can see the system user id 9000000000000000000 creating users with ids 1 and 2

INFO: user: 9000000000000000000, action: create, object: user, id: 1
INFO: user: 9000000000000000000, action: create, object: user, id: 2
INFO: user: 2, action: login,  from: 172.17.0.1
INFO: user: 2, action: logout, from: 172.17.0.1
INFO: user: 1, action: login,  from: 172.17.0.1
INFO: user: 1, action: logout, from: 172.17.0.1
INFO: user: 1, action: login, from: [0:0:0:0:0:0:0:1]    frontend
INFO: user: 1, action: login, from: 127.0.0.1            JUnit !?

8.3. call the API

You can call the Rest APIs such as

curl http://0.0.0.0:8080/api/v3/pet/123

Which returns information about a pet.

You can also update an existing PET such:

curl -XPUT -H "Content-Type: application/json" --data "@daisy.json" http://0.0.0.0:8080/api/v3/pet

8.4. login into fresh traccar server

http://localhost/?token=VIRTUAL_ADMIN_ACCESS
http://localhost/settings/user/9000000000000000000

8.5. grab JSESSIONID

wscat -c ws://localhost:80/api/socket -H "Cookie: JSESSIONID=node014ro3l06ueuxuvmvrcbykfbqp12.node0"
Connected (press CTRL+C to quit)
< {"positions":[]}
< {}
Disconnected (code: 1006, reason: "")   // trigger: docker:run > CTRL+C

8.6. enter browser request

http://localhost/api/devices?id=1461
http://localhost/api/devices/1461

Database Testing

After setting up the Traccar Docker Container there are different options to set up the database according to your development focus. The Database (ERM) can be perceived as the backdoor through which you can peek into the data and analyze the actions of your integration tests.

Multiple options for handling the H2 database are scribbled here, including mounting external volumes, direct SQL shell access. Kind of a cheat sheet outlining different database introspection approaches for development and testing.

9. database introspection

The recommended traccar docker installation is to leave the database inside the container.

Yet by mounting the /data folder we can look inside the data, which stays persistent after the container has stopped - at development time. You can find the data mount line in the docker-maven-plugin and un/comment as required:

<volumes>
    <bind>
        <volume>/opt/traccar/data:/opt/traccar/data:rw</volume>

The H2 database is locked as long the traccar container is working for its simplicity.
Developers can debug *IT tests running against the traccar container
and exit the test after a scenario has been setup.
Then the docker container must be stopped in order to use the h2 shell.

10. h2.tools.Shell

You can always inspect h2 through its console, as a back door directly the database model. The default h2 database is ideal, i.e. made for testing. Developers can login to the traccar data base, explore the schema and inspect data with plain SQL, reset to scratch .. whatever is feasible for you.

You will find the database in your filesystem in /opt/traccar/data as specified above. The following command line assumes to be in this folder.

Then you need to install the h2 lib and point to the jar

/opt/traccar/data$ java -cp /opt/h2/bin/h2-2.3.232.jar org.h2.tools.Shell
                        -url jdbc:h2:./database
                        -user sa

and you should get a welcome

Welcome to H2 Shell 2.3.232 (2024-08-11)
Exit with Ctrl+C

and start querying

sql> select id, name, email, hashedpassword, salt from tc_users;
ID | NAME    | EMAIL  | HASHEDPASSWORD                                   | SALT
1  | admin   | admin  | 44e0c0902fd515f49884c4fd9b78cbabfc7237586a7bc921 | a9d60a6a1734e06c5d76294404e536e8713369d877423d8e
2  | newUser | email  | null                                             | null
7  | user2   | email2 | 53e175f9ded19f065d7e483f44f540f7f8ca9c4026dd69dd | 72e2e2555df4a62c2d8ccb8fb295f7d19dc9373cfdf51772

11. h2.tools.RunScript

java -cp /path/to/h2/jar/h2-version.jar org.h2.tools.RunScript
     -url jdbc:h2:db/server/url
     -user sa -password password
     -script script.sql
     -showResults

12. h2.tools.Console

You can run a console, which opens a database frontend in your browser

java -cp /opt/traccar.bak/h2/bin/h2-2.3.232.jar org.h2.tools.Console
     -web
     -tcp
     -url jdbc:h2:./database
     -user sa

13. database available / locked

docker:run
$ java -cp /opt/traccar/h2/bin/h2-2.3.232.jar org.h2.tools.Shell
       -url jdbc:h2:/opt/traccar/data/database
       -user sa
Exception in thread "main" org.h2.jdbc.JdbcSQLNonTransientConnectionException:
  Database may be already in use: "/opt/traccar/data/database.mv.db".
  Possible solutions: close all other connection(s); use the server mode [90020-232]
Caused by: org.h2.mvstore.MVStoreException:
  The file is locked: /opt/traccar/data/database.mv.db [2.3.232/7]
stop container
sql> delete from tc_users where id=2;
Error: org.h2.jdbc.JdbcSQLNonTransientException:
The database is read only; SQL statement: delete from tc_users [90097-232]
-> change access to database* files
$ sudo chmod 777 database*
=> works :)

14. hashing the password

    # generate a random salt
    salt="$(dd if=/dev/urandom bs=24 count=1 status=none | xxd -p)"

    # generate the password hash from the contents of the "password" variable
    (which you've to set yourself to the new cleartext password)
    hash="$(openssl-3.0.1 kdf -keylen 24 -binary -kdfopt digest:sha1
          -kdfopt "pass:$password" -kdfopt "hexsalt:$salt" -kdfopt iter:1000 pbkdf2 | xxd -p)"

    # uncomment the following line to print out both the salt and the password hash
    #echo -e "salt: $salt\nhash: $hash"

    # set the value of "tchome" to the path of the Traccar directory
    tchome="/opt/traccar"

    # and finally update the password (and salt) of the default "admin" user
    java -cp "$tchome/lib/h2-"*".jar" org.h2.tools.Shell
         -url "jdbc:h2:$tchome/data/database"
         -user sa
         -sql "update tc_users set hashedpassword='$hash', salt='$salt'
               where email = 'admin';"

15. sql with Maven

https://github.com/kbeigl/jeets/blob/master/jeets-models/pom.xml
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>${h2database-version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.dbunit</groupId>
    <artifactId>dbunit</artifactId>
    <version>${dbunit-version}</version>
    <scope>test</scope>
</dependency>

setup development environment

The traccar-api-client defines an interface between a Java Client and a Traccar Server REST API. In order to test the remote invocation, development requires a running traccar server. This is acquired by using a traccar docker container managed in the Maven lifecycle. The only system requirement to the environment is a docker command line and adequat permissions.

credentials

The integration tests are only required for development.
The traccar-api-client can be build without executing tests.

If you want to develop additional functionality the integration tests can be run against any traccar server. If you set your server host, port and credentials in the application.properties file

    traccar.host=http[s]://traccar-host:port
    traccar.user.name=admin
    traccar.user.password=admin

Option 2 is to apply the web.serviceAccountToken by restarting the Traccar Service.

16. surefire vs failsafe

You can 'turn off' the docker management in the project by removing the executions of the pre- and post-integration phases:

    <executions>
        ...
        <phase>pre-integration-test</phase>
        ...
        <phase>post-integration-test</phase>

Then you can simply start the traccar server from the project folder

/bm/bm-traccar/traccar-api-client$ mvn docker:run

[INFO] --- docker-maven-plugin:0.46.0:run (default-cli) @ traccar-api-client ---
[INFO] DOCKER> [traccar/traccar:6.6-ubuntu] "traccar": Start container 839381eec187
[INFO] DOCKER> [traccar/traccar:6.6-ubuntu] "traccar":
               Waiting on url http://localhost with method HEAD for status 200..399.
[INFO] DOCKER> [traccar/traccar:6.6-ubuntu] "traccar":
               Waited on url http://localhost 5183 ms

With the server running you can switch the testing modes in /bm-sim/bm-traccar/pom.xml

    <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
            <includes>
                <include>**/*IT.java</include>
            </includes>
        </configuration>

    <artifactId>maven-failsafe-plugin</artifactId>
        <configuration>
            <excludes>
                <exclude>**/*IT.java</exclude>
            </excludes>
        </configuration>

and then you can simply run the IntegrationTests in JUnit during development time.

The developer should be aware of the Traccar Frontend on localhost (see below).
Very helpful to compare changes before/after testing.

Don’t forget the good old uncheckout of these temporary developer changes after development,
i.e. set the repo back to production.

17. browser UI

Now there is one last thing to do, before running the ITests: We need to create the admin user for traccar. Traccar used to be shipped with an admin/admin user, but not anymore:
First registered user automatically becomes an admin !!

It’s a little tricky to automate the insertion of the admin user. We have to run the container once to create the data model, before we could insert the user …​ TODO

Anyhow you should check the prop file

/bm-sim/bm-traccar/traccar-api-client/src/main/resources/application.properties

for the configured credentials

    traccar.host=http://localhost
    traccar.user.name=admin
    traccar.user.password=admin
  • Execute mvn docker:run again.

  • check log tail

    INFO: Started Server@649534a4{STARTING}[11.0.24,sto=0] @4954ms
  • open http://localhost in your browser
    since there is no user configured it yould jump to http://localhost/register
    enter admin for name, password and email (works without valid email syntax)
    login with the new credentials

done

18. run integration tests

Now the repository is setup for development and you can use the familiar Maven commands

  • mvn clean to make sure there are no conflicts

  • mvn verify to make run the integration tests

  • mvn install to build, run integration tests and install the jar.

Hopefully with

[INFO] BUILD SUCCESS