OSGiβs dynamic service model is both its greatest strength and its most common source of subtle, hard-to-diagnose bugs in production. OSGi.fx ships four advanced features that turn the invisible mechanics of runtime dynamism into something observable, testable, and safe:
| Feature | Summary |
|---|---|
| π Chaos Monkey | Continuously and randomly disrupts bundles/components to prove your runtime is resilient |
| π₯ Blast Radius Analysis | Shows exactly what will break before you stop a bundle or disable a component |
| π΅οΈ Conditions Monitor | Surfaces hidden OSGi R8 Conditions and lets you inject or revoke mocks live |
| π Activation Cascade Analysis | Predicts service hijacking and unexpected activations before you start a bundle or enable a component |

Chaos Monkey is a live, automated fault-injector that randomly and continuously disrupts your OSGi runtime, then self-heals β inspired by Netflix Chaos Engineering, adapted for OSGiβs bundle/component model.
You configure what to target, at what frequency, and for how long. The engine runs autonomously, disrupts victims, reverts them after their downtime expires, and cleans up completely when halted. Your runtime is always left in a valid state.
The engine is built from three cooperating classes:
| Class | Responsibility |
|---|---|
ChaosConfig |
Holds all user settings: target type, filters, timing, concurrency |
TargetSelector |
Picks eligible victims at each cycle using inclusion/exclusion glob filters |
ChaosEngine |
The scheduled loop that disrupts, reverts, and logs all actions |
Each engine cycle:
agent.start() or agent.enableComponentById() for any victim whose downtime has elapsedagent.stop() or agent.disableComponentById()Safety by design β the selector never touches:
0 (the system bundle)Configuration options:
| Setting | Range | Description |
|---|---|---|
| Target Type | BUNDLES, COMPONENTS, BOTH |
What kind of artifacts to disrupt |
| Inclusion Filter | glob pattern | Only target matching names |
| Exclusion Filter | glob pattern | Never target matching names |
| Action Interval | 5β60 s | Time between disruption cycles |
| Downtime Duration | 1β30 s | How long a victim stays offline |
| Concurrency | 1β10 | Maximum simultaneous victims |
| Auto-Stop Timer | 1β60 min | Engine halts automatically after this duration |
Preview (dry-run): The Preview button runs target selection without applying the concurrency limit, showing you the full pool of eligible victims before unleashing anything β a safe pre-flight check for the Chaos session itself.
Live UI: An Action Ticker table streams every disruption and revert in real time (timestamp / emoji icon / target name / state). An Offline Targets list shows what is currently down at any moment.
OSGiβs dynamic service model is its greatest strength β but that same dynamism is the most common source of bugs in production. Chaos Monkey proves (not assumes) that your system is resilient: that optional service bindings degrade gracefully, that mandatory references recover after a bundle restart, and that no hidden race conditions lurk in activation/deactivation phases.
The name is no coincidence. Chaos Monkey is a well-known open-source chaos engineering tool originally built by Netflix that randomly terminates virtual machine instances and services in production to test resilience. OSGi.fx adopts the same philosophy β and the same name β applied to the OSGi bundle and component model.

Before you stop a bundle or disable a DS component, Blast Radius Analysis runs a static simulation on live runtime data and presents a complete, categorised impact report. No changes are made to the runtime until you explicitly confirm.
It answers the question: βIf I stop this bundle right now, what else breaks?β
The analysis is a pure static computation driven by two ImpactAnalyzer utility classes β one in ui.bundles (for bundle stop/uninstall), one in ui.components (for component disable). Both operate on a snapshot of the live runtime state fetched from the connected agent.
For bundle stop or uninstall:
ImportedPackages β ExportedPackages wiring and BFS-traverses from the target bundle:
DEPENDENCY β bundle has static wiring to the provider; the wiring persists in JVM memory even after the bundle is stopped (OSGi spec behaviour)STALE_WIRING β on uninstall, those wires become stale and remain until PackageAdmin.refreshPackages() is explicitly calledSERVICE_UNBIND β that consumer will lose its service binding immediatelyDEACTIVATION (the component goes unsatisfied and deactivates)SERVICE_UNBIND (the component loses one binding but stays alive)SERVICE_UNBIND (simply unbound, no deactivation)For component disable:
Same service/SCR logic, no package-wiring traversal needed since DS components do not export packages.
Each impact row shows:
DEACTIVATION, SERVICE_UNBIND, DEPENDENCY, or STALE_WIRINGMost OSGi consoles give you a STOP command. None of them tell you what will break.
In a microkernel with dozens or hundreds of interdependent services, a single bundle stop can cascade into deactivations you never expected β mandatory references become unsatisfied, optional references silently unbind, and package wires become stale. Blast Radius Analysis makes the invisible chain of consequences explicit before you act.

