ModuleContext
ModuleContext is the single object every lifecycle hook receives.
It exposes the module’s identity, the capabilities it declared as
required, persistent storage handles, and the cross-cutting
primitives shared with the plugin SDK (events, logger, scheduler,
HTTP, JSON).
What you’ll learn
- Every method on
ModuleContext, grouped by purpose. - Which methods are safe to call inside which lifecycle hook.
- How
host()lets a dual-host module branch behaviour.
API surface
The interface lives at
me.prexorjustin.prexorcloud.api.module.platform.ModuleContext. It is
implemented by the controller (ControllerModuleContext) and each
daemon (DaemonModuleContext).
Module identity
PlatformModuleManifest manifest();Path jarPath();String previousVersion(); // empty on fresh installboolean isUpgrade(); // convenience: !previousVersion().isBlank()ModuleHost host(); // CONTROLLER or DAEMONisUpgrade() is the canonical guard for migration logic in
onUpgrade. host() lets a class shared between controller- and
daemon-side branch on which JVM it’s running in.
Capabilities
<T> Optional<T> findCapability(String capabilityId, Class<T> type);<T> T requireCapability(String capabilityId, Class<T> type);Look up capabilities declared as requires in the manifest.
findCapability returns empty if the capability is unbound (provider
absent or not yet activated); requireCapability throws — use it only
for capabilities the module cannot meaningfully run without.
See Capability API for the provides side.
Persistent storage
Optional<ModuleDataStore> findMongoStorage();ModuleDataStore requireMongoStorage();Optional<PlatformRedisStorage> findRedisStorage();PlatformRedisStorage requireRedisStorage();findMongoStorage() is empty when the module did not request Mongo
storage in its manifest, and on every daemon-host context. See the
Storage API page for the
ModuleDataStore and PlatformRedisStorage surfaces.
Cross-cutting primitives
EventBus events();Logger logger(); // SLF4JTaskScheduler scheduler();HttpClient httpClient(); // java.net.httpObjectMapper json(); // Jacksonevents()— cluster-wide event bus, mirror of the plugin SDK’sCloudPluginContext.events(). See EventBus.logger()— SLF4J logger pre-namespaced asmodule:<id>so module log lines are attributable in mixed-source streams.scheduler()— task scheduler for background work; tasks are cancelled automatically ononStop.httpClient()— pre-configured outboundHttpClient. Pool is shared across modules so per-module connection cost is amortised.json()— standard JacksonObjectMapper(java-time, ISO-8601,NON_NULLserialisation, lenient on unknown properties). Use this for REST payloads, event serialisation, anything wire-format. Do not bring Gson — it’s not on the classpath.
Lifecycle availability
| Hook | Storage | Capabilities | Events | Scheduler |
|---|---|---|---|---|
onLoad | safe (ensureCollection) | findCapability only — require* may fail if provider isn’t active yet | subscriptions allowed; publishing not yet | schedule* queued, run after onStart |
onUpgrade | safe | safe | safe | safe |
onRegisterRoutes | n/a — register only, don’t run logic | n/a | n/a | n/a |
onStart | safe | safe | safe | safe |
onStop | safe | best-effort | best-effort | tasks already cancelled |
onUnload | unsafe — references being dropped | unsafe | unsafe | n/a |
Example
public final class StatsAggregatorModule implements PlatformModule {
@Override public void onLoad(ModuleContext context) { // Mongo: required by manifest -> use require*. ModuleDataStore mongo = context.requireMongoStorage(); mongo.ensureCollection("sessions");
// Optional capability: the controller registers PlayerJourneyTracker // built-in, but a defensive findCapability keeps tests simple. PlayerJourneyTracker tracker = context.findCapability( PlayerJourneyTracker.CAPABILITY_ID, PlayerJourneyTracker.class).orElse(null);
// SLF4J logger pre-namespaced as "module:stats-aggregator". context.logger().info("loaded; tracker present={}", tracker != null); }}Next up
- PlatformModule — the contract that consumes this context.
- Storage API — Mongo + Redis details.
- EventBus —
events()deep dive.