[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [e4-dev] OSGi, Contexts and DI
|
Hi,
I think the discussion and comparison with DS is interesting even if our
approaches are different, because it allows us to see if we cover the
main use cases for consuming OSGi services transparently.
Even if we deal with them differently, those use cases make sense and it
would be nice to support them. I'll just sum them up, see how I
currently see things and why.
=======
(1) one service to be bound, static
(a) required: cardinality 1..1 (fail when building the component if
the required service cannot be bound)
(b) optional: cardinality 0..1 (don't fail when building the
component, but don't add a tracker either. If the service couldn't be
bound when we tried, we won't have it at any later point)
In my mind, this use case is really here for userfriendliness, it
restricts OSGi but it also removes a lot of tricky handling of dynamics
(as Oleg showed in his post)...
In fact, a lot of E4 code relies on the (1a) use case, with mandatory
services (like modeled workbench services, etc) that are expected to be
there and "fail if not". Most of all, this dumbed down approch doesn't
require the user to write specific code when the service is leaving (we
should still call @PreDestroy then dispose I guess?)
==> This is something people would like to have for simple service
binding. I think we need it to support, but what should we go when the
service leaves?
The (1b) use case, on the other hand, is really not that interesting in
practice. The few times I used this in DS, I expected it to behave like
dynamic or to create the component ONCE the dependencies were satisfied.
*Whether we decide to allow this use case or not is quite important,
because this is the behavior one could expect with @Optional*.
==> As I see it now, the only reason to support his is for the sake of
completeness. I'm not sure anyone would miss this because it can also be
simply emulated using dynamic 0..1 and ignoring calls after the first.
========
(2) one service to be bound, dynamic (then cardinality 1..1 doesn't make
sense, we want 0..1).
In this case, we have a bind and an unbind method (often named
setService(MyService ...) and unsetService(MyService ...)).
We already see that this is pattern won't be mapped with E4's DI,
because we don't have @Inject and @Uninject ;)
So, with one @Inject'ed method, to decide whether the service *arrived*
or *left* (or just *isn't there yet*), we somehow need null (or some
similar marker).
One way to deal with it would be to consider @Inject on OSGi services
*without* optional to behave like (1a) ... and adding @Optional would
behave like (2). (if we don't support 1b).
Then, users would have to write null-proof code with @Optional OSGi
services like they have with any other stuff with E4's DI.
==> We need this whether it's with @Optional or something else.
============
(3) many services to be bound (dynamic 0..n)
Once again, we don't have an "unset/remove" method. It seems to me that
the easiest approach is to provide the full Iterable<Service> set (not
Collection<> though, because Iterable<> is easier to wrap with other stuff).
==> This would be nice, but this is also the trickiest. In any case,
that would be something to implement when the rest (one service binding)
is done.
============
Also, while we're at it, something really cool with DS is the
possibility to get the service properties injected if the second
argument of the bind method is of class Map. It's really a powerful
feature that complements well the filtering at the component definition
level (using target in DS, and possibily annotations later with E4's DI).
I am not sure it would be possible to do in the current state of the
framework for single-service binding or with the @Inject approach, and
it would be even trickier if we pass an Iterable<> ...
In any case, it's obvious it's gonna be a bit difficult to have the full
scope of DS while still keeping same annotations and approach as E4's
DI. I believe the goal should be to cover those main usages and if
someone wants something special, they can get the BundleContext injected.
Oleg wrote:
> So, offhand, I know that I'd like the answer to be ("yes, dynamic"), but
> I am not sure if that turns out to be a practical answer.
>
> What do you think? If dynamic injection of OSGi services required adding
> "null" checks (even for non-optional services), would that be acceptable?
Oleg, did I understand here that you would want (2) to be the default
and only way to support OSGi services? I think that's what makes more
sense in OSGi programming, but maybe some people would find it too
cumbersome to null-check everytime. If we can find something clean to do
when the service leaves, I think we should still support (1a).
--
Simon
Gunnar Wagenknecht wrote:
Am 26.10.2010 18:23, schrieb Oleg Besedin:
What do you think? If dynamic injection of OSGi services required adding
"null" checks (even for non-optional services), would that be acceptable?
You made some really good points. I was thinking DS-like. Optional means
that something is either there or not. As a consumer, I must be aware of
this. This awareness could be indicated by using an @Optional/@Nullable
(whatever) annotation.
In terms of multiple option, the Collection<MyService> approach seems
interesting. DS does support add/remove methods. I'm not sure what the
@Inject/DI approach for this is/should be.
-Gunnar