59 Condition Service Specification

59.1 Introduction

In dynamic systems, such as OSGi, one of the more challenging problems can be to define when a system or part of it is ready to do some work. The answer can change depending on the individual perspective. The developer of a web server might say, the system is ready when the server starts listening on port 80. An application developer however would define the system as ready, when the database connection is up and all servlets are registered. Taking the application developers view, the web server should start listening on port 80 when the application is ready and not beforehand.

The Service Layer already provides all the necessary tools to register any service as an indicator for when a system is ready. The Condition Service Specification simply provides a specified service to signal such conditions. With this, other specifications and users have a known service to listen for such conditions.

59.1.1 Essentials

  • Condition - Represents a particular state of the runtime.

  • Target - A filter used to match a required condition.

59.1.2 Entities

  • Condition - A service used to represent a state at runtime.

  • True Condition - A condition registered by the Framework with a well known name which is always available from the moment of Framework initialization.

59.2 Condition Service

BundleStartLevel can be used to control the order in which bundles are activated when the Framework is launched. In some scenarios it can be helpful to have certain bundles activate before other bundles so that the necessary services provided by the previously activated bundles are ready before the later activated bundles start. However, such solutions have drawbacks in a dynamic system because dependencies can appear and disappear at any time. Also, there is no guarantee that when a bundle finishes activation, that it has registered all the services that it ever will for the lifetime of its active state.

A better solution is to model ordering as a dependency. Once something is a service dependency, an injection framework, such as Declarative Services or CDI Integration, can defer component activation until the dependency is available. With a proper dependency, when the dependency disappears any components that depend on it will be deactivated automatically. Such a system will tend to automatically initialize and tear down components in the correct order.

The Service Layer provides an expressive tool for describing the aspects of a service through its service properties, see Service Properties, and for selecting and matching available services with the service filter, see Filters. Dependency injection frameworks, such as Declarative Services and CDI Integration, use the expressive nature of the service layer by allowing a target option for dependencies. The target specifies a filter that is used to assert the properties provided by a specific dependency.

The notion of a target for a dependency is very powerful and allows for additional control over when a component can be activated. With Declarative Services and CDI Integration, a dependency target can be specified via configuration. This gives the deployer of the system power to select specific services for dependencies and therefore control over what conditions are necessary for a component to be activated.

Translating ordering dependencies to service dependencies is often straightforward to do, but some scenarios make it more challenging. For example, a component may depend upon a system wide state in order to be fully functional. This type of problem can be common when using the whiteboard pattern. An example of a whiteboard pattern is the previously mentioned web server. A servlet implementation is only required to register itself as a Servlet service and that servlet can start receiving requests from the web server implementation. However in some scenarios, a deployer may want to ensure that one or more specific servlets are registered before allowing the web server to begin processing requests. By default the web server does not need any servlets to be active, but a deployer may want to ensure at least one servlet is available. For this example, a deployer wants both Servlet 1 and Servlet 2 to be available.

Figure 59.1 Service Activation with a normal Whiteboard

Service Activation with a normal Whiteboard

Using Declarative Services, one could incorrectly try the following to achieve this:

// THIS WILL NEVER WORK
@Reference(target="(&(servlet=1)(servlet=2))")
volatile List<Servlet> servlets;

This does not work because no individual servlet service will satisfy both properties. The result is that the list of servlet services will remain empty for the system and the web server will not start. Condition services provide a mechanism for declaring and controlling what conditions are necessary to enable a component. For example, with the listener whiteboard implementation the following condition service requirement could be specified:

@Reference(target="(osgi.condition.id=true)")
Condition requiredCondition;

This component requires the True Condition which is always available at runtime. This allows the component to activate as soon as all of its other requirements are met. In addition, a deployer can now use configuration to change the target of the required condition. For example, the target could be changed to reference a condition that represents when all the servlets required by the deployer are available at runtime. For example, the following condition target could be used:

(osgi.condition.id=application)

Figure 59.2 Service Activation with Condition

Service Activation with Condition

Conditions can also be enabled based on the availability of other conditions. This allows for more powerful aggregation of conditions for a system.

The Condition that indicates that the servlets are ready could be implemented as follows:

@Component(property="osgi.condition.id=application")
public class ApplicationCondition implements Condition {
    @Reference(target="(servlet=1)")
    private Servlet servlet1;
    @Reference(target="(servlet=2)")
    private Servlet servlet2;
}

Please note, that the example Condition implementation above is just a simplified construct. When a service is registered, all service listeners are called in some sequence. This means, that the example Condition implementation above may observe the availability of a servlet service before other parties that are also interested in servlet services, such as the web server. Thus the registration of the Condition service should happen asynchronously, and perhaps even after a slight delay, so the framework has a chance to notify all service listeners regarding the relevant service.

59.2.1 True Condition

The Framework will always register a default True Condition that all bundles can rely on being always available. The default True Condition will be registered during Framework initialization as the Framework registers framework services. It is registered with the CONDITION_ID property set to the value of CONDITION_ID_TRUE.

59.3 Security

59.3.1 Conditions

A Condition service has no function outside of providing a marker service to indicate a particular state and is therefore not required to be a trusted service.

59.3.2 Minimum Implementation Permissions

To implement and register a Condition service, a bundle must have the following permissions.

PackagePermission[org.osgi.service.condition,IMPORT]
ServicePermission[org.osgi.service.condition.Condition, REGISTER ]

59.3.3 Minimum Using Permissions

No permissions are necessary to get a Condition service. Service Permission with the GET action for the Condition service must be granted by the framework, see Implied Permissions. Note that the org.osgi.service.condition package does not necessarily need to be imported for a bundle to be able to get a Condition service unless the bundle actually has a runtime reference to the Condition type.

59.4 org.osgi.service.condition

Version 1.0

Condition Service Package Version 1.0.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.

Example import for consumers using the API in this package:

Import-Package: org.osgi.service.condition; version="[1.0,2.0)"

Example import for providers implementing the API in this package:

Import-Package: org.osgi.service.condition; version="[1.0,1.1)"

59.4.1 Summary

59.4.2 public interface Condition

Condition Service interface.

In dynamic systems, such as OSGi, one of the more challenging problems can be to define when a system or part of it is ready to do work. The answer can change depending on the individual perspective. The developer of a web server might say, the system is ready when the server starts listening on port 80. An application developer however would define the system as ready when the database connection is up and all servlets are registered. Taking the application developers view, the web server should start listening on port 80 when the application is ready and not beforehand.

The Condition service interface is a marker interface designed to address this issue. Its role is to provide a dependency that can be tracked. It acts as a defined signal to other services.

A Condition service must be registered with the Condition.CONDITION_ID service property.

Thread-safe

59.4.2.1 public static final String CONDITION_ID = "osgi.condition.id"

Service property identifying a condition's unique identifier.

Since a Condition service can potentially describe more then one condition, the type of this service property is String+.

59.4.2.2 public static final String CONDITION_ID_TRUE = "true"

The unique identifier for the default True condition.

The default True condition is registered by the framework during framework initialization and therefore can always be relied upon.

Condition.CONDITION_ID

59.4.2.3 public static final Condition INSTANCE

A condition instance that can be used to register Condition services.

This can be helpful to avoid a bundle having to implement this interface to register a Condition service