List of Figures
Chapter 1. OSGi and the enterprise—why now?
Figure 1.1. Conventional Java has a flat classpath which is searched in a linear order. For large applications, this classpath
can be long, and searches can be time consuming. If a class occurs more than once on the classpath, only the first instance
is used—even if the second copy is better.
Figure 1.2. A highly interconnected spaghetti application with little structure. The solid lines represent dependencies that
are identifiable at both compile-time and runtime, whereas the dotted lines are runtime-only dependencies. This sort of dependency
graph is typical of procedural languages.
Figure 1.3. An application with no structure beyond individual well-encapsulated objects (connections between objects aren’t
shown). This sort of structure is typical of object-oriented languages. Although the objects themselves are highly modular,
there’s no more granular modularity.
Figure 1.4. A well-structured application with objects grouped inside modules. Dependencies between modules are clearly identified.
This is typical of the application structure that can be achieved with OSGi.
Figure 1.5. The transitive dependencies of a module (the dependencies of its dependencies) may have incompatible versions.
In a flat classpath, this can be disastrous, but OSGi allows the implementations to coexist by isolating them.
Figure 1.6. Bundles may move between the installed, resolved, starting, active, and stopping states. A starting bundle can
be lazily activated, and if so it won’t move to the active state (crossing the dashed line) until it’s needed by another bundle.
A bundle is resolved if it’s installed and all its dependencies are also resolved or started. When a bundle is uninstalled,
it’s no longer able to start, nor can it provide packages to any new bundles.
Figure 1.7. The JVM contains many active classloaders in an OSGi environment. Each bundle has its own classloader. These classloaders
delegate to the classloaders of other bundles for imported packages, and to the environment’s classloader for core classes.
Figure 1.8. The class space for a bundle includes all of its private classes, and the public classes of any bundle it’s wired
to. It doesn’t necessarily include all the bundle’s public classes, because some might be imported from other bundles instead.
Figure 1.9. A service that’s provided by one bundle and used by another bundle. The narrow end of the triangle points toward
the service provider.
Chapter 2. Developing a simple OSGi-based web application
Figure 2.1. The elements of Apache Aries. Aries includes a Blueprint implementation, OSGi integrations for JPA, JTA, and the
web, application packaging, and JMX management. Blueprint is at the heart of a lot of the Aries function.
Figure 2.2. As well as Apache Aries components, the Aries sandbox stack includes an OSGi framework, a database, web container,
JPA and JTA implementations, and a few pieces of the Geronimo application server.
Figure 2.3. The output of the ss command, showing all the bundles in the OSGi framework
Figure 2.4. The layout of the fancyfoods.web JAR. All code lives in WEB-INF/classes. The web container looks at WEB-INF/web.xml
to find out what servlets are provided by the bundle. Finally, the standard JAR manifest, META-INF/MANIFEST.MF includes important
extra metadata for the OSGi container.
Figure 2.5. The web application in action
Figure 2.6. The class space of the fancyfoods.web bundle. It doesn’t have any public packages. To confirm which bundle exports
the javax.servlet package, type packages javax.servlet in your OSGi console, or bundle fancyfoods.web to see where all of
the packages used by fancyfoods.web come from.
Figure 2.7. The OSGi console can provide the list of bundles providing and consuming the javax.servlet package.
Figure 2.8. If the Geronimo servlet bundle is removed from the runtime, the fancyfoods.web bundle can’t be started, because
no servlet API is present.
Figure 2.9. OSGi fragments attach to a parent bundle and share its classloader.
Figure 2.10. The layout of the fancyfoods.web.nls.fr fragment
Figure 2.11. The Fancy Foods web page, before and after deleting the French-language translations from the load directory
Figure 2.12. Normal control and inversion of control. In the normal case, the consumer looks up a service it requires. In
the inversion of control model, also known as dependency injection, the consumer is automatically given the service. An application
container manages passing the service to the consumer.
Figure 2.13. The bundle details for the chocolate bundle show that it registers an OSGi service implementing the SpecialOffer
interface. A Blueprint container for this bundle is also registered as a service by the Blueprint implementation.
Figure 2.14. The backend of the Fancy Foods application. Triangles represent service dependencies, with the broad end of the
triangle facing the consumers of the service. There isn’t a direct dependency between the chocolate department and the offer
aggregator, but the offer aggregator does consume a service provided by the chocolate department.
Figure 2.15. The Fancy Foods web bundle accesses the offer aggregator service using JNDI. It has no direct dependency on the
chocolate or cheese department services.
Figure 2.16. Before the aggregator bundle is started, the Fancy Foods welcome page won’t be able to display any special offers.
Figure 2.17. After the aggregator and chocolate bundle are loaded, the page will display a special offer for chocolate.
Chapter 3. Persistence pays off
Figure 3.1. JDBC provides a useful Java-language access layer on top of a raw database. JPA and other ORM frameworks add support
for transparently moving between database entries and Java objects.
Figure 3.2. The datasource bundle is about as simple as a useful bundle could be. It has a manifest and a Blueprint file,
but nothing else.
Figure 3.3. Properties can be set for both beans and services using Blueprint. Bean properties are used by the bean’s business
logic. Service properties are invisible to the object implementing the service, but they’re visible to consumers of the service.
Figure 3.4. The datasource bundle provides three datasource services. The first and third were explicitly configured in the
blueprint.xml, but the second was automatically created by the container to provide support for implicit transactions.
Figure 3.5. The fancyfoods.datasource bundle explicitly declares two datasource services. A third service that consumes the
XADataSource is automatically registered by the container.
Figure 3.6. The schema for the Fancy Foods database. It’s probably not the most complex schema you’re likely to see in your
career! The database only has one table, representing a food. Foods have a name, a price, and a stock level.
Figure 3.7. The connection between a database and Java objects is managed by a JPA entity manager. The persistence unit defines
the relationship between the datasource and the classes.
Figure 3.8. The persistence bundle uses the services exposed by the datasource bundle. It accesses them by JNDI lookup.
Figure 3.9. The architecture of the Fancy Foods application
Figure 3.10. After the addition of the cheese department, datasource, and persistence bundles, the Fancy Foods shop has a
new special offer, driven from the cheese stock levels in the database.
Figure 3.11. The schema for the purchase-enabled Fancy Foods website. The schema is still simple, but there are now two entities,
and two corresponding tables in the database.
Figure 3.12. The SayHello servlet with links to allow users to purchase food
Figure 3.13. The BuyFood servlet prompts customers to fill in their name and how much food they’d like to buy.
Figure 3.14. When a user purchases a small quantity of cheese, their account is created and then debited, and the cheese stock
levels are reduced.
Figure 3.15. An attempt by Holly to buy three boxes of chocolates
Figure 3.16. If a user tries to buy something that exceeds their credit limit, the purchase doesn’t succeed and their account
isn’t debited. Unfortunately, the stock levels are reduced.
Figure 3.17. The transaction boundaries in the default case. If a purchase exceeds a customer’s credit limit, customer creation
will be rolled back, but the purchased food will still be removed from the inventory.
Figure 3.18. Better transaction boundaries. If a purchase exceeds a customer’s credit limit, no food will be removed from
the inventory.
Figure 3.19. With appropriately scoped transactions, an attempt to buy chocolate that’s beyond a customer’s means won’t result
in a change to their balance or to the chocolate inventory levels.
Chapter 4. Packaging your enterprise OSGi applications
Figure 4.1. Duplication of common libraries between EARs
Figure 4.2. An EAR and an ESA representing the same application. The EAR must include all its component JARs and all the libraries
it depends on. The ESA, on the other hand, need only include its component bundles, and even those may be loaded by reference
from a bundle repository.
Figure 4.3. This subsystem refers to two bundles, both of which are available in the repository, but one of which is present
in the ESA at a higher version. The higher-version bundle from the ESA is used at runtime, but the other bundle is provisioned
from a remote location found in the repository.
Figure 4.4. If you want to install this application bundle into a framework, then you need to ensure that the fancyfoods.logging
package is available. This is provided by a bundle that has a dependency on the common.logging.framework package, which must
also be satisfied by the resolution process. In this case, you pull in a third bundle that can supply the package and has
no further missing dependencies.
Figure 4.5. Isolation allows both Application 1 and Application 2 to share code with a single instance of a shared bundle
without exposing their internal bundles.
Figure 4.6. The minimum-effort EBA contains no metadata, only bundles.
Figure 4.7. The installed EBA. Because the development stack doesn’t support isolation, all of the application bundles are
visible using the ss command. These bundles have been installed, but not started, by the application runtime.
Figure 4.8. The relationships between bundles in your EBA. All of the bundles have a package dependency on the API bundle.
The two department bundles expose services that are consumed by the business bundle. The web bundle consumes services from
the business and persistence bundles indirectly, by JNDI.
Figure 4.9. The resolved EBA. As before, all of the application bundles are visible using the ss command. This also shows
that the API bundle has been installed, even though it wasn’t part of the application content, because it was needed as a
dependency.
Chapter 5. Best practices for enterprise applications
Figure 5.1. Bundles that have complex dependencies (like A) can typically only be used in one way, relying on the dependencies
they were compiled with. Bundles with a well-managed dependency graph can (like the refactored A') be reused in a variety
of ways, because it’s simple to satisfy their dependency requirements.
Figure 5.2. Bundles that are too granular will be forced to import and export lots of packages from other parts of the application
(solid lines). If the bundles are made slightly larger, many of those dependencies become internal-only (dotted lines).
Figure 5.3. Bundles that are too big can have far too many unrelated dependencies. Splitting these bundles up doesn’t reduce
the number of dependencies, but it can make the dependencies easier to manage, and the bundles easier to reuse, by not requiring
all the dependencies to be present all the time!
Figure 5.4. An importing bundle can only wire to a single instance of an exported package. If this client needs fancyfoods.split.Foo,
then you have a 50:50 chance of success. If it needs both fancyfoods.split.Foo and fancyfoods.split.Bar, then it can never
work.
Figure 5.5. In this case, the importing bundle, A, must wire to bundle B’s package because the mandatory directive on bundle
C’s package requires that the importer specify partial="true" to wire to it. B uses Require-Bundle: C to unify the package,
meaning that both fancyfoods.split.Foo and fancyfoods.split.Bar are visible to bundle A.
Figure 5.6. When the API for a service is separated from the client and implementations, then implementations can easily be
switched. On the left you see the client using implementation 1. If you remove implementation 1 from the system, then the
client can switch to implementation 2 with no loss in function or availability.
Figure 5.7. The listener pattern. A listener registers with an event source.
Figure 5.8. The whiteboard pattern. A listener registers with the Service Registry. When an event occurs, the event source
obtains an up-to-date list of listeners to notify from the Service Registry.
Figure 5.9. Whereas a WAR often needs to package all its code and dependencies inside the WAR itself, WABs can be much more
modular.
Figure 5.10. In an enterprise OSGi environment, it’s important to package persistence classes in the same bundle in which
the persistence units are defined.
Chapter 6. Building dynamic applications with OSGi services
Figure 6.1. A bundle using Declarative Services to consume a service into a managed component, which is then exported as a
service itself
Figure 6.2. When the singleton scope is used for a bean, every consumer of the bean is wired to the same instance.
Figure 6.3. When the prototype scope is used for a bean, every user of the bean is wired to a new instance. This allows beans
to maintain internal state, but it’s less scalable.
Figure 6.4. The lifecycle of a bundle’s Blueprint container and Blueprint beans is closely tied to the bundle’s lifecycle.
The init-method is called on eager singleton beans after the container is started; the destroy-method is called when the bundle
is stopped.
Figure 6.5. It’s possible that (a) a required service isn’t available, (b) there’s more than one match for a required service
or that a new service becomes available at runtime, or (c) a service that’s in use goes away.
Figure 6.6. The Blueprint container reporting that it’s waiting for a Blueprint dependency to become available
Figure 6.7. If the proxied implementation of a Blueprint-provided service becomes unavailable, the proxy will be transparently
wired to another implementation.
Figure 6.8. If the persistence bundle is stopped, the Blueprint container automatically makes the cheese special offer unavailable
and removes it from the reference list in the offer aggregator. Subsequent requests won’t see the cheese offer.
Figure 6.9. If a Blueprint service is unregistered after services that depend on it have been invoked, the proxy to the service
will block for five minutes before throwing a ServiceUnavailableException.
Figure 6.10. If a proxied service reappears after disappearing, blocked service calls will resume and complete almost normally.
But dependent services will be removed and reregistered, which could allow iterators to traverse them twice.
Figure 6.11. As services appear and disappear in a system, they’re automatically added to or removed from reference lists.
Chapter 7. Provisioning and resolution
Figure 7.1. Resources may have requirements and capabilities.
Figure 7.2. Resource repositories may contain resources of any type including, but not restricted to, bundles. Two resources
may share a symbolic name and version as long as they’re different types.
Figure 7.3. A requirement is satisfied by a capability if that capability is of a matching namespace, provides the attributes
needed by the requirement, and has no conflicting constraints.
Figure 7.4. If a capability includes the mandatory directive, requirements must specify the mandatory attributes to be satisfied.
In this case, a bundle with a requirement for the fancyfoods.mandatory package must also specify that chocolate is nice and
cheese is yummy for bundle B to satisfy the requirement.
Figure 7.5. How many instances of a capability are resolved is determined by the combination of the cardinality directive
and the resolution directive.
Figure 7.6. A resolver can make use of one or more repository services via the Environment to find out what capabilities are
available.
Figure 7.7. Your example repository contains three bundles with a variety of package exports, versions, attributes, and directives.
Figure 7.8. To resolve a bundle, a resolver will first model its requirements, and then query an environment for matching
capabilities and any transitive requirements of the matching resources. It will then further refine possible matches based
on the resource’s attributes and directives.
Chapter 8. Tools for building and testing
Figure 8.1. What build tools are right for you can be decided by whether you want to control your manifests or not, and which
build tools you already prefer.
Figure 8.2. Testing OSGi applications can be done in many ways. Any test process should include a simple unit test phase,
but the best way to do integration testing depends on a number of factors, including which build tools are already being used.
Figure 8.3. A range of tools for building, developing, and testing OSGi applications is available. Many of the tools build
on or integrate with other tools, or even several other tools.
Chapter 9. IDE development tools
Figure 9.1. When choosing an IDE, the most important factor to consider is whether you’re developing code-first or manifest-first.
Good tools based on the Eclipse platform are available in both cases, but other options are also available, particularly in
the code-first case. No matter which development style you’re using, if you’re using Eclipse as your IDE you may also want
to use one of the development tools specifically designed to support the enterprise OSGi programming model.
Figure 9.2. Eclipse adds a plug-in dependencies container to each project’s classpath. Required projects and JARs from the
target platform are added. If you’re curious about what’s on the classpath, you can look inside each bundle by expanding it.
Figure 9.3. Eclipse PDE makes it easy to define a target platform from the Aries assembly. This platform is used for both
compiling and running.
Figure 9.4. Eclipse PDE offers a nice manifest editor. As well as a source view, there are tabs for controlling package imports,
exports, and what’s packaged into a built bundle.
Figure 9.5. If imported packages aren’t available in the target platform, Eclipse will highlight them in the manifest. In
this case, fancyfoods.food is available, because it’s another Eclipse project, but the javax.persistence and openjpa APIs
can’t resolve.
Figure 9.6. The manifest editor’s dependency analysis view shows which bundles depend on the current bundle, and also which
bundles the current bundle depends on.
Figure 9.7. Eclipse PDE’s visualization of the dependency hierarchy of the Fancy Foods application.
Figure 9.8. Bnd maintains a list of bundle repositories that are used for compiling and running bundles. To ensure your compile-time
dependencies are available, you can add them to the internal bndtools repository.
Figure 9.9. You’ll need to add the bundles your project depends on in the Build tab in the bndtools bnd file editor.
Figure 9.10. Bndtools will show you the calculated imports for each bundle, which can help avoid runtime surprises. You can
even see which classes are using the imported packages.
Figure 9.11. NetBeans provides a GUI editor to choose which packages you want to export from a module.
Figure 9.12. The manifests for NetBeans OSGi bundles allow variable substitution. The editor doesn’t have autocompletion or
error detection.
Figure 9.13. When you add a module explicitly to one of your NetBeans modules, it shows in the Libraries twisty of the module.
This is similar to the plug-in dependencies twisty in Eclipse, and Eclipse’s referenced libraries twisty.
Figure 9.14. The Osmorc IDE being used to develop the fancyfoods application
Figure 9.15. Osmorc’s manifest editor has fewer features than Eclipse’s, but it does provide syntax highlighting, error-detection,
and autocompletion.
Figure 9.16. One nice feature of Osmorc is that it allows you to choose whether to manage your manifests yourself, or to have
your manifests managed for you based on your module dependencies.
Figure 9.17. When you opt to let Osmorc manage your manifests, you can point it to a bnd file, or fill in a simple panel on
the module settings page with bnd-style settings. Don’t forget to narrow down the default package exports.
Figure 9.18. The Rational tools support Aries-style EBA applications. The APPLICATION.MF files may be edited as text files
or in a GUI editor.
Figure 9.19. In the Java EE perspective, the web.xml files of OSGi bundles with the web facet can be easily visualized and
manipulated.
Figure 9.20. Libra allows you to add OSGi facets to servlet and JPA projects.
Figure 9.21. Eclipse allows unit tests to be run in an OSGi framework from within the IDE using a simple menu option. The
target platform is used to generate the list of bundles to install in the OSGi framework.
Figure 9.22. Eclipse presents test results from JUnit tests that were run inside a framework in the same GUI format as normal
JUnit results.
Figure 9.23. Bndtools can run JUnit tests inside an OSGi framework from within Eclipse.
Chapter 10. Hooking up remote systems with distributed OSGi
Figure 10.1. Horizontal scaling allows client requests to be transparently distributed across a number of servers to increase
throughput.
Figure 10.2. A simple web server can forward complex processing tasks out to dedicated machines for execution, returning results
when the task is complete.
Figure 10.3. If all your services exist on one big server, then maintenance to any of them can break a client. In this case,
the client only needs to access services A and D, but suffers an unnecessary outage whenever B or C needs updating. If the
services all exist on separate servers, then the client can continue to operate even if B and C are no longer available.
Figure 10.4. In combination with a firewall, an intermediate server can be used to provide safe access to a secure system
without allowing direct access to it.
Figure 10.5. The execution times for remote methods are dramatically increased by the latency of the network, even on a local
network with a 500 microsecond latency.
Figure 10.6. A distribution provider uses the whiteboard pattern to locate remotable services and expose them outside the
OSGi framework.
Figure 10.7. A distribution provider can also create OSGi services within an OSGi framework that delegate to remote endpoints.
Figure 10.8. The distributed Fancy Foods system includes two frameworks. The original framework includes a new fancyfoods.remote.config
bundle; the remote framework reuses some Fancy Foods bundles and adds a new fancyfoods.department.foreign bundle.
Figure 10.9. The local view of your remote service
Figure 10.10. The WSDL for your remote service
Figure 10.11. Invoking your remote service
Figure 10.12. Without your remote service
Figure 10.13. After adding Distributed OSGi
Figure 10.14. Your Jetty service properties
Figure 10.15. Using your new Jetty port
Figure 10.16. Your remote-enabled superstore
Figure 10.17. Trying to buy some foreign food—part 1
Figure 10.18. Trying to buy some foreign food—part 2
Figure 10.19. Running with a remote database
Figure 10.20. A second attempt to buy from your foreign foods department
Figure 10.21. A successful purchase
Figure 10.22. A new special offer!
Figure 10.23. If the remote implementation of a remote service is missing, the service will still be available, but using
it will cause errors.
Figure 10.24. As this server error demonstrates, SCA’s WSDL binding only works well for services whose interfaces are restricted
to using primitive types.
Chapter 11. Migration and integration
Figure 11.1. SCA systems consist of components connected by bindings.
Figure 11.2. SCA provides a toolkit of component types and a toolkit of connectors that can be mixed and matched to bind endpoints
together. The component types and bindings we show here aren’t an exhaustive list, not least because SCA is extensible.
Figure 11.3. SCA bindings are exposed to OSGi applications as services, which means non-SCA-aware OSGi applications can communicate
with non-SCA-aware applications of other types by consuming normal OSGi services.
Figure 11.4. An ESB acts as a common transport channel loosely connecting diverse endpoints. Communications may be mediated
with XSLT transforms or other adjustments to the content.
Figure 11.5. A typical WAR layout
Chapter 12. Coping with the non-OSGi world
Figure 12.1. Tools can take a conventional Java JAR and produce sensible OSGi bundles more reliably than converting them by
hand.
Figure 12.2. The output from Bundlor
Figure 12.3. Unlike compile-time dependencies (solid lines), reflective dependencies (dashed lines) may not be explicitly
declared in bundle manifests. This won’t cause problems for JARs, which have little distinction between internals and externals,
but it can cause runtime failures for bundles.
Figure 12.4. If the containing folder of a configuration file, or other resource, isn’t explicitly exported as a package by
Bundle B, it won’t be visible in the class space of Bundle A.
Figure 12.5. The thread context ClassLoader gives Java code in Bundle A visibility of classes that aren’t normally in its
class space (solid gray area). But in an OSGi environment, the class space of the thread context ClassLoader (dotted area)
may exclude classes normally visible to Bundle A.
Chapter 13. Choosing a stack
Figure 13.1. To see the features Karaf can install, use the features:list command.
Figure 13.2. To install Aries into Karaf, you’ll need to install the war, transaction, jpa, jndi, and application-without-isolation
features.
Figure 13.3. Out of the box, Karaf shows the Blueprint status when listing bundles. In this case, the datasource JNDI name
in the persistence.xml is incorrect, so Blueprint can’t inject an EntityManager into the inventory bean, and reports a failure.
Figure 13.4. Geronimo lists all installed EBAs and allows you to start, stop, and uninstall them. Conveniently, it also shows
the web context root.
Figure 13.5. The Geronimo console includes a nice graphical bundle viewer that shows a bundle’s package and service dependencies.
Figure 13.6. The Fancy Foods bundles installed in the WebSphere bundle repository. This allows them to be automatically provisioned
and shared between several applications.
Figure 13.7. WebSphere Application Server provides management support for updating individual bundles in an EBA. For example,
the fancyfoods.department.chocolate bundle may be updated from version 1.0.0 to 1.1.0 after the initial deployment when a
new version of the chocolate bundle becomes available.
Figure 13.8. A dump will be automatically generated for a variety of failures, including OSGi resolution failures. The dump
records active threads, the current configuration, repository contents, and a snapshot of the OSGi state of the server.
Figure 13.9. If you install the fancyfoods.department.chocolate bundle before the fancyfoods.api bundle, the chocolate bundle
can’t be resolved. Exploring the snapshotted OSGi state shows the reason for the resolution failure.
Figure 13.10. The Felix Gogo shell, as it appears in GlassFish
Figure 13.11. The JBoss administrative console has an OSGi section that allows you to view and configure the framework properties
and server bundles.
Figure 13.12. The bundle IDs show that the core Nimble distribution includes only a handful of bundles. When the fancyfoods.api
and fancyfoods.web bundles are installed, more bundles are provisioned, including the jetty web container and a few GlassFish
bundles.
Figure 13.13. A repository that contains the Fancy Foods application can be generated by indexing a built copy of the source
tree. If the --enable-ee-spotters flag is added, the resulting OBR index will include extra requirements for enterprise OSGi
function. The index can be viewed from within the Posh shell using the more command.
Appendix A. OSGi—the basics
Figure A.1. The transitive dependencies of a module (the dependencies of its dependencies) may have incompatible versions.
OSGi allows the implementations to coexist by isolating them from one another.
Figure A.2. The JVM contains many active classloaders in an OSGi environment. Each bundle has its own classloader. These classloaders
delegate to the classloaders of other bundles for imported classes, and to the environment’s classloader for core classes.
Figure A.3. The classloaders form a delegation chain. If a classloader can’t load a given class, it passes the request to
the next classloader in the chain.
Figure A.4. The class space for a bundle includes all of its private classes, and the public classes of any bundle it’s wired
to. It doesn’t necessarily include all of the bundle’s public classes, because some might be imported from other packages
instead.
Figure A.5. A bundle fragment attaches to its host and shares a classloader.
Figure A.6. Bundles may move between the installed, resolved, starting, active, and stopping states. A starting bundle can
be lazily activated, and if so it won’t move to the active state (crossing the dashed line) until it’s needed by another bundle.
A bundle is resolved if it’s installed and all its dependencies are also resolved or started. When a bundle is uninstalled,
it’s no longer able to start, nor can it provide packages to any new bundles.
Figure A.7. A service that is provided by one bundle and used by another bundle. The triangle points toward the service provider.
Figure A.8. A service consumer may consume multiple instances of a service.
Figure A.9. The functionality of OSGi includes a number of layers. The white elements are provided by OSGi, the gray elements
are prerequisites, and the black elements are user content. Applications will take advantage of the core OSGi framework by
providing modules, possibly with sophisticated lifecycles. These modules may communicate with one another and the supporting
platform using OSGi services. Security is provided across all layers.
Figure A.10. The Felix OSGi console, in a minimal Felix installation. Bundles may be queried, installed, started, and stopped.
Available bundles may be listed using the lb command.
Figure A.11. The Equinox OSGi console. Available bundles may be listed using the ss command. In this case, the Fancy Foods
application is installed, but many of its dependencies aren’t, so most of the application bundles don’t resolve (and are shown
as INSTALLED only).
Appendix B. The OSGi ecosystem
Figure B.1. The OSGI service platform includes a number of specifications. The Core Specification is the foundation on which
the other specifications are built. The Compendium Specification defines a range of extra services. The Enterprise and Mobile
Specifications are subsets of the standards defined in the Compendium Specification. Some elements of the Enterprise Specification
were defined after the most recent version of the Compendium Specification and will be rolled back into the next version.
Figure B.2. How the OSGi Enterprise Specification overlaps with the Compendium and Core Specifications. Version 4.3 of the
Compendium Specification should be a superset of version 4.2 of the Enterprise Specification.