3.7. Life within the Framework

Let's follow a few common scenarios to explore the interplay of various entities in the framework. We avoid covering every detail for fear of obfuscating the discussion. With the basic concepts soundly established, you will be able to complete the picture from the tutorials in later chapters as well as from the official specification itself.

3.7.1. Installing a Bundle

To install a bundle (Figure 3.8), we simply supply the framework with the URL of the bundle's JAR file. The bundle's JAR file may reside on a Web server over the network or on the local file system.

Figure 3.8. Installing a bundle


The framework retrieves the contents of the bundle from the given location and installs it on the gateway. Once installed, the bundle is assigned a unique integral ID, and its state becomes INSTALLED. An event is broadcast to notify the listeners that the bundle has been installed.

Bundles with the same location strings are considered identical. Consequently, if the same bundle was moved to a new location, it would be regarded as a different bundle and would get installed twice.

3.7.2. Starting the Bundle

The framework examines the manifest headers of the bundle, and extracts the following information about the new bundle:

  • What packages this bundle offers to export (Export-Package header)

  • What packages this bundle needs to import (Import-Package header)

  • Which class is the activator for this bundle (Bundle-Activator header)

If the bundle needs to import packages, the framework checks whether any of the resolved bundles have exported those packages. If this succeeds, the bundle is resolved; otherwise, the bundle activation fails.

If the bundle is resolved or does not import any package, the bundle enters the RESOLVED state. It then exports its packages, as declared in the Export-Package manifest header, to the framework.

The framework creates a BundleContext object for the bundle, calls the start method of the bundle's activator, and passes in BundleContext as the argument. The bundle should register any services it provides in the start method at this time. If it does register a service, an event is broadcast to notify interested listeners that a service has been registered. For the brief period when the start method is being executed, the bundle is temporarily in the STARTING state.

On the successful return from the activator, the bundle moves into the ACTIVE state, and another event is broadcast to notify interested listeners that the bundle has been started (Figure 3.9).

Figure 3.9. Starting a bundle: exporting packages and registering services. The shaded portion of http.jar shows the implementation package internal to the bundle, whereas the unshaded portion indicates the exported package to be shared with other bundles.


3.7.3. Importing Packages and Getting Services

Next, suppose the streaming audio bundle, mp3.jar, comes along and gets installed much as http.jar depicted in the previous section. When the bundle is to be started, the framework attempts to satisfy its import requirements. mp3.jar states that it imports the http.service package, which has been exported by http.jar. The framework finds the match and marks mp3.jar as RESOLVED. Because mp3.jar's dependency on http.jar has been resolved, the mp3.jar bundle can be started, and it becomes ACTIVE.

During the course of its execution, mp3.jar needs to call the HttpService API. Knowing what it needs, it asks the framework for a service implementing the http.service.HttpService interface from the service registry.

The framework returns a reference to the requested service, represented by a ServiceReference object, to the calling bundle (mp3.jar, in our case). The caller then proceeds to obtain the service itself and invokes the appropriate API defined by the service (Figure 3.10).

Figure 3.10. Importing packages and getting services


An important aspect of the interaction is that the HttpService interface is the coupling contact between the calling bundle mp3.jar and the service-providing bundle http.jar, and it is the only interface from the http.service package exported by the latter (Figure 3.11).

Figure 3.11. Two well-defined interfacing mechanisms. A service interface serves as the interbundle interface and the bundle context serves as the bundle-to-framework interface.


3.7.4. Handling the Dynamic Service Dependency

Within the framework, events are broadcast when bundles go through their life cycle states and when services are published or withdrawn. Let's examine how events can be used to cope with the unregistration of a service as a result of its bundle being stopped and uninstalled.

The streaming audio bundle understands that HttpService is registered by another bundle that is outside its control and may disappear (be unregistered) at any time, so it needs to monitor the unregistration events of the service.

Suppose that http.jar has to be uninstalled. As part of the process (see Section 3.7.6), the framework calls the stop method in the http.jar bundle's activator, which unregisters HttpService from the framework registry. The framework then removes http.jar from the gateway.

