A lightweight Java component model and runtime container.
Home | Previous: Covalent Public API | Next: Covalent Managed Components Guide
Covalent uses a Maven multi-module build:
covalent-core: component model and runtime container core, with no
third-party runtime dependency;covalent-hmi: JavaFX HMI runtime integration (HmiCore, ActionManager);covalent-supervision: JavaFX supervision and diagnostics tooling;covalent-tests: unit and non-regression tests;covalent-examples: runnable examples and demos.Build the repository, run every test and check the Javadoc with the Maven Wrapper, on Windows:
.\mvnw clean verify
or on Linux and macOS:
./mvnw clean verify
The core’s tests live in covalent-tests. Build and test the core alone, without
the JavaFX modules, with:
.\mvnw -pl covalent-tests -am clean verify
Enable optional runtime extensions, such as the component viewer, with:
-Dcovalent.extensions=component-viewer
See Extensions for the full mechanism, and the Covalent Supervision Guide for what the component viewer itself provides and how to summon it on a running application.
Covalent relies heavily on runtime reflection and dynamic proxies to implement dependency injection, service/events/parameters ports, and lifecycle management. This section documents the runtime environment this relies on, and the constructor contract implied by it, so that constraints are known up front rather than discovered through a runtime failure.
Covalent targets Java 21 (maven.compiler.release in the root pom.xml) and
is built and tested against that version. No code intentionally depends on
Java-21-only APIs beyond ordinary reflection, so more recent JDK versions are
expected to keep working, but only Java 21 is verified.
No module in the Maven reactor (covalent-core, covalent-hmi,
covalent-supervision, covalent-tests, covalent-examples) declares a module-info.java.
Covalent runs entirely on the classpath, in the unnamed module. This means:
@Implementation classes in packages that are not opensed
(unconditionally, or at least to Covalent), Covalent’s reflective
instantiation and field injection will fail at runtime with an
InaccessibleObjectException-based failure, because deep reflective access
across named module boundaries requires an explicit opens on the
declaring side;Covalent has not been built, tested, or otherwise validated under GraalVM
native-image. Native-image’s closed-world static analysis cannot discover, by
itself, the framework’s dynamic proxy creation, private/final field
injection, or caller-stack inspection. Using Covalent under native-image would
require the consuming application to supply its own reflection configuration
(covering every @Implementation class Covalent instantiates or injects
into) and dynamic-proxy configuration (covering every service, parameters,
and events interface exposed through a Covalent proxy). The project does not
provide or maintain such a configuration.
Covalent does not install, require, or test against a SecurityManager. The
SecurityManager API has been deprecated for removal since Java 17 (JEP
411), and this project does not rely on it. For completeness: Covalent’s
reflective operations call setAccessible(true) on constructors, methods,
and fields it needs to reach, which under an active SecurityManager would
require ReflectPermission("suppressAccessChecks") (and, for proxies,
ReflectPermission("newProxyInPackage.*") in some configurations). Running
under a restrictive SecurityManager policy has never been exercised and is
not a supported configuration.
Covalent’s internal Reflection.instantiateWithDefaultConstructor method is
what the container uses to instantiate @Implementation classes (among other
reflectively-created instances). It enforces a specific contract:
Class.getConstructor(), which only finds public members, not
getDeclaredConstructor() – a package-private, protected, or private
no-arg constructor is not found, and instantiation fails;ReflectionException.Concretely: declare every @Implementation class, and its no-argument
constructor, as public. This is not enforced at compile time; violating it
surfaces as a runtime ReflectionException at container startup.
Home | Previous: Covalent Public API | Next: Covalent Managed Components Guide