List of Figures
Chapter 1. OSGi revealed
Figure 1.1. Modularity refers to the logical decomposition of a large system into smaller collaborating pieces.
Figure 1.2. Multiple JARs containing overlapping classes and/or packages are merged based on their order of appearance in
the class path, with no regard to logical coherency among archives.
Figure 1.3. The OSGi Service Platform specification is divided into halves, one for the OSGi framework and one for standard
services.
Figure 1.4. OSGi layered architecture
Figure 1.5. A bundle contains code, resources, and metadata.
Figure 1.6. The service-oriented interaction pattern. Providers publish services into a registry where requesters can discover
which services are available for use.
Figure 1.7. Simple paint program user interface
Chapter 2. Mastering modularity
Figure 2.1. A module defines a logical boundary. The module itself is explicitly in control of which classes are completely
encapsulated and which are exposed for external use.
Figure 2.2. Classes have explicit dependencies due to the references contained in the code. Modules have implicit dependencies
due to the code they contain.
Figure 2.3. Even though object orientation and modularity provide similar capabilities, they address them at different levels
of granularity.
Figure 2.4. The paint program is a simple Swing application.
Figure 2.5. Paint program class relationships
Figure 2.6. A bundle can contain all the usual artifacts you expect in a standard JAR file. The only major difference is that
the manifest file contains information describing the bundle’s modular characteristics.
Figure 2.7. A class is a member of a bundle if it’s packaged in it, the bundle carries its module metadata inside it as part
of its manifest data, and the bundle can be deployed as a unit into a runtime environment.
Figure 2.8. Packages (and therefore the classes in them) contained in a bundle are private to that bundle unless explicitly
exposed, allowing them to be shared with other bundles.
Figure 2.9. Flow diagram showing the steps the JVM goes through to execute a Java program from the class path
Figure 2.10. Flow diagram showing the steps the JVM goes through to load a class from the class path
Figure 2.11. Graphical depiction of an exported package
Figure 2.12. Graphical depiction of an imported package
Figure 2.13. Structure of the paint program’s bundles
Figure 2.14. Logical structure of the paint program with separate modules for each shape implementation
Figure 2.15. Transitive dependencies occur when bundle A depends on packages from bundle B and bundle B in turn depends on
packages from bundle C. To use bundle A, you need to resolve the dependencies of both bundle B and bundle C.
Figure 2.16. Transitive bundle-resolution wiring
Figure 2.17. How does the framework choose between multiple exporters of a package?
Figure 2.18. If a bundle is already resolved because it’s in use by another bundle, this bundle is preferred to bundles that
are only installed.
Figure 2.19. Bundle A’s class space is defined as the union of its bundle class path with its imported packages, which are
provided by bundle B’s exports.
Figure 2.20. HTTP service-dependency resolution
Figure 2.21. Subsequent HTTP client-dependency resolution
Figure 2.22. Consistent dependency resolution of HTTP service and client bundles
Figure 2.23. Bundle export uses import
Figure 2.24. Uses constraints detect class-space inconsistencies, so the framework can determine that it isn’t possible to
resolve the HTTP client bundle.
Figure 2.25. Uses constraints guide dependency resolution.
Figure 2.26. Modular and nonmodular versions of the paint program
Chapter 3. Learning lifecycle
Figure 3.1. The four phases of the software lifecycle. An application is installed so you can execute it. Later, you can update
it to a newer version or, ultimately, remove it if you no longer need it.
Figure 3.2. Execution-time evolution: dynamically adding shapes to and removing shapes from the paint program as if by magic
Figure 3.3. Class path versus OSGi framework with full lifecycle management
Figure 3.4. Difference between the bundle identifiers
Figure 3.5. OSGi bundle lifecycle
Figure 3.6. Bundle cache during framework restarts
Figure 3.7. TelnetBinding overview
Figure 3.8. The install-related portion of the bundle lifecycle state diagram
Figure 3.9. The start-related portion of the bundle lifecycle state diagram
Figure 3.10. The stop-related portion of the bundle lifecycle state diagram
Figure 3.11. The update-related portion of the bundle lifecycle state diagram
Figure 3.12. The uninstall-related portion of the bundle lifecycle state diagram
Figure 3.13. Storing state externally
Figure 3.14. Storing state with other bundles
Figure 3.15. Storing state internally
Figure 3.16. Extender pattern overview
Figure 3.17. Paint program as an implementation of the extender pattern
Figure 3.18. Dynamic paint program class relationships
Figure 3.19. Updating and refreshing bundles is a two-step process. Most of the work normally takes place in the second step
during the framework refresh operation.
Chapter 4. Studying services
Figure 4.1. Services follow a contract and involve some form of discovery.
Figure 4.2. Using CRC to place responsibilities can be like playing pass-the-parcel.
Figure 4.3. Why you need contracts
Figure 4.4. Programming to interfaces means teams can work in parallel.
Figure 4.5. Simple dependency injection vs. service discovery
Figure 4.6. Listener pattern
Figure 4.7. Whiteboard pattern
Figure 4.8. OSGi service registry
Figure 4.9. Publishing a service that provides both stock listings and stock charts
Figure 4.10. Using an OSGi service
Figure 4.11. OSGi service ordering (by highest service.ranking and then lowest service.id)
Figure 4.12. Discovering an OSGi service
Figure 4.13. OSGi service events
Figure 4.14. Painting with services
Chapter 5. Delving deeper into modularity
Figure 5.1. If bundle C imports from B, both can share servlet instances with A because there’s only one copy of the Servlet
class; but this creates a dependency for C on B.
Figure 5.2. If B and C each have a copy of the Servlet class, A can only share Servlet instances with either B or C because
it can only see one definition of a class.
Figure 5.3. B and C can both export and import the Servlet package, which makes it possible for the framework to choose to
substitute packages so all bundles use a single class definition.
Figure 5.4. a) Your metadata declares explicit attributes that are attached to your bundle’s exported packages, but b) the
framework also implicitly attaches attributes explicitly identifying from which bundle the exports come.
Figure 5.5. Only attributes mentioned in the imported package declaration impact dependency resolution matching. Any attributes
mentioned only in the exported package declaration are ignored.
Figure 5.6. If an export attribute is declared as mandatory, importing bundles must declare the attribute and matching value;
otherwise, it won’t match when the framework resolves dependencies.
Figure 5.7. Bundle A exports the org.foo.service package but excludes the Util class. When bundle B imports the org.foo.service
package from bundle A, it can only access the public Service class.
Figure 5.8. A bundle can export the same package multiple times, but this is only a form of masquerading. Only one set of
classes exists for the package in the bundle.
Figure 5.9. Requiring a bundle is similar to explicitly importing every package exported by the target bundle.
Figure 5.10. When bundle B requires bundle A with reexport visibility, any packages exported from A become visible to any
bundles requiring B.
Figure 5.11. a) The host and fragment bundles are deployed as independent bundles in the framework. b) When the framework
resolves the host, it effectively merges the fragment’s content and metadata into the host bundle.
Figure 5.12. Paint program with installed German localization fragments
Chapter 6. Moving toward bundles
Figure 6.1. A bundle must have a unique identity.
Figure 6.2. Sharing implementations without exporting their packages
Figure 6.3. The classic application class loader merges JAR files into a single class space.
Figure 6.4. Embedding tightly coupled dependencies in a bundle
Figure 6.5. JAR-to-bundle cheat sheet
Figure 6.6. Turning a
Figure 6.7. Main jEdit window
Figure 6.8. jEdit when first run as OSGi bundle
Figure 6.9. Slicing code into bundles
Figure 6.10. Extracting a common jEdit plugin API
Figure 6.11. jEdit calculator plugin
Figure 6.12. Error attempting to print from jEdit
Chapter 7. Testing applications
Figure 7.1. Test deployment options
Figure 7.2. Testing Commons Pool inside an OSGi framework
Figure 7.3. Recommended test structure for OSGi bundle tests
Figure 7.4. Cobertura coverage report for Commons Pool
Figure 7.5. Mocking in action
Figure 7.6. Synchronizing tests with multithreaded code
Figure 7.7. Unit, bundle, and integration testing
Chapter 8. Debugging applications
Figure 8.1. Updated paint example running under jdb
Figure 8.2. Configuring the Eclipse Debugger
Figure 8.3. Debugging the paint example in Eclipse
Figure 8.4. Watching for NullPointer-Exceptions
Figure 8.5. Exception caused by a bad setColor() method
Figure 8.6. HotSwap failure updating DefaultShape
Figure 8.7. Successful HotSwap with the IBM JVM
Figure 8.8. Painting with the fixed example
Figure 8.9. Simple hub-and-spoke message system
Figure 8.10. Split packages and package-private visibility
Figure 8.11. Differences between ClassNotFoundException and NoClassDefFoundError
Figure 8.12. Mismatched wiring due to missing uses constraints
Figure 8.13. Using TCCL with nested containers
Figure 8.14. Leak suspects reported by the Eclipse Memory Analyzer
Figure 8.15. Leaking thread stack identified by the Eclipse Memory Analyzer
Figure 8.16. Classic dangling service
Figure 8.17. Delegating service proxy
Chapter 9. Managing bundles
Figure 9.1. Versioning packages independently
Figure 9.2. Impact on versioning between using and implementing the interface
Figure 9.3. The platform implementation contains many subpackages that must evolve in step with the specification, but what’s
the version of the implementation?
Figure 9.4. An administrator configures a bundle in the framework by interacting with the Configuration Admin Service. This
approach decouples the administrator from having to know the internal workings of the bundle using the configuration data.
Figure 9.5. Difference between a ManagedService and ManagedServiceFactory
Figure 9.6. Metatype Service overview
Figure 9.7. System and user-preferences trees
Figure 9.8. The lazy activation policy causes a bundle to defer activation and linger in the STARTING state until a class
is loaded from it, at which point the framework completes its activation.
Chapter 10. Managing applications
Figure 10.1. The OBR proposed specification provides a federated index that allows a management agent to resolve and install
large numbers of bundles from a number of remote locations. The OBR index files are aggregated by a RepositoryAdmin service
that resolves bundle dependencies on behalf of a management agent.
Figure 10.2. Relationships among the OBR repository entities
Figure 10.3. UML diagram of the Repository-Admin service. An external repository client uses the RepositoryAdmin and Resolver
interfaces to download and install bundles and their transitive dependencies.
Figure 10.4. Structure of a deployment package JAR file
Figure 10.5. Paint program packaging alternatives
Figure 10.6. Transactional aspects of a session
Chapter 11. Component models and frameworks
Figure 11.1. Trivial component composition of two components: FooImpl and BarImpl
Figure 11.2. Component frameworks in OSGi are generally implemented as other bundles using the extender pattern. They remove
boilerplate code from user bundles (often using metadata files—OSGI-INF/foo.xml in this case), allowing the deployer to build
complex business services out of modular building blocks.
Figure 11.3. Components used in the modified paint application
Chapter 12. Advanced component frameworks
Figure 12.1. Blueprint injects a proxy object, which masks changes in the OSGi service registry. If the underlying service
provider goes away and returns, the client code is insulated from this dynamism.
Figure 12.2. The Blueprint component lifecycle
Figure 12.3. The Blueprint metadata interface hierarchy
Figure 12.4. iPOJO components are an aggregation of handlers attached to the component container at execution time.
Chapter 13. Launching and embedding an OSGi framework
Figure 13.1. The Java META-INF/services approach discovers service providers at execution time by performing lookups of well-known
named resource files to acquire concrete service-implementation class names.
Figure 13.2. The embedded framework instance forms an isolation boundary between the bundles on the inside and the application
objects on the outside.
Figure 13.3. A framework instance represents the system bundle and provides the means to manage the framework instance as
well as interact with deployed bundles.
Figure 13.4. a) Before The service-based paint program is composed of five bundle sharing packages and services.
Figure 13.4. b) After The standalone paint program combines the core paint program, shape API, and launcher into a single
JAR file that provides and shares the API with the bundles and uses their services.
Figure 13.5. The standalone paint program
Chapter 14. Securing your applications
Figure 14.1. The JVM checks permissions by collecting all protection domains associated with classes on the call stack and
seeing if each involved protection domain has the specified permission granted to it.
Figure 14.2. Conditional Permission Admin Service overview
Figure 14.3. Secured paint program prompting the user to grant the unsigned circle bundle permission to provide a shape service
Figure 14.4. Secured paint program after the user has granted permission to the unsigned circle bundle
Figure 14.5. Secured paint program with an unsigned circle bundle and a signed square bundle
Chapter 15. Web applications and web services
Figure 15.1. In this chapter you’ll build a simple web application hosted on a single OSGi framework that calls out to a number
of back-end OSGi frameworks using web-services protocols.
Figure 15.2. The ResourceBinder has a mandatory dependency on the HTTP Service for providing content and an optional dependency
on the Log Service for logging errors.
Figure 15.3. Static content served from the OSGi HTTP Service
Figure 15.4. JSP shopping cart application running in an OSGi environment
Figure 15.5. The Google stock-watcher application running in an OSGi context
Figure 15.6. The Google stock-watcher application running in an OSGi context
Figure 15.7. When making remote services available, the number of options is bewildering: protocols, transports, authentication
schemes, and encryption algorithms all play their part.
Figure 15.8. Service providers and distribution providers can each define intents that are applied to a service endpoint.
Figure 15.9. The distribution provider bundle creates a remote endpoint for the service provider. It may also announce the
location and type of this endpoint for other distribution provider bundles to find. The client-side distribution provider
discovers remote endpoints and creates proxies to these services, which it injects into the local OSGi service registry.
Figure 15.10. Simple registry scheme that abstracts mechanism of service discovery