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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.245.140