SmallMind is a comprehensive multi-module Java framework for building enterprise applications. It provides a curated set of integrations, abstractions, and utilities designed to work together coherently across the full stack of a modern Java application — from persistence and messaging to scheduling, web services, and observability.
The project targets Java 25 and is built with Maven. It integrates with widely-adopted libraries and platforms including Spring, Hibernate, Jakarta EE, Jetty, Netty, Kafka, RabbitMQ, MongoDB, and AWS, providing a consistent programming model across all of them.
Licensed under the GNU Affero General Public License v3 and GNU Lesser General Public License v3.
The following documentation covers each functional area of the framework:
-
Ansible — Configuration and provisioning integration
-
Artifact — Artifact management and packaging utilities
-
Batch — Batch processing support built on Spring Batch
-
Bayeux — CometD/Bayeux protocol support for server-sent events and WebSocket messaging
-
Claxon — Alerting and notification infrastructure
-
Doppelganger — Object cloning and transformation utilities
-
File — File handling and storage abstractions
-
JavaFX — JavaFX controls, dialogs, a parabox layout bridge, and live metric charts
-
Kafka — Apache Kafka producer and consumer integration
-
Liquibase — Database schema migration support via Liquibase
-
Memcached — Memcached client integration and caching abstractions
-
MongoDB — MongoDB driver integration and document mapping
-
NutsNBolts — Core utilities, foundations, and shared infrastructure
-
Persistence — JPA/Hibernate persistence layer with QueryDSL support
-
Phalanx — Distributed coordination and cluster management
-
Quorum — Consensus and distributed locking primitives
-
Schedule — Job scheduling via Quartz
-
Scribe — Logging infrastructure built on SLF4J and Log4j 2
-
Sleuth — Distributed tracing and observability
-
Spark — Self-executing jar packaging (Singularity) and OS service distributions (Tanukisoft)
-
Testbench — Internal test harness: Dockerized service fixtures, preconditions, and build-file tooling used to test SmallMind itself
-
Web — Web layer support including REST (Jersey), Jetty, and WebSocket
Every SmallMind jar declares a stable Java module name. The name is org.smallmind.
followed by the artifact’s directory path in this repository, and it does not change when
the jar file is renamed. A modular consumer refers to an artifact by this name, for example
requires org.smallmind.nutsnbolts;.
The Kind column says how the name is declared. An explicit jar ships a module
descriptor (module-info.class) that lists its exported packages, the modules it requires,
and the packages it opens to reflection; see Module Path And Classpath for what that means for a
consumer. An automatic jar carries the name only in its Automatic-Module-Name manifest
entry and is an automatic module on the module path. Explicit jars keep the manifest entry
as well. On the classpath neither form has any effect.
| Artifact | Module name | Kind | Chapter |
|---|---|---|---|
|
|
explicit |
|
|
|
automatic |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
automatic |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
automatic |
|
|
|
explicit |
|
|
|
automatic |
|
|
|
automatic |
|
|
|
automatic |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
automatic |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
|
|
|
explicit |
† Maven plugins and the Surefire provider carry a name so the jar is identifiable, but Maven
and Surefire load them through their own class realms. These names are not intended for a
consumer’s requires.
They stay automatic permanently.
The classpath is the configuration SmallMind tests against: every module’s test suite runs with its jars on the classpath, where module descriptors are ignored and nothing in this section applies. The rules below apply when an application puts SmallMind jars on the module path. Each chapter’s installation section lists the module-specific details: which optional dependencies its descriptor names, which modules it re-exports, and which of your packages you must open to it.
- All or nothing
-
A named module cannot read the classpath. If a SmallMind jar is on the module path, the third-party jars it uses (Spring, the Jakarta APIs, and so on) must be on the module path too. Jars without a descriptor become automatic modules there.
- Optional dependencies are
requires static -
Every dependency a SmallMind POM marks
<optional>true</optional>appears in the descriptor asrequires static. Such a module is needed at compile time but is not resolved at run time just because a SmallMind module names it. If its jar is on the module path and nothing in the application requires it, the module is not in the module graph, and the SmallMind code that uses it fails on first use withNoClassDefFoundError, even though the jar is present. Eitherrequiresthe module in your own descriptor, which is the normal case because you are using that library directly, or add it with--add-modules. Resolving any automatic module resolves every automatic module on the module path, so in practice this failure hits explicit modules (the Jakarta APIs, Bouncy Castle, ASM, and the like) far more often than automatic ones (Spring, FreeMarker, Shiro, AspectJ). - Re-exported and non-re-exported modules
-
A SmallMind descriptor uses
requires transitivefor a mandatory explicit module whose types appear in its public signatures, so your module reads that module without naming it. Optional modules are never re-exported, becausejavacwould then demand them when compiling every consumer, and automatic modules are never re-exported, because their names are not guaranteed stable. When a SmallMind signature exposes a type from either kind, require that module yourself. - Reflection
-
SmallMind descriptors open their own packages to the frameworks that reflect into them, such as Spring and JAXB. Packages that carry resources loaded by path, such as the Spring XML files documented as
classpath:org/smallmind/…, are opened unconditionally so those paths keep working. When a SmallMind utility reflects over your classes, you open your package to the SmallMind module named in that chapter. - Services
-
Service implementations are declared both with
providesin the descriptor and in aMETA-INF/servicesfile. The module path reads only the first; the classpath reads only the second.