39

Each bundle in my OSGi project has its own BundleActivator, which I think is normal. This gets passed the current BundleContext, which is useful to have around for getting service references and whatnot.

However, from classes in my bundle, how can I get the BundleContext? Assigning it to a public static field in the BundleActivator sucks and passing it around as an argument also sucks. Is there a more intelligent way?

Chin
  • 19,717
  • 37
  • 107
  • 164
xconspirisist
  • 1,451
  • 2
  • 13
  • 26
  • 1
    I second this: The default activator generated by the PDE is very questionable. I consider this a bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=392919 – oberlies Mar 05 '13 at 07:59

4 Answers4

55

You can use FrameworkUtil.getBundle(ClassFromBundle).getBundleContext().

See FrameworkUtil JavaDoc.

Community
  • 1
  • 1
Ivan Dubrov
  • 4,778
  • 2
  • 29
  • 41
  • 2
    Thank you, this technique is exactly what I was after. – xconspirisist Jun 30 '11 at 11:44
  • 2
    How is that better than a static variable in your Activator? Instead of your own class you now depend on a static framework method. This makes your code even harder to test. – Christian Schneider Feb 09 '15 at 12:49
  • 2
    It is not necessarily better, but 1. you don't have to write activator 2. you can get context of another bundle. In any case RaduK is correct about centralizing OSGi-specific code. – Ivan Dubrov Feb 10 '15 at 16:59
18

A good practice when developing OSGi bundles in my opinion is to try to write the OSGi related code as centralized as possible. This way, if you want to use your code in a non-OSGi environment, the migration effort is minimum.

Therefore, using static references or FrameworkUtil all over the place is not a good idea imho. Neither is using plain OSGi. Try to look at iPOJO or Declarative Services.

RaduK
  • 1,463
  • 10
  • 16
  • An insightful comment, thank you. I recognize that tightly integrating classes with OSGi is bad practice, but FrameworkUtil from the other response answered the question. Thanks also for the references to declarative services, I will read up on that too. – xconspirisist Jun 30 '11 at 11:45
14

Another alternative is to use Declarative Services, which allows you to receive the BundleContext into your activator method. For example, assuming you use the Bnd Annotations for DS:

@Activate
public void activate(BundleContext context) {
    // ...
}

However as RaduK said, it's much better if you can write the majority of your code in POJO style without using OSGi APIs such as BundleContext.

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77
  • The service activate method takes a ComponentContext not a BundleContext. You can however get the BundleContext from the ComponentContext. So you can store a copy of the bundleContext in the services class. Don't do this using a BundleActivator method, since the BundleActivator does not use the same instance as used when the service activate method is called assuming your using a singleton service (this will result in your saved bundleContext being null if you access it from the service instance ) – Tom Rutchik Jul 27 '19 at 01:00
  • 1
    @TomRutchik Activate can take either ComponentContext or BundleContext according to your needs. – Neil Bartlett Jul 29 '19 at 14:07
-4

There is no magic here. You need some way to provide the information to the other classes. So it is either available via the call stack or in some well known place (e.g. static).

BJ Hargrave
  • 9,324
  • 1
  • 19
  • 27