Search code examples
javaosgiapache-felixosgi-bundle

NPE thrown after getting BundleContext from FrameworkUtil class


I was following this tutorial to embed OSGi in my maven based application. I have one class file that creates and start the framework as mentioned here and it works fine there as I am able to get BundleContext easily.

I have added this dependency in my pom.xml file.

    <dependency>
        <groupId>org.apache.felix</groupId>
        <artifactId>org.apache.felix.framework</artifactId>
        <version>4.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.ops4j.pax.url</groupId>
        <artifactId>pax-url-mvn</artifactId>
        <version>1.3.6</version>
    </dependency>

Now when I am running my whole framework and when it reaches to one of my new class file in the same maven based project where I need to use BundleContext so I thought I can use this piece of code to get the BundleContext`

FrameworkUtil.getBundle(ModelProcessor.class).getBundleContext();

but somehow the above code throws me NullPointerException and then I tried printing out to see what's happening-

System.out.println(FrameworkUtil.getBundle(ModelProcessor.class));

So the above lines prints- null

Does anyone have any idea what does null means here in terms of OSGi and what I can do to resolve this issue?

Thanks for the help.


Solution

  • ModelProcessor class is not loaded by OSGi classloader but by the Classloader of the main application (that embeds the OSGi framework). If you do the following you will see which classloader loaded the class:

    System.out.println(ModelProcessor.class.getClassLoader().toString());
    

    If you want to use the ModelProcessor class inside OSGi you should place it into a bundle and install it into the OSGi container.

    Your next question would be probably: how to access classes from the main application that are in bundles in the OSGi container?

    I do not know the answer without trying it but I have some guesses:

    • I guess that a class or interface that is in the classpath of the main project (that embeds the OSGi container) will be on the boot classpath of the embedded OSGi container
    • If my first guess is true you should take an interface into the main project and take an implementation of that interface into that bundle. You can instantiate the implementation in the Activator of the bundle and register it as a service
    • In the main application you will be able to access the registered service based on the interface via the bundle context of the installed bundle (or the via the framework bundle context)

    Till now this way the cause. Now if you need that bundle you can get it via the framework object. The framework object itself is a bundle as well. It has a bundleContext also. You can get your bundle based on the location value. The location identifies each bundle and you know the location of your bundle as you installed it :). If you do not know the location, you have to iterate through the bundles and check their symbolic names.