| Summary: | OSGi integration story: injecting the proper bundle context | ||
|---|---|---|---|
| Product: | z_Archived | Reporter: | Simon Chemouil <eclipse> |
| Component: | E4 | Assignee: | Project Inbox <e4.runtime-inbox> |
| Status: | CLOSED DUPLICATE | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | bokowski, contact, eclipse, erdal.karaca.de, jawr, jeffmcaffer, john.arthorne, Lars.Vogel, ob1.eclipse, pwebster, tjwatson |
| Version: | unspecified | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| Whiteboard: | |||
|
Description
Simon Chemouil
This bug is step 1 for bug 330865 When I do talks on OSGi best practices the #1 is don't program OSGi API so I think making the use of BundleContext easier is a BAD thing. I would hope that the e4 programming model makes it largely irrelevant whether or not OSGi is being used. Perhaps some usecases or examples of when a BundleContext would be needed will help shed some light on the best way (or if at all) to make it available. (In reply to comment #2) > When I do talks on OSGi best practices the #1 is don't program OSGi API so I > think making the use of BundleContext easier is a BAD thing. I would hope that > the e4 programming model makes it largely irrelevant whether or not OSGi is > being used. Perhaps some usecases or examples of when a BundleContext would be > needed will help shed some light on the best way (or if at all) to make it > available. Okay, I believe there are two layers of "best practices". Best practices when programming against the OSGi API (don't pass references to services to another bundle, don't call the framework with a lock, avoid statics, etc), that I would call "OSGi best practices".. And best practices for a general point of view to avoid a dependence on OSGi and have thread-safe components when using a dynamic mode but that's more generally "program using POJOs" and this is also the mantra of E4 and other DI frameworks. Whether we like it or not, sometimes we're forced to program with the OSGi API. Two simple examples would be to have a service tracker with a customizer or a filter, which can't be done using E4's DI, or publishing an EventHandler with a dynamic topic (which can't be done using E4's DI either). As a framework, the Eclipse 4 Application Platform will only provide a subset of the capabilities of OSGi (through DI). In fact, that will itself be a subset of what DS provides. This is for several reasons that have been explained by mail on e4-dev@ but the gist is that some use cases don't make sense with E4 managed objects (for instance, large parts of the "static" DS 'mode' can't really work, e.g static 0..1 because we can't dispose & create the view again when an optional service goes). I have come across several patterns in DS when it's useful to get the BundleContext (or ComponentContext#getUsingBundle()) from the activate method. I have come across the very same situation while programming an E4 RCP application. Trust me that we do our best (and generally succeed) to avoid any dependency or programming directly against the OSGi API, but this is sometimes impossible. We need a way for powerusers to access interact with other bundles cleanly for those use cases that aren't supported by DI. Also we can't ask those users to change the way their services are accessed (publish them under different interfaces or whatever) because those services might come from 3rd party bundle. After a first discussion the decision was not to *change* E4's DI system on that regard (maybe add filtering/etc but it won't be dynamic so it won't ever be enough). We believe it addresses 90% use cases, just like DS address 95% uses cases. Having the proper BundleContext handy is just the first part of the next step which is to be able to register services on the proper bundlecontext. If we have it handy for that, we should also allow it to be injected. I've not been involved much in the e4 DI stuff so don't know all the ins and outs so take my comments as you choose. We are in agreement that sometimes there is the need to look under the covers. A simplistic view says that if lots of people need to look under the covers (e4 DI) then the covers are not doing their job and should be fixed. If few people need to look under, then tuck them in and make it hard to look under so people don't do so by accident or through laziness. (In reply to comment #4) > I've not been involved much in the e4 DI stuff so don't know all the ins and > outs so take my comments as you choose. > > We are in agreement that sometimes there is the need to look under the covers. > A simplistic view says that if lots of people need to look under the covers (e4 > DI) then the covers are not doing their job and should be fixed. If few people > need to look under, then tuck them in and make it hard to look under so people > don't do so by accident or through laziness. Ok, I'm not sure if I was clear on purpose here then ;). It would allow to get the proper BundleContext injected, for instance, the user would have to write: ----------------->8-------------------- @Inject BundleContext bundleContext; ----------------->8-------------------- in the fields or a maybe safer way ----------------->8-------------------- @PostConstruct public void activate(BundleContext bundleContext, SomeService service, MPart theActivePart) { // do something } ----------------->8-------------------- This second way is really similar to what we can do in DS and have the BundleContext or ComponentContext injected there but it's totally optional for users who need to tinker a bit. This is not something that happens unless the user wants it. E4's DI is really an implementation of JSR-330 so the behavior here is the same as with other DI frameworks that implement it such as Google Guice. This is step one of my "plan of action" because we need to bind the ServiceReferences to the proper BundleContext. That's step 2. Note that it is/will be still *immensely* easier to get an OSGi service completely transparently through injection, just ask for it and it's here. That covers most of the use cases for UI elements. But having the BundleContext handy also means we can give it to the users who want it, maybe they get it injected only in OSGi-dependant parts of their implementation, it's up to them to design appropriately if they don't want to be tied to the OSGi API too much. But for those who want it, it's far better than using a static method (even if we're just hiding it). A lot of RCP 3.x users resort to using FrameworkUtil#getBundle because of the lack of out-of-the-box integration between 3.x managed objects such as views and OSGi services. We could propose a cleaner approach here :). In an arbitrary place the bundle context can be obtained using this single line of code: BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext(); IMO, BundleContext should not be placed in the context as the context tree structure is ortogonal to bundles. (In reply to comment #6) > In an arbitrary place the bundle context can be obtained using this single line > of code: > > BundleContext context = FrameworkUtil.getBundle(getClass()).getBundleContext(); > > IMO, BundleContext should not be placed in the context as the context tree > structure is ortogonal to bundles. Hi Oleg, Thanks for your reply. Indeed, I forgot to add that line here as well, but in the linked bug, here's my original description and reason for opening this bug: > (1) Having a way to get the bundle context injected in user code (people > should not be forced to call FrameworkUtil#getBundle() or have an activator > with a static bundleContext reference) My reasons is to avoid forcing the users to use statics/singletons in their code, and *mostly* it doesn't 'feel' right when we have an injection framework. This is something we definitely missed when developing our RCP app with E4. As a temporary solution, we even created some injected objects in non-E4 managed bundles with a ContextInjectionFactory (so the context was not shared outside) and first thing we did was to put the BundleContext there :). I believe there were also talks in the OSGi Alliance of removing FrameworkUtil to allow nested framework instances (but that was in a draft). I do agree, though, that the BundleContext has no place in the context, but the injector can have other sources. Fixed with https://git.eclipse.org/c/platform/eclipse.platform.runtime.git/commit/?id=a264facfd581f2b16f348d9247e94cb39c0b8e96 *** This bug has been marked as a duplicate of bug 423212 *** |