Skip to main content

[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




Back to the top