MAPS (Multi Adapter and Protocol Standards) Messaging Server — a Java 21 IoT messaging
server supporting 20+ wire protocols (MQTT 3/5, MQTT-SN, AMQP, STOMP, CoAP, NATS, LoRa,
WebSocket, etc.). Plugin architecture via Java ServiceLoader (SPI). Main entry point:
io.mapsmessaging.MessageDaemon.
Maven project. Java 21 source/target. UTF-8 encoding.
# Full build (skip tests)
mvn clean package -DskipTests
# Full build with tests
mvn clean verify
# Run all tests
mvn test
# Run a single test class
mvn test -Dtest=RetainManagerTest
# Run a single test method
mvn test -Dtest=RetainManagerTest#current_onNewInstance_returnsMinusOne
# Run tests matching a pattern
mvn test -Dtest="io.mapsmessaging.engine.**"
# Build and deploy (used by CI)
mvn -DskipTests=true clean deploy -U
# OWASP dependency vulnerability check
mvn dependency-check:check
# Config lint (runs during verify phase)
mvn verifyTest patterns recognized by Surefire: **/*Test.java, **/*Tests.java, **/*IT.java.
Surefire argLine sets SSL keystores and MAPS_HOME=${project.build.directory} automatically.
- Framework: JUnit Jupiter (JUnit 5), Mockito 5, REST Assured 5
- Base classes:
BaseTest— logging/timing hooks for all testsBaseTestConfig extends BaseTest— starts fullMessageDaemon; has@Timeout(240000)ApiTestBase extends BaseTestConfig— REST API tests with OpenAPI validation
- Test naming: snake_case descriptive names preferred (e.g.,
current_onNewInstance_returnsMinusOne), camelCase also used - Assertions: Use
org.junit.jupiter.api.Assertions(assertEquals, assertThrows, etc.) - Test class visibility: Package-private (no
publicmodifier) is the norm - Cleanup:
try-finallyfor resource cleanup in tests;BaseTestConfighandles session/destination cleanup in@AfterEach
- 2-space indentation (spaces, not tabs)
- K&R brace style — opening brace on same line
- No formal formatter config (no Checkstyle/Prettier/EditorConfig)
- SonarCloud used for code quality analysis
- Order: project (
io.mapsmessaging.*) → third-party → Lombok → Java stdlib - Wildcard imports are used for
java.util.*,java.io.*,java.nio.* - Explicit imports for third-party and project classes
- Packages: lowercase dot-separated (
io.mapsmessaging.engine.destination) - Classes: PascalCase (
RetainManager,MessageDaemon) - Methods/fields: camelCase (
getInstance(),currentId) - Constants: UPPER_SNAKE_CASE (
HEADER_SIZE) - Test methods: snake_case descriptive (
replace_withValidIds_setsAndOverwritesRetainId)
- Lombok: Used extensively —
@Getter,@Setter,@NoArgsConstructor,@NonNull - JetBrains annotations:
@NotNull,@Nullablealongside Lombok@NonNull - SonarQube suppressions:
@SuppressWarnings("java:S106")with Sonar rule IDs
try-finallyfor resource cleanup (not try-with-resources in all cases)Thread.currentThread().interrupt()when catchingInterruptedException- Custom enum-based logging:
logger.log(ServerLogMessages.MESSAGE_DAEMON_STARTUP) - No string concatenation in log calls
- Custom framework:
io.mapsmessaging.logging.Logger/LoggerFactory - Log messages are enum constants (
ServerLogMessages,LogMessages) - Logback as the underlying implementation
- Singletons: Static
getInstance()(e.g.,MessageDaemonConfig.getInstance()) - ServiceLoader (SPI): Plugin discovery for protocols, transformations, analyzers
(see
META-INF/services/) - CompletableFuture: Heavily used for async operations in the API layer
- Editor fold markers:
//<editor-fold desc="...">to organize code sections - Configuration: YAML-based, loaded via
ConfigurationManager, mapped to DTO/Config classes
Every Java file must start with:
/*
*
* Copyright [ 2020 - 2024 ] Matthew Buckton
* Copyright [ 2024 - 2026 ] MapsMessaging B.V.
*
* Licensed under the Apache License, Version 2.0 with the Commons Clause
* ...
*/src/main/java/io/mapsmessaging/
MessageDaemon.java # Main entry point
api/ # Public API (Session, Destination, Message, Schema)
config/ # Configuration DTOs and managers
engine/ # Core messaging engine (destinations, sessions, subscriptions)
network/protocol/impl/ # Protocol implementations (mqtt/, amqp/, stomp/, coap/, etc.)
rest/ # REST API (Jersey/Grizzly)
auth/ # Authentication/authorization
dto/ # Data Transfer Objects
logging/ # Custom enum-based logging
src/test/java/io/mapsmessaging/
BaseTest.java # Base test class
test/BaseTestConfig.java # Server-bootstrapping base (starts MessageDaemon)
src/main/resources/ # YAML configs (MessageDaemon.yaml, NetworkManager.yaml, etc.)
Conventional Commits enforced. Format: type(scope): subject
- Types: feat, fix, refactor, perf, test, build, ci, docs, style, chore, revert
- Scopes: server, ml, engine, config, schema, protocol, network, rest, buildkite, docs
- Header: ≤100 chars, imperative mood, lowercase type/scope, no trailing period
- Footer:
JIRA: MAPS-###orNO-ISSUE; optionalBREAKING CHANGE:,DEPRECATED:,SECURITY: - Branch naming:
MAPS-###-short-desc
Example:
feat(protocol): add MQTT 5 bridge support
Implements protocol translation between MQTT 3.1.1 and 5.0.
JIRA: MAPS-123
- Buildkite is the primary CI (
.buildkite/server_pipeline.yml) - GitHub Actions for Dependabot auto-merge only
- SonarCloud integration for code quality (org:
maps-messaging) - JaCoCo for code coverage
- OWASP dependency-check for vulnerability scanning (fails on CVSS ≥ 10)
Lombok, Logback, SnakeYAML, Jackson, Jersey 4 + Grizzly, Swagger/OpenAPI, Apache Qpid Proton-J (AMQP), Eclipse Paho (MQTT), Californium (CoAP), Auth0 JWT, AWS SDK (Cognito), Pi4J (hardware), MapDB, Quartz Scheduler, JMH (benchmarks).
- The
mlMaven profile addssrc/main/java-mlandsrc/test/java-mlsource dirs - The
nativeMaven profile builds a GraalVM native image - SSL keystores (
my-keystore.jks,my-truststore.jks) are in the project root and required for tests — do not delete them - Test timeout is 4 minutes (
@Timeout(240000)) on integration tests viaBaseTestConfig - Many tests start the full
MessageDaemon— they are slow; prefer unit tests when possible