Day 5 of 40
OSGi
Bundles, services, components, and the Felix console
By the end of today you should be able to
- Explain what an OSGi bundle is and how it differs from a plain JAR
- Describe the bundle lifecycle and what 'resolved' vs 'active' means
- Explain services, components and Declarative Services annotations
- Use the Felix web console to diagnose a bundle or component that will not start
Why AEM has a module system at all
AEM is a large Java application that must let you deploy, update and remove your code without restarting the server. That is what OSGi provides: a dynamic module system for the JVM. AEM's OSGi container is Apache Felix, and everything in AEM — including Adobe's own code — ships as OSGi bundles.
Bundles
A bundle is a JAR with extra manifest headers that declare its boundaries:
Bundle-SymbolicNameandBundle-Version— its identity.Export-Package— the packages it makes visible to other bundles.Import-Package— the packages it needs from elsewhere, with version ranges.
Unlike a plain classpath, nothing is visible unless it is explicitly exported and imported.
This strict boundary is the source of the most common OSGi frustration: a class that exists in the
JVM but that your bundle cannot see because nobody exported it. Your core module's
bnd/maven-bundle-plugin configuration generates these headers for you.
The lifecycle
A bundle moves through states, and knowing them turns a mysterious failure into a two-minute diagnosis:
- Installed — present, but its dependencies have not been satisfied.
- Resolved — every
Import-Packagewas matched. It can start. - Active — started and running. This is where you want to be.
A bundle sitting at Installed rather than Active almost always has an unsatisfied import. Open /system/console/bundles, click it, and read the imports — the unsatisfied one is flagged. Usually it is a version range mismatch or a dependency you forgot to make available.
Services and components
Inside a bundle, an OSGi component is a class managed by the container. If it publishes itself under an interface, it is also a service that other code can consume. AEM uses Declarative Services (DS) annotations, so you write plain annotated classes:
@Component(service = GreetingService.class)
public class GreetingServiceImpl implements GreetingService {
@Reference
private SlingSettingsService settings;
@Activate
protected void activate(Config config) { /* ... */ }
@Deactivate
protected void deactivate() { /* ... */ }
}
@Component— register this class with the container;service=names the interface(s) it publishes.@Reference— inject another service. By default this is mandatory: if it cannot be satisfied, your component stays unsatisfied and never activates.@Activate/@Deactivate— lifecycle hooks, called when the component starts and stops.
Components are dynamic. A service can come and go at runtime, and the container rewires dependents accordingly. That is why you never cache a service reference in a static field.
The web console
At /system/console (locally: http://localhost:4502/system/console) you get the diagnostic tools you will use constantly:
/system/console/bundles— every bundle and its state. Your first stop after a deploy./system/console/components— every DS component, and crucially why an unsatisfied one is unsatisfied./system/console/configMgr— OSGi configuration (day 30)./system/console/slingmodels— registered Sling Models and their adapters.
You do not get the Felix console on production. You get the Developer Console and downloadable logs instead. Locally the full console is available, which is exactly why reproducing problems on your local SDK matters.
Bundles are JARs with enforced boundaries; components are managed classes; services are components published under an interface. When something does not work after a deploy, check bundle state first, component state second.
Watch
Adobe's own videos for this topic. They load only when you press play.
Read on Experience League
The primary sources these notes are drawn from.
Your notes
Saved automatically to this browser.
Check yourself
11 questions on today's material. 80% to pass.