Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

...

Background

Excerpt

In a service oriented architecture, applications consist of several cooperating services. These networks of services are often dynamic in nature, so managing dependencies is something the developer needs to take into account.

In an OSGi framework, services are deployed using bundles and these bundles feature two types of dependencies:

  1. Package dependencies. A bundle can export a package which others import. These dependencies, although dynamic, are
    relatively easy to handle.
  2. Service dependencies. Services, encapsulated in deployable components (bundles) can be started and stopped any time. Other components often depend on these services and need to deal with changes in their availability.

When you look at dependency management, there are two aspects you need to take into account:

The first is managing software configurations. This means you need to manage the dependencies from a configuration standpoint. What you are managing are bundles, since those are the units of deployment. What you need to manage are the package and service dependencies between bundles. Package dependencies are always visible by examining the bundle manifest and when a bundle is installed the framework will try to resolve such dependencies before that bundle can even be started. Service dependencies are only optionally described in the manifest by a list of services a bundle might export as well as a list it might use (import). The words 'optionally' and 'might' already indicate that these aren't things we can depend on. The framework doesn't have to perform any checks on these attributes.

The second is managing service dependencies at runtime. As mentioned before, a service oriented architecture is dynamic by design, so your implementation should be able to deal with this. Bundles can start in any order and any service can go away or be replaced by a dif ferent implementation at any point in time. OSGi itself of fers basic assistance for tracking services. You can track them yourself by registering as a service listener. A slightly more advanced way is to create a service tracker, which you can subsequently query, or have it notify you on changes. A third alternative is the service binder SBINDER, which uses XML component descriptors to specify the dependencies.

In real implementations, you are probably going to track multiple services. Using service trackers in such a scenario has the tendency to result in dependency logic that is entangled in the implementation instead of being expressed in a declarative way, as can be seen in the code example in appendix C. Using a declarative way to specify dependencies has clear advantages when it comes to monitoring and managing them, a task that becomes more and more important in modern, federated, service oriented environments. This article presents a solution that allows you to just define the dependencies and let a dependency manager do all the hard work for you.

Goals

Two important goals drove the design of the dependency manager:

There are a couple of concepts, explained here, that help understand the dependency manager better. This page lists them.

White board pattern

The white board pattern presents a more efficient way to implement listeners. Instead of having listeners track sources and registering themselves with those sources, the white board pattern has the listeners register themselves as services in the OSGi service registry. When a source needs to notify listeners, it simply looks up all listener services in the registry and notifies them.

The pattern is explained in great detail in (warning) TODO-ref where both the traditional listener implementation and the white board implementation are compared.

Null object pattern

A null object pattern (warning) TODO-ref provides an object as a surrogate for the lack of an object of a given type. It essentially provides intelligent "do nothing" behavior, hiding the details from its collaborators. The pattern is also known as "Stub" or "Active Nothing".

The motivation for using it is that sometimes a class that requires a collaborator does not need the collaborator to do anything. However, the class wishes to treat a collaborator that does nothing the same way it treats one that actually provides behavior

...

.