The Conditions Monitor lets you observe every OSGi R8 Condition in your runtime β whether it is active, missing, or mocked β and inject or revoke synthetic conditions without redeploying anything.
Introduced in OSGi R8, a Condition is a named service typically carrying the property osgi.condition.id. DS components can declare a reference targeting a specific condition via a standard LDAP filter:
@Reference(target = "(osgi.condition.id=com.acme.gps.available)")
Condition gpsAvailableCondition;
While osgi.condition.id is the conventional property, any arbitrary LDAP filter can be used. It simply matches against the properties of any registered Condition service. If no matching condition service is registered in the framework, the component stays permanently UNSATISFIED β even if every other dependency is satisfied. This makes conditions a powerful but completely opaque gating mechanism.
In IoT and embedded OSGi deployments, conditions are the standard idiom for hardware-contingent feature activation:
osgi.condition.id = com.acme.gps.available)UNSATISFIED β by designThis is elegant in production, but creates a real problem during development and CI: you cannot test the hardware-contingent feature logic without the physical hardware. In a pure software environment, a CI pipeline, or a developer workstation, the condition is simply never registered.
OSGi.fx solves this directly:
MISSING condition (com.acme.gps.available) in the monitor β you can immediately see which components it is blockingZero code changes. Zero redeployment. No hardware required.
Each condition is described by XConditionDTO:
| Field | Description |
|---|---|
identifier |
The condition ID (e.g. com.acme.gps.available) |
state |
ACTIVE, MISSING, or MOCKED |
providerBundleId |
Bundle currently providing this condition (-1 if none) |
properties |
Service properties the condition carries |
satisfiedComponents |
DS components that are activated because this condition is present |
unsatisfiedComponents |
DS components that are blocked because this condition is absent |
The UI (ConditionsFxController):
MOCKED state highlighted in orange β never confused with real conditionsInject path (MockConditionDialog):
targetFilter OSGi LDAP string and pre-fills the dialog with the expected key-value pairs β no manual typing of filter propertiesagent.injectMockCondition(identifier, properties) registers a synthetic Condition in the remote frameworkRevoke path:
agent.revokeMockCondition(identifier) removes the mockMISSING conditions; the Revoke button is only enabled for MOCKED conditions β preventing invalid operationsThe hardware-availability gating workflow described above is idiomatic in IoT OSGi systems β but the core insight applies far beyond IoT. Think of OSGi Conditions as feature flags at the framework level: a condition can gate any feature, capability, or subsystem, not just hardware. Security readiness, licence checks, cloud connectivity, database availability β all can be modelled as conditions.
OSGi.fx fixes the testability gap entirely: you find the MISSING condition, see which components itβs blocking, click Inject, and the hardware-contingent (or feature-flagged) components activate on the spot β no hardware, no code change, no redeployment. Revoke restores everything when youβre done.
Beyond inject/revoke, the Conditions Monitor gives you complete visibility of the condition landscape:
ACTIVE, MISSING, or MOCKED β are listed in one placesatisfiedComponents and unsatisfiedComponents lists answer exactly βwhich components does condition X gate?β without any guesswork
Activation Cascade Analysis is the forward-looking counterpart to Blast Radius Analysis. Where Blast Radius asks βwhat breaks if I stop this?β, Activation Cascade asks βwhat activates β and what gets hijacked β if I start this?β
Before you start a bundle or enable a DS component, it runs a simulation on live runtime data and presents a complete, categorised prediction report. No changes are made until you confirm.
In OSGiβs dynamic service model, when multiple providers register the same service interface, the framework and DS select the provider with the highest service ranking (lowest service ID as the tiebreaker). This is a feature β it allows graceful upgrades and overrides.
But it is also a hazard: if a newly started bundle registers an implementation with a higher ranking than the existing provider, every consumer silently switches to the new provider. The old provider is still there, the consumer is still active, everything looks fine β but it is now bound to a completely different implementation.
This silent substitution is especially dangerous when:
For bundle start:
ACTIVATION β a currently-inactive bundle may now start because its missing package dependency will be providedDEPENDENCY β a currently-active bundle already has static wiring to this providerSATISFACTION β was UNSATISFIED or blocked; will now have its mandatory reference fulfilled and will activateDEPENDENCY β was already active; will bind to an additional provider β οΈ potential hijacking if the new provider has a higher service rankingACTIVATION (they will come to life as their host bundle starts)For component enable:
Same service-layer logic without the package BFS traversal.
Each impact row shows:
ACTIVATION, SATISFACTION, or DEPENDENCY (the last being the hijack-risk signal)The symmetry with Blast Radius Analysis is intentional: just as stopping something has downstream victims, starting something has downstream beneficiaries β and sometimes uninvited substitutions.
Service hijacking is the most subtle and dangerous failure mode in OSGi production systems, precisely because everything looks fine: the replaced service is still there, the consumer is still active, but it is now silently bound to a different implementation. There is no error, no warning, and no obvious signal that anything changed.
Activation Cascade Analysis makes this prediction explicit before the bundle or SCR component is ever started. Before you take action, you can foresee every downstream component and bundle that will be affected by the operation β which ones will newly activate, which ones will have their references satisfied for the first time, and β critically β which ones will silently rebind to a new provider. You get the full picture of the cascade upfront, so you can decide whether to proceed, adjust the service ranking, or choose a different deployment strategy.
This is particularly valuable during:
These four features form a complete resilience and observability toolkit for the OSGi dynamic service model:
| Feature | Timing | Direction | Key Question Answered |
|---|---|---|---|
| π Chaos Monkey | Live | Continuous mutation | Is my runtime actually resilient? |
| π₯ Blast Radius | Pre-flight | Stop β downstream | What breaks if I stop this? |
| π΅οΈ Conditions Monitor | Live | Bidirectional inspect + inject | Why is this component still unsatisfied? |
| π Activation Cascade | Pre-flight | Start β downstream | What activates β or gets hijacked β if I start this? |
Together they turn OSGiβs greatest strength β runtime dynamism β from a latent source of subtle, hard-to-debug failures into a well-understood, testable, and observable system property.