This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 423212 - Allow to inject OSGi Bundle and BundleContext
Summary: Allow to inject OSGi Bundle and BundleContext
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Runtime (show other bugs)
Version: 4.4   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: 4.4 M5   Edit
Assignee: Paul Webster CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 330866 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-12-04 13:25 EST by Markus Kuppe CLA
Modified: 2014-01-21 09:36 EST (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Kuppe CLA 2013-12-04 13:25:37 EST
Interaction with OSGi in e4 is cumbersome as one has to use

Bundle bundle = FrameworkUtil.getBundle(this.getClass());
BundleContext bundleContext = bundle.getBundleContext();

in order to get the BC for the current bundle. It would be much more convenient, if BC would be available via @Inject instead.
Comment 1 Paul Webster CLA 2013-12-04 13:34:12 EST
So something like an ExtendedObjectSupplier?

@Inject
@BundleContext
private BundleContext bundleContext;

Would you have enough information in the ExtendedObjectSupplier to do the FrameworkUtil.getBundle(classOfObjectBeingDIed)?

PW
Comment 2 Markus Kuppe CLA 2013-12-04 13:41:11 EST
One possible way to implement this, is to have the renderer add the corresponding BC to the model element's IEclipseContext when the renderer instantiates the Java class referenced by the model element.

Alternatively the BC could be looked up dynamically for each caller which unfortunately would have to be handled in org.eclipse.e4.core.internal.di.InjectorImpl. A context function does not have a reference to the caller.
Comment 3 Markus Kuppe CLA 2013-12-04 13:47:39 EST
A @BundleContext annotation looks rather redundant to me, because we do know the variable type already. The only advantage of @BundleContext would be if it takes the BSN as an argument and thus returns a more specific BC.
Comment 4 Paul Webster CLA 2013-12-04 13:51:28 EST
The answer is yes, ExtendedObjectSupplier can get the originating class: org.eclipse.e4.core.di.suppliers.IRequestor.getRequestingObjectClass()

PW
Comment 5 Markus Kuppe CLA 2013-12-04 14:00:43 EST
Sure, but that requires us to have a dedicated (and unelegant) annotation, doesn't it?
Comment 6 Paul Webster CLA 2013-12-04 14:02:03 EST
It's an extension on what can be injected, just like @Preference.  @BundleContext because that identifies it as an extension, but it can be something else.

It's not appropriate to put this onus on the Renderers, they really have nothing to do with it.

The parties involved at the class of the object being injected and the DI engine (because it's being injected).  ExtendedObjectSupplier is the logical place.

PW
Comment 7 Paul Webster CLA 2013-12-04 14:03:57 EST
Asking an IEclipseContext for a BundleContext (where that's an attribute of the requesting class, not an attribute of the runtime application) seems to be a misuse of the parties involved.  The annotations are not inelegant (or they all are, but that's a personal preference :-)

But the division of responsibilities bears out that it should go in the ExtendedObjectSupplier.

PW
Comment 8 Markus Kuppe CLA 2013-12-04 14:16:38 EST
@Preference does not compare to @BundleContext. The EOS of the former wouldn't know what to inject without the annotation telling it, while the latter use case does not need this information, it knows the type.

Anyway, I'm fine with the compromise. Do you want @BundleContext to go into org.eclipse.e4.core.di.extensions?
Comment 9 Paul Webster CLA 2013-12-04 14:22:01 EST
(In reply to Markus Kuppe from comment #8)
> Anyway, I'm fine with the compromise. Do you want @BundleContext to go into
> org.eclipse.e4.core.di.extensions?

Yes, I think that it's a reasonable low-level extension.

PW
Comment 10 Wim Jongman CLA 2013-12-04 15:14:03 EST
I don't want to spoil the party but trading a three liner for a two liner does not make much sense, boilerplate-wise. The BC is pretty much a singleton so there are no obvious re-injecting advantages. What if I want to get the BC of another class, do I go to FWUtil or do you see this specified in the annotation?
Comment 11 Paul Webster CLA 2013-12-04 15:22:23 EST
(In reply to Wim Jongman from comment #10)
> I don't want to spoil the party but trading a three liner for a two liner
> does not make much sense, boilerplate-wise. The BC is pretty much a
> singleton so there are no obvious re-injecting advantages. What if I want to
> get the BC of another class, do I go to FWUtil or do you see this specified
> in the annotation?

You'd probably have to go to FWUtil.  Whatever is an attribute on an annotation has to be decided at compile time, doesn't it?  And a class would be effected by where it's loaded from.

PW
Comment 12 Markus Kuppe CLA 2013-12-04 16:09:01 EST
(In reply to Wim Jongman from comment #10)
> I don't want to spoil the party but trading a three liner for a two liner
> does not make much sense, boilerplate-wise. The BC is pretty much a
> singleton so there are no obvious re-injecting advantages. What if I want to
> get the BC of another class, do I go to FWUtil or do you see this specified
> in the annotation?

That argument would apply to e.g. Shell as well. Also you can track the live cycle of the bundle, because there is no BC if a bundle is in the RESOLVED state.

Btw. when we name the annotation "BundleContext" consumers will have to full qualifier either the annotation or the type:

@BundleContext org.osgi.framework.BundleContext ctx
Comment 13 Paul Webster CLA 2013-12-04 16:12:12 EST
(In reply to Markus Kuppe from comment #12)
> Btw. when we name the annotation "BundleContext" consumers will have to full
> qualifier either the annotation or the type:
> 
> @BundleContext org.osgi.framework.BundleContext ctx

OK, perhaps we can pick another annotation :-)

PW
Comment 14 Markus Kuppe CLA 2013-12-04 17:18:44 EST
Here's a first stab at it https://git.eclipse.org/r/#/c/19342/ (with annotation still named BundleContext)
Comment 15 Markus Kuppe CLA 2013-12-10 09:12:45 EST
(In reply to Markus Kuppe from comment #14)
> Here's a first stab at it https://git.eclipse.org/r/#/c/19342/ (with
> annotation still named BundleContext)

Ping
Comment 16 Paul Webster CLA 2013-12-16 14:13:05 EST
Hi Markus, the initial implementation looks good.

Can you add a test in org.eclipse.e4.core.tests similar to org.eclipse.e4.core.internal.tests.di.extensions.InjectionPreferencesTest ?

PW
Comment 17 Markus Kuppe CLA 2013-12-17 07:20:52 EST
(In reply to Paul Webster from comment #16)
> Hi Markus, the initial implementation looks good.
> 
> Can you add a test in org.eclipse.e4.core.tests similar to
> org.eclipse.e4.core.internal.tests.di.extensions.InjectionPreferencesTest ?
> 
> PW

Pushed patch set #4 (ee144d28b2ff03ec2a4d1d81e3d0658b9d01d219) to gerrit.
Comment 18 Paul Webster CLA 2013-12-18 14:13:36 EST
Released as http://git.eclipse.org/c/platform/eclipse.platform.runtime.git/commit/?id=5131597f77f28f1bc65df79ea05c53160deb8e0a

Should we pick another name for @BundleContext?  I couldn't think of one off hand that was as simple as @Preference.

PW
Comment 19 Lars Vogel CLA 2013-12-18 14:27:30 EST
(In reply to Paul Webster fr
> Should we pick another name for @BundleContext?  I couldn't think of one off
> hand that was as simple as @Preference.
> 
> PW

@OSGiContext would be nicer IMHO and descriptive.
Comment 20 Paul Webster CLA 2013-12-18 14:29:04 EST
(In reply to Lars Vogel from comment #19)
> @OSGiContext would be nicer IMHO and descriptive.

I like this as well as it's descriptive and avoids the package collision.  What do you think Markus?

PW
Comment 21 Markus Kuppe CLA 2013-12-19 04:03:40 EST
(In reply to Paul Webster from comment #20)
> (In reply to Lars Vogel from comment #19)
> > @OSGiContext would be nicer IMHO and descriptive.
> 
> I like this as well as it's descriptive and avoids the package collision. 
> What do you think Markus?

In the interest of avoiding annotation proliferation I would be in favor
of a more generic @OSGi which later is used to also qualify things
like org.osgi.framework.Bundle and additionally be extended for use
cases outlined in:

http://www.eclipse.org/forums/index.php/t/446503/
http://www.eclipse.org/forums/index.php/mv/msg/369538/902803/#msg_902803
Comment 22 Lars Vogel CLA 2013-12-19 04:18:09 EST
(In reply to Markus Kuppe from comment #21)
> (In reply to Paul Webster from comment #20)
> > (In reply to Lars Vogel from comment #19)
> > > @OSGiContext would be nicer IMHO and descriptive.
> > 
> > I like this as well as it's descriptive and avoids the package collision. 
> > What do you think Markus?
> 
> In the interest of avoiding annotation proliferation I would be in favor
> of a more generic @OSGi which later is used to also qualify things
> like org.osgi.framework.Bundle and additionally be extended for use
> cases outlined in:
> 
> http://www.eclipse.org/forums/index.php/t/446503/
> http://www.eclipse.org/forums/index.php/mv/msg/369538/902803/#msg_902803

IMHO this, e.g. OSGi service lookup, could also be covered by @OSGiContext as the lookup would be in the context of OSGi. But @OSGi is also fine for me.
Comment 23 Paul Webster CLA 2013-12-19 10:50:13 EST
(In reply to Markus Kuppe from comment #21)
> 
> In the interest of avoiding annotation proliferation I would be in favor
> of a more generic @OSGi which later is used to also qualify things
> like org.osgi.framework.Bundle and additionally be extended for use
> cases outlined in:
> 
> http://www.eclipse.org/forums/index.php/t/446503/
> http://www.eclipse.org/forums/index.php/mv/msg/369538/902803/#msg_902803

Those are completely different usecases than this.

Here we're providing easy access to the BundleContext for the caller that's being injected.

That's not the same thing as modifying how the framework deals with OSGi services.  There's already an OSGi service injection framework that works with OSGi peculiarities - Declarative Services.

Searching up the IEclipseContext tree is not the high cost in accessing OSGi services through the Eclipse4 DI engine, believe me :-)

PW
Comment 24 Markus Kuppe CLA 2013-12-19 11:59:22 EST
(In reply to Paul Webster from comment #23)
> Those are completely different usecases than this.
> 
> Here we're providing easy access to the BundleContext for the caller that's
> being injected.
> 
> That's not the same thing as modifying how the framework deals with OSGi
> services.  There's already an OSGi service injection framework that works
> with OSGi peculiarities - Declarative Services.
> 
> Searching up the IEclipseContext tree is not the high cost in accessing OSGi
> services through the Eclipse4 DI engine, believe me :-)

I'm not saying that these use cases should be handled as part of this bug. I'm saying that "@OSGi" is forward looking and open in that it can be used for more than just this bug and that we should avoid ending up with an @OSGiContext, @OSGiFoo, @OSGiBar annotation just for ever use case that comes up. Other than that, I don't really care much except that @OSGi_CONTEXT_ is redundant to type Bundle_CONTEXT_.
Comment 25 Paul Webster CLA 2013-12-19 12:49:22 EST
(In reply to Markus Kuppe from comment #24)
> 
> I'm not saying that these use cases should be handled as part of this bug.
> I'm saying that "@OSGi" is forward looking and open in that it can be used
> for more than just this bug and that we should avoid ending up with an
> @OSGiContext, @OSGiFoo, @OSGiBar annotation just for ever use case that
> comes up. 

But so far I have this use case and another that's unrelated.  That they both have to do with OSGi isn't relevant to the API.

On top of that, our pattern is to switch on annotations.  Caring about parameters means that the annotation describes a sub-module (that has to make sense) and then it must switch on parameters to delegate the kind of behaviour (or be extensible itself).

I'd like to see something specific until it's time to introduce a new API that is a superset of the specific case, which can then be deprecated. I'm open to opening the API in Luna if we have a couple of usecases that demonstrate it's one API for some common functionality even if we don't get to it in Luna.

PW
Comment 26 Markus Kuppe CLA 2013-12-19 13:01:19 EST
(In reply to Paul Webster from comment #25)
> But so far I have this use case and another that's unrelated.  That they
> both have to do with OSGi isn't relevant to the API.
> 
> On top of that, our pattern is to switch on annotations.  Caring about
> parameters means that the annotation describes a sub-module (that has to
> make sense) and then it must switch on parameters to delegate the kind of
> behaviour (or be extensible itself).
> 
> I'd like to see something specific until it's time to introduce a new API
> that is a superset of the specific case, which can then be deprecated. I'm
> open to opening the API in Luna if we have a couple of usecases that
> demonstrate it's one API for some common functionality even if we don't get
> to it in Luna.

Well, this goes way beyond the scope of this bug, but anyway. Isn't this the road that leads to the rather complex 3.x API again?
Comment 27 Markus Kuppe CLA 2013-12-20 05:18:32 EST
https://git.eclipse.org/r/20098 changes the annotation name to "@OSGi". Patch set #2 introduces support for type org.osgi.framework.Bundle that has the added benefit that it is injectable even if the bundle's state is RESOLVED.
Comment 28 Paul Webster CLA 2013-12-20 10:00:01 EST
(In reply to Markus Kuppe from comment #27)
> https://git.eclipse.org/r/20098 changes the annotation name to "@OSGi".
> Patch set #2 introduces support for type org.osgi.framework.Bundle that has
> the added benefit that it is injectable even if the bundle's state is
> RESOLVED.

It makes sense that you can get Bundle or BundleContext.  Can we rename the annotation @OSGiBundle then?  OSGi is a little to general, and I wouldn't want to commit any other OSGi related things through this one object supplier.

PW
Comment 29 Markus Kuppe CLA 2013-12-23 16:48:49 EST
(In reply to Paul Webster from comment #28)
> (In reply to Markus Kuppe from comment #27)
> > https://git.eclipse.org/r/20098 changes the annotation name to "@OSGi".
> > Patch set #2 introduces support for type org.osgi.framework.Bundle that has
> > the added benefit that it is injectable even if the bundle's state is
> > RESOLVED.
> 
> It makes sense that you can get Bundle or BundleContext.  Can we rename the
> annotation @OSGiBundle then?  OSGi is a little to general, and I wouldn't
> want to commit any other OSGi related things through this one object
> supplier.

Over the last past days I have though about a third use case. Why not use @OSGiXXX to also implement the OSGi ServiceListener [1] similar to how @EventTopic implements the EventHandler (but without the IEventBroker wrapper)?

public void serviceListener(@OSGiXXX("event ldap filter") ServiceEvent) {
  // do foo
}


This allows for better integration with OSGi because it - contrary to IEclipseContext - supports injection of a service instance before it gets removed (instead of null) and additionally knows the concept of modify.

(FrameworkListener [2] naturally comes to mind as next step)

[1] http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/ServiceListener.html
[2] http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/FrameworkListener.html
Comment 30 Thomas Watson CLA 2014-01-09 10:37:17 EST
(In reply to Wim Jongman from comment #10)
> I don't want to spoil the party but trading a three liner for a two liner
> does not make much sense, boilerplate-wise. The BC is pretty much a
> singleton so there are no obvious re-injecting advantages. What if I want to
> get the BC of another class, do I go to FWUtil or do you see this specified
> in the annotation?

Are the components in e4 tied to the active lifecycle of the providing Bundle?
If the providing Bundle is stopped are the e4 injected components deactivated?

A BundleContext is a kind of singleton in that only one exists for a bundle while it is in the STARTING | ACTIVE | STOPPING state but a new BundleContext is created every time the bundle enters the STARTING state and that BundleContext is thrown away and never reused when the Bundle goes from STOPPING->RESOLVED (is stopped).  If e4 components outlive the STARTING | ACTIVE | STOPPING states of the providing bundle then the BundleContext they are injected with will become invalid if the providing bundle is stopped and restarted.
Comment 31 Markus Kuppe CLA 2014-01-09 10:53:55 EST
(In reply to Thomas Watson from comment #30)
> Are the components in e4 tied to the active lifecycle of the providing
> Bundle?
> If the providing Bundle is stopped are the e4 injected components
> deactivated?

The BundleContext does get un-injected if the bundle transitions into the resolved state. See the unit test InjectionOSGiTest#testUnInject [1].

[1] https://git.eclipse.org/r/#/c/20098/2/tests/org.eclipse.e4.core.tests/src/org/eclipse/e4/core/internal/tests/di/extensions/InjectionOSGiTest.java
Comment 32 Thomas Watson CLA 2014-01-09 12:37:58 EST
Sorry, I'm a bit out of my realm here but why is @OSGi annotation needed at all?  Why cannot the e4 DI handle this directly?

@Inject public BundleContext myContext;
Comment 33 Paul Webster CLA 2014-01-09 12:45:05 EST
@Inject BundleContext will search up the IEclipseContext chain for a BundleContext entry (there isn't one) and then hit the EclipseContextOSGi.  That one can't find BundleContext either, and it's not a service (and we don't want to return the workbench BundleContext) 

@Inject @<secondaryAnnotation> allows an ExtendedObjectSupplier to be consulted to return the object.  In this case, because the requester has the requesting class, it's easy to find the correct BundleContext.   @Inject @OSGi steps out of the regular lookup chain, the same way @Inject @Preference(*) does 

PW
Comment 34 Thomas Watson CLA 2014-01-09 17:07:24 EST
(In reply to Markus Kuppe from comment #29)
> Over the last past days I have though about a third use case. Why not use
> @OSGiXXX to also implement the OSGi ServiceListener [1] similar to how
> @EventTopic implements the EventHandler (but without the IEventBroker
> wrapper)?
> 
> public void serviceListener(@OSGiXXX("event ldap filter") ServiceEvent) {
>   // do foo
> }
> 
> 
> This allows for better integration with OSGi because it - contrary to
> IEclipseContext - supports injection of a service instance before it gets
> removed (instead of null) and additionally knows the concept of modify.
> 
> (FrameworkListener [2] naturally comes to mind as next step)
> 

I would prefer not to do this if we already support @EventTopic then why not just use the topics that give you access to the various events fired by the framework?

org/osgi/framework/FrameworkEvent/* (See Event Admin section 113.6.3)
org/osgi/framework/BundleEvent/* (See Event Admin section 113.6.4)
org/osgi/framework/ServiceEvent/* (See Event Admin section 113.6.5)
Comment 35 Lars Vogel CLA 2014-01-10 04:09:49 EST
(In reply to Thomas Watson from comment #34)

> I would prefer not to do this if we already support @EventTopic then why not
> just use the topics that give you access to the various events fired by the
> framework?
> 
> org/osgi/framework/FrameworkEvent/* (See Event Admin section 113.6.3)
> org/osgi/framework/BundleEvent/* (See Event Admin section 113.6.4)
> org/osgi/framework/ServiceEvent/* (See Event Admin section 113.6.5)

+1, sounds great and consistent.
Comment 36 Markus Kuppe CLA 2014-01-10 06:23:03 EST
(In reply to Thomas Watson from comment #34)
> I would prefer not to do this if we already support @EventTopic then why not
> just use the topics that give you access to the various events fired by the
> framework?
> 
> org/osgi/framework/FrameworkEvent/* (See Event Admin section 113.6.3)
> org/osgi/framework/BundleEvent/* (See Event Admin section 113.6.4)
> org/osgi/framework/ServiceEvent/* (See Event Admin section 113.6.5)

Hi Thomas,

I agree that @EventTopic is a viable alternative.

OTOH it behaves slightly different in that it sends the events asynchronously in a separate thread, whereas comment #29 delivers ServiceEvents synchronously [1]. Also I don't see how one can define an LDAP filter with @EventTopic to narrow the SEs down.

Third, IEventBroker nowhere explicitly states that it will forever be implemented on top of OSGi's EventAdmin. Thus, if IEB is backed by another broker impl, will it still deliver the org/osgi/* events? The only statement I could find about this is in https://bugs.eclipse.org/bugs/show_bug.cgi?id=288999#c29 from 2009.

[1] http://www.osgi.org/javadoc/r4v43/core/org/osgi/framework/ServiceListener.html
Comment 37 Thomas Watson CLA 2014-01-10 09:23:56 EST
(In reply to Markus Kuppe from comment #36)
> (In reply to Thomas Watson from comment #34)
> > I would prefer not to do this if we already support @EventTopic then why not
> > just use the topics that give you access to the various events fired by the
> > framework?
> > 
> > org/osgi/framework/FrameworkEvent/* (See Event Admin section 113.6.3)
> > org/osgi/framework/BundleEvent/* (See Event Admin section 113.6.4)
> > org/osgi/framework/ServiceEvent/* (See Event Admin section 113.6.5)
> 
> Hi Thomas,
> 
> I agree that @EventTopic is a viable alternative.
> 
> OTOH it behaves slightly different in that it sends the events
> asynchronously in a separate thread, whereas comment #29 delivers
> ServiceEvents synchronously [1].

I agree these are asynchronous, which reduces some of their usefulness for the UNREGISTERING service event.  But they are perfectly fine for FrameworkEvents which are always async and BundleEvents which are async to normal BundleListeners (they are sync for SynchronousBundleListeners).

But I question the usecase for receiving these events in a DI container.  Typical usecases would leave the event processing up to the DI container and have it inject the components appropriately as service events are sent to notify service object changes (at least this is what all other service component models do in OSGi that I am familiar with).  If you are actually going to react to the service events yourself then you are better off using a ServiceTracker against the BundleContext you are injected with.  Inventing another way to receive ServiceEvents does not seem that useful to me.

> Also I don't see how one can define an LDAP
> filter with @EventTopic to narrow the SEs down.

Sounds like a possible enhancement to EventTopic.  EventHandlers certainly can limit the events using a filter.  The org/osgi/framework/ServiceEvent/ events do include some interesting properties to filter on (like the objectName) but they do not include all the service properties from the service registration.

> 
> Third, IEventBroker nowhere explicitly states that it will forever be
> implemented on top of OSGi's EventAdmin. Thus, if IEB is backed by another
> broker impl, will it still deliver the org/osgi/* events? The only statement
> I could find about this is in
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=288999#c29 from 2009.

All of a sudden not firing events that used to be fired seems like a pretty big breaking change to me.  In some sense the topics are API themselves.  If we currently propagate EventAdmin Events then I think that behavior should be preserved as long as there is an EventAdmin implementation available in the system.
Comment 38 Paul Webster CLA 2014-01-10 09:41:39 EST
(In reply to Markus Kuppe from comment #27)
> https://git.eclipse.org/r/20098 changes the annotation name to "@OSGi".
> Patch set #2 introduces support for type org.osgi.framework.Bundle that has
> the added benefit that it is injectable even if the bundle's state is
> RESOLVED.

I'd like this changed to @OSGiBundle or @OSGiContext.  It's too general as is.  The events can be retrieved from the EventAdmin service (we can guarantee we'll propagate the events if necessary).  If we do need to add an @OSGiService annotation later, I prefer that to @OSGi(type="service"...) anyway, and having a separate annotation will lead to smaller EventObjectSuppliers that do the right thing.

PW
Comment 39 Markus Kuppe CLA 2014-01-13 06:13:44 EST
(In reply to Paul Webster from comment #38)
> I'd like this changed to @OSGiBundle or @OSGiContext.

Done with patch set #4 (https://git.eclipse.org/r/#/c/20098/)
Comment 40 Markus Kuppe CLA 2014-01-13 07:00:11 EST
https://git.eclipse.org/r/20565 is a proof-of-concept impl for ServiceEvent injection (no need to review, just wanted to save it somewhere).
Comment 41 Paul Webster CLA 2014-01-14 14:00:27 EST
(In reply to Markus Kuppe from comment #39)
> (In reply to Paul Webster from comment #38)
> > I'd like this changed to @OSGiBundle or @OSGiContext.
> 
> Done with patch set #4 (https://git.eclipse.org/r/#/c/20098/)

Released as http://git.eclipse.org/c/platform/eclipse.platform.runtime.git/commit/?id=a264facfd581f2b16f348d9247e94cb39c0b8e96

Thamks Markus.

PW
Comment 42 Lars Vogel CLA 2014-01-17 10:18:18 EST
*** Bug 330866 has been marked as a duplicate of this bug. ***
Comment 43 Lars Vogel CLA 2014-01-21 04:50:27 EST
Fails in I20140120-2000. How to reproduce:

1.) Create new e4 project with the wizard with sample content
2.) Add dependency to 
3.) Add field 

@Inject
@OSGiBundle
BundleContext ctx;

4.) Access it in postconstruct

@PostConstruct
	public void createComposite(Composite parent) {
		System.out.println(ctx);
}

Results in:


org.eclipse.e4.core.di.InjectionException: Unable to inject BundleContext: Testing bundle is not active or starting/stopping
	at org.eclipse.e4.core.di.internal.extensions.OSGiObjectSupplier.get(OSGiObjectSupplier.java:60)
	at org.eclipse.e4.core.internal.di.InjectorImpl.resolveArgs(InjectorImpl.java:455)
	at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:393)
	at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:108)
	at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(InjectorImpl.java:333)
	at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorImpl.java:254)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(ContextInjectionFactory.java:162)
	at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.createFromBundle(ReflectionContributionFactory.java:102)
	at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.doCreate(ReflectionContributionFactory.java:71)
	at org.eclipse.e4.ui.internal.workbench.ReflectionContributionFactory.create(ReflectionContributionFactory.java:53)
	at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.createWidget(ContributedPartRenderer.java:129)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createWidget(PartRenderingEngine.java:958)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:642)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:744)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:715)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:709)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:694)
	at org.eclipse.e4.ui.workbench.renderers.swt.StackRenderer.showTab(StackRenderer.java:1215)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:65)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler$1.run(UIEventHandler.java:41)
	at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:185)
	at org.eclipse.swt.widgets.Display.syncExec(Display.java:4545)
	at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:208)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38)
	at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
	at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135)
	at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
	at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
	at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:80)
	at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58)
	at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374)
	at org.eclipse.e4.ui.model.application.ui.impl.ElementContainerImpl.setSelectedElement(ElementContainerImpl.java:171)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.postProcess(LazyStackRenderer.java:101)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:658)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:744)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:715)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:709)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:694)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:67)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:654)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:744)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:715)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:709)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:694)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:67)
	at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveRenderer.processContents(PerspectiveRenderer.java:59)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:654)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:744)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:715)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:709)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:694)
	at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.showTab(PerspectiveStackRenderer.java:103)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer$1.handleEvent(LazyStackRenderer.java:65)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler$1.run(UIEventHandler.java:41)
	at org.eclipse.swt.widgets.Synchronizer.syncExec(Synchronizer.java:185)
	at org.eclipse.swt.widgets.Display.syncExec(Display.java:4545)
	at org.eclipse.e4.ui.internal.workbench.swt.E4Application$1.syncExec(E4Application.java:208)
	at org.eclipse.e4.ui.services.internal.events.UIEventHandler.handleEvent(UIEventHandler.java:38)
	at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197)
	at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
	at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135)
	at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
	at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
	at org.eclipse.e4.ui.services.internal.events.EventBroker.send(EventBroker.java:80)
	at org.eclipse.e4.ui.internal.workbench.UIEventPublisher.notifyChanged(UIEventPublisher.java:58)
	at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:374)
	at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:135)
	at org.eclipse.e4.ui.model.application.ui.advanced.impl.PerspectiveStackImpl.setSelectedElement(PerspectiveStackImpl.java:1)
	at org.eclipse.e4.ui.workbench.renderers.swt.LazyStackRenderer.postProcess(LazyStackRenderer.java:101)
	at org.eclipse.e4.ui.workbench.renderers.swt.PerspectiveStackRenderer.postProcess(PerspectiveStackRenderer.java:77)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:658)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:744)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:715)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:709)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:694)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.processContents(SWTPartRenderer.java:67)
	at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.processContents(WBWRenderer.java:639)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:654)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeCreateGui(PartRenderingEngine.java:744)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$2(PartRenderingEngine.java:715)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$7.run(PartRenderingEngine.java:709)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.createGui(PartRenderingEngine.java:694)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1047)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1006)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:146)
	at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:165)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:109)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:80)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:372)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:226)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:636)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:591)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1450)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1426)
Comment 44 Markus Kuppe CLA 2014-01-21 06:48:38 EST
(In reply to Lars Vogel from comment #43)
> Fails in I20140120-2000. How to reproduce:
> 
> 1.) Create new e4 project with the wizard with sample content
> 2.) Add dependency to 
> 3.) Add field 
> 
> @Inject
> @OSGiBundle
> BundleContext ctx;
> 
> 4.) Access it in postconstruct
> 
> @PostConstruct
> 	public void createComposite(Composite parent) {
> 		System.out.println(ctx);
> }
> 
> Results in:
> 
> 
> org.eclipse.e4.core.di.InjectionException: Unable to inject BundleContext:
> Testing bundle is not active or starting/stopping
> 	at

You don't say what state the "Testing" bundle is in? If it's only in RESOLVED state, you have to annotate BundleContext with @Optional obviously.
Comment 45 Lars Vogel CLA 2014-01-21 06:55:47 EST
(In reply to Markus Kuppe from comment #44)

> You don't say what state the "Testing" bundle is in? If it's only in
> RESOLVED state, you have to annotate BundleContext with @Optional obviously.

This bundle is the "main" UI bundle, i.e. the generated application plug-in. If the UI is constructed how can the bundle not being in state Active? I also tried with a handler (after the UI is created), injection it into the @Execute method and got the same error.
Comment 46 Markus Kuppe CLA 2014-01-21 07:12:20 EST
(In reply to Lars Vogel from comment #45)
> This bundle is the "main" UI bundle, i.e. the generated application plug-in.
> If the UI is constructed how can the bundle not being in state Active? I
> also tried with a handler (after the UI is created), injection it into the
> @Execute method and got the same error.

Please verify that your bundle is in ACTIVE/STARTING state. Just because it is the "main" UI bundle from the e4 perspective, it does not mean OSGi starts it for you.
Comment 47 Lars Vogel CLA 2014-01-21 07:22:10 EST
(In reply to Markus Kuppe from comment #46)

> Please verify that your bundle is in ACTIVE/STARTING state. Just because it
> is the "main" UI bundle from the e4 perspective, it does not mean OSGi
> starts it for you.

You are right, the plug-in is still in "RESOLVED" state. How can it not be ACTIVE, if the classes are used?
Comment 48 Markus Kuppe CLA 2014-01-21 07:28:26 EST
(In reply to Lars Vogel from comment #47)
> You are right, the plug-in is still in "RESOLVED" state. How can it not be
> ACTIVE, if the classes are used?

A bundle does not have to be in ACTIVE state in order for its classes to be available to consumers.

RESOLVED => Module layer/class access
ACTIVE => Service layer/service access
Comment 49 Lars Vogel CLA 2014-01-21 07:31:17 EST
(In reply to Markus Kuppe from comment #48)
> A bundle does not have to be in ACTIVE state in order for its classes to be
> available to consumers.
> 
> RESOLVED => Module layer/class access
> ACTIVE => Service layer/service access

Thanks for the clarification. If I try to inject the BundleContext should that not set the status to ACTIVE? Or what is the process to register a service via code if the bundle does not yet have an active service?
Comment 50 Markus Kuppe CLA 2014-01-21 07:48:00 EST
(In reply to Lars Vogel from comment #49)
> Thanks for the clarification. If I try to inject the BundleContext should
> that not set the status to ACTIVE?

No. If you want to explicitly start your bundle, inject the Bundle instead and call start() on it (better use some other mechanism though).

> Or what is the process to register a
> service via code if the bundle does not yet have an active service?

The purpose of injecting the BC is not solely to registering services. E.g. you might wish to register _synchronous_ listeners (see comment #36).
Comment 51 Wim Jongman CLA 2014-01-21 08:34:44 EST
(In reply to Lars Vogel from comment #47)
> (In reply to Markus Kuppe from comment #46)
> 
> > Please verify that your bundle is in ACTIVE/STARTING state. Just because it
> > is the "main" UI bundle from the e4 perspective, it does not mean OSGi
> > starts it for you.
> 
> You are right, the plug-in is still in "RESOLVED" state. How can it not be
> ACTIVE, if the classes are used?

If you want this you need to switch on lazy loading in the manifest.
Comment 52 Lars Vogel CLA 2014-01-21 08:40:07 EST
(In reply to Wim Jongman from comment #51)
> (In reply to Lars Vogel from comment #47)

> If you want this you need to switch on lazy loading in the manifest.

Thanks Markus and Wim for the clarification.
Comment 53 Lars Vogel CLA 2014-01-21 08:46:45 EST
Validated in I20140120-2000
Comment 54 Neil Bartlett CLA 2014-01-21 09:18:47 EST
I just want to point out that the code snippet in the very first comment of this thread is considered unsafe:

    FrameworkUtil.getBundle(this.getClass());


If your class is subclassed in another bundle, then "this.getClass()" will return the subclass, NOT the base class. Therefore the above snippet will return some other bundle, which is probably not what you are expecting. It's always best to use the class literal syntax, i.e.:

    FrameworkUtil.getBundle(MyClass.class);
Comment 55 Paul Webster CLA 2014-01-21 09:36:18 EST
(In reply to Neil Bartlett from comment #54)
> I just want to point out that the code snippet in the very first comment of
> this thread is considered unsafe:
> 
>     FrameworkUtil.getBundle(this.getClass());

Understood, and I agree.  In this case, though, it is a runtime object that want's the BundleContext of the bundle that defines its class.  If it were the subclass that's instantiated, then bundle that contributes the subclass is desired.

But that's probably something worth noting in the annotation javadoc.  I've opened Bug 426256

PW