OSGi is a framework for building modular applications in the JVM.
- A bundle is the unit of modularisation in OSGi. “It is simply a JAR with additional information. This information allows you to control what packages are imported, exported, as well as which ones are private and/or hidden.” (Instant OSGi Starter)
Bundles have a lifecycle:
- On Install: Installed → Resolved → Starting → Active
- Then on Stop: → Stopping → Resolved
- Then on Uninstall: → Uninstalled
A bundle’s start level is a number that indicates when a bundle should be started. A bundle is started if: OSGI framework start-level >= bundle start level
When booting, the OSGi framework starts all bundles whose start level is equal to or lower than that of the framework’s active start level. This is done in ascending order; that is, the framework starts all bundles whose start level is n, then n+1, n+2, …, until n is equal to the framework’s active start level.
For example, if the active start level is 2, then first you’ll start all bundles whose start level is 0, then those whose start level is 1, and then finally those whose start level is 2.
– OSGi in Depth by Alexandre de Castro Alves, Chapter 11: Launching OSGi using start levels
- The default start-level of a Fuse container is
100. This means it will start all bundles where the start level is 100 or less.
Services are a way of publishing objects (beans) to a central registry, so that they can be consumed by bundles.
osgi:service to define/expose a service, e.g.:
<bean id="myHelloService" .../> <osgi:service ref="myHelloService" interface="xyz.tomd.HelloService"/>
osgi:reference to reference it from another bundle, e.g.:
<osgi:reference id="myHelloService" interface="xyz.tomd.HelloService"/>
- Features are simply a set of OSGi bundles grouped together into a single deployment
- To upgrade a feature in Karaf/Felix, you have to stop and uninstall the feature first. Use
addurlto add the URL (
mvn:...) to the new version.
- Make bundles as restrictive as possible by exporting (via
Export-Package) only the classes that absolutely must be shared
- Avoid the
Require-Bundleheader, as it can cause split packages (where a package may be split across two bundles that export it); favour fragment bundles instead
DynamicImport-Packagebecause it means the class is only searched for when it is needed, rather than at bundle resolution time. Favour using optional packages or other alternatives.