Comments (1)
Comment author: Elias N Vasylenko <[email protected]>
Sometimes we need to publish (possibly interrelated) services according to patterns which are awkward or impossible to express in the current DS model. For example:
-
Register a set of services which expose different "views" of some underlying component, but which can't be implemented on the same instance.
-
For some service "B" which consumes a single instance of another service "A", dynamically register an instance of "B" for every available "A".
-
Register a non-interface-class service, where instances of the class can only be obtained via some API.
Typically this means leaving the safety and simplicity of DS and manually registering and unregistering services, and manually publishing the relevant capability information in the manifest.
I propose to introduce a mechanism for a "master" component to declaratively advertise "subordinate" components which the framework should register on its behalf. I'll describe the design space of the proposal in terms of service annotations rather than the component.xml
format as it's a little easier to visualise and discuss.
The means by which a master would advertise/expose subordinates would be via @ Component annotations on fields and methods. The SCR would register those fields, and the results of those methods, as components on behalf of the master. When the master component is activated or deactivated, so are its subordinates.
So in the following example, in which we have the interfaces ThingA
and ThingB
, we might expect the SCR to register the objects referenced by the fields a
and b
as services of the appropriate interface.
@ Component
class ThingManager {
@ Component
public final ThingA a;
@ Component
public final ThingB b;
@ Activate
public ThingManager( ... ) {
a = ... ;
b = ... ;
}
}
We can also imagine support for adding "field" and "method" targets to other service annotations so they can be applied to subordinate components.
Optionally we might also want to support exposing collections of subordinate services. In the following example, we might expect the SCR to behave similarly to as above, but to register each element of the collection returned by getThings
as a Thing
service.
@ Component
class ThingManager {
private Collection<Thing> things;
@ Activate
public void activate( ... ) {
things = Collections.unmodifiableSet( ... );
}
@ Component
public Collection<Thing> getThings() {
return things;
}
}
Here we simply have to trust that the referenced object of things
and its contents will not change once activate
is complete, as we have no way to verify this, much less to observe changes and react accordingly.
A limitation of exposing collections of subordinate services is that we can't specify different service properties for each element, which also means that the PID needs to be generated to make them unique.
Exposing dynamic subordinates is a little trickier. We might, for example, want to support a pattern where we expose a Derived
service for every instance of a Thingy
service.
@ Component
class ThingManager {
private final Map<Thingy, Derived> derivations = new HashMap<>();
@ Activate
public ThingManager(/* ... */) {
// ... init things ...
}
@ Reference(cardinality = MULTIPLE, policy = DYNAMIC)
public void addThingy(Thingy thingy) {
derivations.put(thingy, new DerivedImpl(thingy));
}
public void removeThingy(Thingy thingy) {
derivations.remove(thingy);
}
@ Component
Collection<Derived> getDerivations() {
return derivations.values();
}
}
In this case, the result of getDerivations
can change dynamically, and as before the SCR has no way of hooking into the implementation to figure out when results might change. However we can specify that every time a dynamic reference of a master component is changed, or the configuration of a master component is changed, all subordinate components are rechecked and registered/unregistered accordingly. This should capture most use-cases.
So for the above example, that would mean every time SCR calls addThingy
or removeThingy
it must also call getDerivations
and then unregister each Derived
that it previously registered on behalf of ThingManager
but is now missing, and register each new Derived
in the collection which has not previously been registered. We should compare Thingy
s by identity rather than equality here.
There would probably be various constraints on how the components could be configured.
For example on service scopes:
- Prototype-scope services should not be allowed to have subordinates, as there would be no way for consumers to bind to both the master and the subordinate.
- Subordinates which are fields should not have prototype scope as new ones can't be generated on demand.
- The service scope of a subordinate should not be "wider" than that of its master. For example a bundle-scoped master can expose prototype-scoped subordinates (on methods), as the framework can call the method each time a new instance of the subordinate service is required by a component within the same bundle. But a bundle-scoped master cannot expose singleton-scoped subordinates, as there is no sensible way to select a master within the global singleton scope.
Just a suggestion. It's something that I've felt is missing a few times when working with OSGi, and I'd be happy to give a few less abstract examples of use-cases if it'd help. I think probably every single time I've had to manually register services in a BundleContext
, I could have achieved the same thing more easily with a simply declarative system like this.
from design.
Related Issues (20)
- Ordering issue with RFC-217 "osgi.jaxrs.filter.base" filters HOT 2
- rfc-217 should clarify how ApplicationPath annotation can affect the base path HOT 1
- RFC-217 support for Feature, DynamicFeature, ContextResolver and other providers HOT 3
- RFC-221 Transaction control: Release resources managed by JDBCConnectionProvider HOT 4
- Typos in RFC 221 Transaction Control - Drafs HOT 1
- RFC-229 MQTT Wildcard topics HOT 2
- [Converter] Conversion of Collections HOT 2
- R7 Core draft 2017-3, 10.8.4.3 (Capability and Requirement version params) HOT 2
- Configurer specification - partial configurations and merging (R8+) HOT 2
- Feature: support Optional<T> for DS service reference type HOT 3
- [RFC 216/ PushStream] Inconsistency between JavaDoc/Spec Section 706.7.14.6 and the reference implementation HOT 1
- [RFC 216/ PushStream] Inconsistent time unit of PushbackPolicyOption.getPolicy() between JavaDoc and implementation HOT 4
- rfc-241 (Feature) - json structure and comment HOT 4
- Offer BundleContext#registerService without HashTable HOT 4
- [JPA Service] allow a JPA Service to use the (non-)jta-data-source attribute instead of the javax.persistence.jdbc.driver property HOT 1
- DS 1.4 Component Property Types: Allow meta annotations or static fields for generating constant component properties HOT 3
- DS 1.4 Component Property Type Annotations: Allow elements which only optionally create component properties HOT 1
- DS: Allow a condition towards a framework property HOT 3
- DS: Allow conditions for a class being available to the classloader HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from design.