OSGi R7 made developing Applications with OSGi very
convenient. It supports complex applications, to become easier manageable and
allows for a structure every developer can keep track of. It is furthermore a
great Framework to avoid unnecessary complexity, even though it cannot totally
prevent it in large applications.
Using services, either with DS and/or CDI, naturally leads to dependent services, which both models can handle conveniently and transparently. A developer can define mandatory services that need to be injected and/or filter for what kind of service he desires. This makes sure that services are available and activated, only if their preconditions are met. The system is not without limits though and the Condition Service is a supplement for such situations.
Using services, either with DS and/or CDI, naturally leads to dependent services, which both models can handle conveniently and transparently. A developer can define mandatory services that need to be injected and/or filter for what kind of service he desires. This makes sure that services are available and activated, only if their preconditions are met. The system is not without limits though and the Condition Service is a supplement for such situations.
What are the Use Cases?
Indirect Preconditions
As an example: The whiteboard is one
of the most powerful concepts OSGi allows, but it can be a double-edged sword.
At development time, it is great to write a whiteboard that works, if none or
numerous participants are available. Usually, at startup, you will find yourself
in a situation, where you want a whiteboard to be available to you, only if it
is already populated with certain services.
Service Not Available
OSGi allows you to tell a component to
become active only if certain required services are available. It is, however,
not possible to have an active service, as long as one of its required services
is not available. Take the example of a Web-Application, that mainly depends on
an external component. As long as this component is not available, you might
want to have a registered servlet that responds to every request with
“Service temporarily not available”, but goes away the moment the component
becomes available.
Configure a Component to activate only if service A and B are Available
Imagine a configurable service, that
provides access to billing providers like Credit, Debit and PayPal, where every
individual billing provider is a service by itself. At the moment it is not
possible to create such a service via ConfigAdmin, that only becomes active if
e.g., the Credit and Debit provider is available, without writing a lot of OSGi
specific custom code to the component.
Condition Service to the Rescue!
What is a Condition?
In OSGi, a Condition is simply
a component, that registers the marker interface org.osgi.service.condition.Condition. DS and CDI
will soon have an implicit mandatory reference on every component that can be
directed against any condition you like. Thus a component will only become
active if such a condition is available. The framework itself will conveniently
provide a default TRUE-Condition service registration, DS and CDI use as
default. Thus no action is needed if you do not desire to utilize
conditions.
How can I modify this Condition?
Via Annotation
How can I modify this Condition?
Via Annotation
OSGi will provide a convenient
component property annotation to set your own target filter to the default
condition.
Via ConfigAdmin
You can use the ConfigAdmin to modify
the default condition after the fact by addressing it via the osgi.condition.target property and
supplying a valid filter.
How Can I Create a Condition?
There are two main possibilities. A
developer can simply register any service exposing the org.osgi.service.condition.Condition
interface.
Here you have everything in your own hand.
The other possibility is the usage of
the ConditionFactory. This will be a configurable component, that can be
addressed via ConfigAdmin to register a condition if certain filters
apply.
An example could look like the following Configurator JSON:
{
":configurator:resource-version": 1,
"osgi.condition.factory~test" : {
"osgi.condition.identifier" : "resulting.condition.id",
"osgi.condition.properties.custom.condition.prop" : "my.property",
"osgi.condition.match.all" : [
"(&(objectClass=org.foo.Bar)(my.prop=foo))",
"(my.prop=bar)"
],
"osgi.condition.match.none" : [
"(&(objectClass=org.foo.Fizz)(my.prop=buzz))"
]
}
}
This configuration defines three
preconditions where both of the "osgi.condition.match.all"
filters
must find a service and no service must be available that matches "osgi.condition.match.none". If this is
the case, the ConditionFactory registers a condition service, with the
properties:
"osgi.condition.id" : "resulting.condition.id",
"custom.condition.prop" : "my.property"
The moment services come and go and
violate the configured preconditions the condition will be unregistered and all
the dependent components will be deactivated.
Conclusion
Usually, OSGi bundles and services
have no preset starting order, because the system can figure this out by
itself. For quite some time now, this is a contested and discussed issue in the
community, because there are a couple of valid cases where the system needs
hints and help to figure out the right starting order. The condition service
will be a great step here, by providing missing information to the
system.Conclusion