For the complete documentation index, see llms.txt. This page is also available as Markdown.

Lifecycle

Complete module lifecycle from discovery through registration, activation, and deactivation

BoxLang modules follow a well-defined lifecycle with distinct phases, each firing events that your module can listen to.

Lifecycle Overview

Phase 1: Discovery

When the runtime starts, the ModuleService scans configured paths for directories containing ModuleConfig.bx or box.json.

What happens:

  • Each discovered module becomes a ModuleRecord in the registry

  • Duplicates are resolved first-come-first-served

  • Module name is determined from box.json boxlang.moduleName or directory name

No events fire during discovery.

Phase 2: Registration

Each module is registered in the order discovered. Registration loads the descriptor and prepares the module but does not make it active.

1

PRE_MODULE_REGISTRATION Event

Fires before the module descriptor is loaded. The moduleRecord and moduleName are available in the event data.

2

Load Descriptor

The descriptor (ModuleConfig.bx or Java IModuleConfig) is loaded. The module's class loader is created with isolation from other modules.

3

Configure the Module

The configure() method is called:

  • Module settings struct is populated

  • Interceptors are registered from the interceptors array

  • Custom interception points are added

4

Discover Capabilities

Auto-discovery scans for:

  • bifs/ → BoxLang BIF files compiled and registered

  • components/ → BoxLang components registered

  • ServiceLoader entries → Java BIFs, components, services, schedulers, cache providers

  • public/ → Public web folder mapping

5

POST_MODULE_REGISTRATION Event

Fires after the module is fully registered. All module capabilities are available.

After all modules are registered, the AFTER_MODULE_REGISTRATIONS event fires.

Phase 3: Activation

Activation makes the module "live" in the runtime. Dependencies are activated first (recursively).

1

Resolve Dependencies

Dependencies declared in this.dependencies are activated in order before this module.

2

PRE_MODULE_LOAD Event

Fires before onLoad() is called. All dependencies are already active at this point.

3

onLoad() Called

The onLoad() lifecycle method executes. This is where you:

  • Register system setting providers

  • Register custom class resolvers

  • Modify runtime configuration

  • Initialize module state

  • Check for other loaded modules

4

POST_MODULE_LOAD Event

Fires after onLoad() completes successfully.

After all modules are activated, the AFTER_MODULE_ACTIVATIONS event fires, followed by ON_MODULE_SERVICE_STARTUP.

Phase 4: Running

The module is active and all its capabilities are available to the runtime:

  • BIFs are callable from BoxLang code

  • Components are usable as bx: tags

  • Interceptors are listening for events

  • Services are available via BoxRuntime

Phase 5: Deactivation (Shutdown)

When the runtime shuts down or a module is explicitly unloaded:

1

ON_MODULE_SERVICE_SHUTDOWN Event

Fires when the module service begins shutdown.

2

PRE_MODULE_UNLOAD Event

Fires before onUnload() is called.

3

onUnload() Called

The onUnload() lifecycle method executes. Clean up:

  • Unregister system setting providers

  • Unregister class resolvers

  • Close connections and resources

  • Remove any runtime modifications

4

Cleanup

The module service automatically:

  • Unregisters all interceptors

  • Unregisters JDBC drivers

  • Removes global services

  • Unregisters mappings

  • Closes the module class loader

5

POST_MODULE_UNLOAD Event

Fires after cleanup is complete.

Lifecycle Events Reference

Event
Phase
Data

PRE_MODULE_REGISTRATION

Registration

moduleRecord, moduleName

POST_MODULE_REGISTRATION

Registration

moduleRecord, moduleName

AFTER_MODULE_REGISTRATIONS

Registration

moduleRegistry

PRE_MODULE_LOAD

Activation

moduleRecord, moduleName

POST_MODULE_LOAD

Activation

moduleRecord, moduleName

AFTER_MODULE_ACTIVATIONS

Activation

moduleRegistry

ON_MODULE_SERVICE_STARTUP

Activation

moduleService

ON_MODULE_SERVICE_SHUTDOWN

Deactivation

moduleService

PRE_MODULE_UNLOAD

Deactivation

moduleRecord, moduleName

POST_MODULE_UNLOAD

Deactivation

moduleRecord, moduleName

Listening to Events

Your ModuleConfig.bx can listen to any lifecycle event by defining a matching method:

Your module config file is also registered as an interceptor automatically, so any runtime event method you define will be called.

Version Compatibility

During registration, the module's minimumVersion (from box.json) is checked against the running BoxLang version using semver:

  • Major version lower → Module is rejected with an error

  • Minor/patch version lower → Module loads but logs a warning

In development mode (BoxLang version 0.x.x), version checks are skipped entirely.

Next Steps

Last updated

Was this helpful?