Bundle mp3.jar, having depended on http.jar for its service, receives the notification that HttpService is being unregistered (HttpService's unregistration is not completed until all interested parties have been notified and they have finished any action in response to the pending event of HttpService being unregistered). The mp3.jar bundle does the proper cleanup to ensure it no longer calls HttpService. It may continue to monitor service registration events, hoping that HttpService may come back, in which case it reobtains HttpService.

3.7.5. Updating a Bundle

One of the most important features of the framework is the capability of updating a bundle at run-time, which allows a newer version of a bundle to take over on the gateway. This is essential for delivering bug fixes and feature enhancements to deployed gateways in the field.

The new bundle should strive to make changes only in the implementation, not the exported packages. This practice minimizes disruption to bundles that depend on the bundle undergoing update. For the Java Embedded Server product, the new versions of the exported packages will not be exported and will not take effect until the next time the framework is restarted.

It is imperative to reaffirm the behavior that the framework refuses to export a package that has already been exported, and the exported package will remain regardless of whether the exporter is stopped or uninstalled. Therefore, it is impossible to have the new package take over by restarting the old bundle or by uninstalling the old and then reinstalling the new bundle. If you modify the classes in the exported package, the only way to use the new version is to shut down the framework, then relaunch it. This is why a stable and minimal interface between bundles is crucial for updates to be effective and successful.

Assume that http.jar is updated. Let's follow the procedures of an update. The HTTP bundle is stopped. As a result, HttpService is unregistered. Recall that mp3.jar is using the service and is monitoring its availability, so mp3.jar is able to brace itself for the change.

The new version of the HTTP bundle is fetched from the following sources:

  1. If the existing bundle has the manifest header Bundle-UpdateLocation defined, then that location is used to fetch the new version. This configuration is useful when the old bundle knows the location of future updates ahead of time.

  2. If no Bundle-UpdateLocation is defined, then the new version is expected to come from the same location as the old bundle.

The new bundle will be installed. If installation fails, the framework reverts to using the old bundle. Otherwise, the new bundle's state becomes INSTALLED, and an event is broadcast to notify interested listeners that the bundle has been updated. Because the HTTP bundle was active prior to the update, the new bundle is started.

As the new HTTP bundle is started, no package is exported because the http.service package exported by the old version remains in effect and is still imported by the mp3.jar bundle. HttpService is registered again at this time. The service interface remains intact (as part of the http.service package), but its implementation surely has changed.

The client bundle, mp3.jar, learns that the new service is registered and it should reacquire the service. Once this is achieved, it can go about its own business as before.

This narrative demonstrates how the principle of separating interfaces from implementations works in reality: The HTTP bundle only puts its service interface in one package (http.service), and it hides its implementation classes in another package (http.impl), which is not exported. In this way the HTTP bundle can update its implementation and ensure that its callers won't break because of binary incompatibility, and they can take advantage of the update right away.

Because a bundle's original location string and bundle ID are usually used to establish its identity, when the bundle is updated in the framework, they remain unchanged.

We can also demonstrate the update process using the bundle created in the previous chapter. Install and start the example bundle as before, then make the following change to the source SweetHome.java: Replace the string I'll be back to Bye in the stop method. Recompile and repackage the bundle JAR file as described previously, except that the altered JAR file is named newhome.jar. Now do the following:

> bundles
ID  STATE     LOCATION
--  --------- -------------------------
1   ACTIVE    file:/home/joe/bundles/home.jar

This shows the original bundle's location and ID.

Next we update home.jar, whose ID is 1, with the new bundle newhome.jar identified by its URL:

> update 1 file:/home/joe/bundles/newhome.jar
I'll be back
Home, sweet home

Notice that you must specify a space, not a comma, between the ID and the URL. The old bundle was stopped (we see its activator's stop method was called), then the new one was installed and started (thus its activator's start method was called). Then we reexamine the bundle status:

> bundles
ID  STATE     LOCATION
--  --------- -------------------------
1   ACTIVE    file:/home/joe/bundles/home.jar

It shows that the ID and location of the original bundle are unchanged, despite the fact that the new bundle was fetched from a different URL.

Lastly, we stop the bundle:

> stop 1
Bye
>

The message displayed testifies that the bundle has indeed been updated to reflect the new behavior.

3.7.6. Stopping and Uninstalling a Bundle

When a bundle is to be stopped, the framework calls the bundle activator's stop method. While the method is being executed, the bundle is briefly in the STOPPING state. The framework then automatically performs the following tasks:

  1. Unregisters the service provided by the bundle. During this process, an event is broadcast to notify interested listeners that the service is being unregistered.

  2. Releases any services in use by the bundle (details in Chapter 4)

  3. Removes any event listeners added by the bundle

  4. Moves the bundle back to the RESOLVED state

  5. Broadcasts another event to notify listeners that the bundle has been stopped

If http.jar is stopped, HttpService is unregistered in step 1, and nothing needs to be done for steps 2 and 3, because it is not using any service from another bundle and it has not added a listener. On the other hand, if mp3.jar is stopped, nothing needs to be done for step 1 because it has not registered any service. However, HttpService, which it has been using, is released at step 2, and its event listener is removed at step 3. Both, of course, follow through with steps 4 and 5.

When uninstalled, the bundle is removed from the gateway, an event is broadcast to notify the listeners that the bundle has been uninstalled, and its state becomes UNINSTALLED.

Even when a bundle is stopped or uninstalled, the packages it has exported remain in force to ensure that other bundles that have come to depend on those packages still have access to them.

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

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