Hi Folks,
in Fabric we have a service model whereby services have interdependencies, are
configurable and dynamic by nature - all of which is managed in OSGi with the
help of Declarative Services. To illustrate I use a simple example
ServiceT {
@Reference
ServiceA serviceA;
@Reference
ServiceB serviceB;
public doStuff() {
// that uses serviceA & serviceB
}
}
The injection is handled by the DS framework - there are various callbacks
involved.
Lets assume the system is fully configured and a client makes a call on ServiceT
ServiceT serviceT = getServiceT();
serviceT.doStuff();
Due to the dynamic nature of OSGi services and their respective configuration
ServiceT must deal with the following possible/likely situations
#1 An instance of a referenced service is not available at the point of access
(i.e. serviceA is null)
#2 In the context of a single call the service instance may change (i.e. call
may span multiple instances of serviceA)
#3 In the context of a single call the configuration of a service instance may
change (i.e. serviceA is not immutable, sequential operations on A may access
different configurations)
In OSGi there is no notion of global lock for service/configurations nor a
notion of lock of a given set of services/configurations - I cannot do
lock(T, A, B);
try {
ServiceT serviceT = getServiceT();
serviceT.doStuff();
} finally {
unlock(T, A, B);
}
This code is also flawed because it assumes that the caller of doStuff() is
aware of the transitive set of services involved in the call and that this set
will not change.
As a conclusion we can say that the behaviour of doStuff() is only defined when
we assume stability in service availability and their respective configuration,
which happens to be true most of the time - nevertheless, there are no
guarantees for defined behaviour.
How about this …
The functionality of A and B and its respective configuration is decoupled from
OSGi and its dynamicity
A {
final Map config;
public doStuffInA() {
}
}
B {
final Map config;
public doStuffInB() {
}
}
ServiceA and ServiceB are providers of immutable instances of A and B
respectively. There is a notion of CallContext that provides an idempotent set
of instances involved in the call.
CallContext {
public T get(Class<T> type);
}
This guarantees that throughout the duration of a call we always access the
same instance, which itself is immutable. CallContext also takes care of
instance availability and may have appropriate timeouts if a given instance
type cannot be provided. It would still be the responsibility of A/B to decide
wether an operation is permissible on stale configuration.
Changes to the system would be non-trival and before I do any prototyping I'd
like to hear what you think.
cheers
--thomas
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev