Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 108214

Summary: need access to BundleContext without having activator
Product: [Eclipse Project] Equinox Reporter: Jeff McAffer <jeffmcaffer>
Component: FrameworkAssignee: equinox.framework-inbox <equinox.framework-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: bogofilter+eclipse.org, gunnar, Joel.Kamentz, ob1.eclipse, pascal, pvlei, simon_kaegi, sja.eclipse
Version: 3.2   
Target Milestone: 3.3   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Jeff McAffer CLA 2005-08-27 23:30:10 EDT
Right now if your code needs a BundleContext, you have to have an activator.  
This is the only place that you can get the context.  You then stash it and 
use it to register services etc.  The problem is, having an activator causes 
classloaders to be created.  if you don't have one then your bundle can be 
started with no cost.  if you have one but the class is in another bundle, 
that too avoids the classloader creation but is useless in terms of refernces 
to the context since there is no place for the start() method to put it that 
would not cause classloading.  Catch 22.

The reason this is interesting is that there are three reasons people have 
start() methdos
- get the context for future use.
- register a service or start a thread
- do something cause they think that their function is just so darn important 
their code must be run

I suspect that many (many) bundles are of the first kind.  So if you setup a 
framework to start all bundles on installation, all the bundles with 
activators are going to have their classloaders created and actually start 
loading classes.  This takes up alot of space.

What I'm thinking here is something like Bundle.getContext() where the method 
is spec'd only to return non null values if the method calling this method is 
defined in a class that is loaded by the receiver's classloader.  That is, the 
code really has to be from the bundle itself.
Comment 1 Thomas Watson CLA 2005-08-28 16:10:48 EDT
Some thoughts:

- Bundle#getContext() may not be very useful because the code would need to 
obtain its own bundle to get the context.  I realize there are 
Platform#getBundle methods but it would be nice to have a way without 
core.runtime.

- Currently in OSGi a BundleContext is not valid unless a bundle is in the 
STARTING/ACTIVE/STOPPING state.  A method for getting the bundle context must 
not return a context unless the bundle is in one of these states.

A good place for such a method would have been on the new 
org.osgi.framework.FrameworkUtil class.  We can certainly add it some place 
else until a later release of OSGi.  The method would look something like this.

public static BundleContext getContext(boolean activate)

It would return non-null values if the calling class was loaded by a bundle 
classloader and that bundle is in the STARTING/ACTIVE/STOPPING state.  Maybe 
it could take an argument to specify that if the bundle is in the RESOLVED 
state then attempt to start it; if successful then return the context 
otherwise return null.

This should be fairly easy to implement.  It would be similar to the 
implementation of ContextFinder when looking to find who is calling this 
method.
Comment 2 Jeff McAffer CLA 2005-08-28 21:16:36 EDT
Good points.  I'm not 100% sure this is needed but we should consider it as 
part of removing dependencies on eclipse-isms like AutoStart.
Comment 3 Thomas Watson CLA 2005-09-28 13:38:40 EDT
My current thinking is that we add a new class to the org.eclipse.osgi.util to 
add the new method for accessing the BundleContext.  Something like this:

public class FrameworkContext {
  public static BundleContext getBundleContext(boolean activate) 
    throws BundleException;
}

A BundleException could be thrown while attempting to activate a non-active 
bundle.

I'm not sure what to call this class.  I know it should not be FrameworkUtil 
or Framework because we already have classes with that name.
Comment 4 Jeff McAffer CLA 2005-10-04 10:20:36 EDT
ok.  Is there an existing class to which this method could be added?
Comment 5 Thomas Watson CLA 2005-10-25 16:05:58 EDT
Do we still need this?

Re comment 2:
> we should consider it as part of removing dependencies on eclipse-isms like 
> AutoStart.

But if we have bundles start calling this static method which is only 
available in equinox, is that not another containerism?
Comment 6 Jeff McAffer CLA 2005-10-25 17:02:37 EDT
Personally I think we still need this but perhaps we should work it through 
the OSGi spec process first.  The issue, as you point out, is that if we add 
it and lots of plugins use it (because it truly is convenient) then those 
bundles will only run on Equinox.  That would be counter productive.

Comment 7 Thomas Watson CLA 2006-04-10 15:09:48 EDT
This *really* is needed.  Eclipse-LazyStart has its limitations.

Consider a lazy-started bundle that needs a BundleContext.  Upon first classload it will obtain its BundleContext from its activator.start method.  Now imagine the bundle is small and every class from it gets loaded.  Then the bundle is stopped by someone.  The next time a class is used from the bundle it will not get restarted because every class from the bundle is already loaded and will fail because the BundleContext is invalid or null because the activator.stop method nulled the context out.

If there was a method like the one suggested in comment 1 then such a bundle could obtain the BundleContext and force itself to get restarted.
Comment 8 BJ Hargrave CLA 2006-04-10 15:27:54 EDT
Tom (or Jeff), why don't you open up an enhancement bug in the OSGi bugzilla system on this? I would like to see some DI technique used for this.
Comment 9 Thomas Watson CLA 2006-04-11 10:39:55 EDT
re comment 8

Sure, but can you elaborate on DI (Dependency Injection?) technique?

The usecase here is some code from a bundle is running on demand.  Imagine a library bundle (X) which exports a number of packages.  The bundle (X) will start in the RESOVLED state.  Some other bundle (Y) imports and starts using classes from bundle (X).  The classes in bundle (X) run into a situation where it needs the BundleContext.  At this point it would help if there was a facility that allowed for bundle (X) to request access to its BundleContext.  This facility would optionally start the bundle if it was not already ACTIVE.

This is similar to lazy-start but instead of being class load driven the control is completely handled by the bundle code as the BundleContext is needed.  I'm not sure how DI techniques can be used for this usecase.

See comment 1 for my initial suggestion for a FrameworkUtil method.
Comment 10 BJ Hargrave CLA 2006-04-11 11:25:54 EDT
(In reply to comment #9)
 I have no detailed thoughts yet, but the issue with the API is controling who can call it. BundleContext is a capability, this is why how SCR gets the BC for a bundle is "Magic (TM)" vs. some official API.

Having some DI technique ("Don't call me, I'll call you") where the framework injects the BC into the bundle would simplify thing because the framework would not have to figure out if the caller to some method is entitled to have the BC. (You could consider the BundleActivator to be a degenerate form of DI.)

More thinking needed here.... :-)
Comment 11 BJ Hargrave CLA 2007-03-02 19:30:13 EST
I think this can be closed since Equinox now implements the new OSGi 4.1 method: Bundle.getBundleContext.