Loading resources with context loader fails with NullPointerException

I'm just wondering why I can't load a resource using the thread context loader in Felix OSGi? I shouldn't touch the context loader, am I doing something wrong or is this a bug?

I have a super simple kit with a simple activator:

public class Activator implements BundleActivator {
    public void start(BundleContext context) throws Exception {
        System.out.println("Hello World!!");
        String resourcePath = "META-INF/mySuperDuperResource.txt";

        // works
        System.out.println(Activator.class.getClassLoader().getResource(resourcePath));
        // null-pointer exception
        System.out.println(Thread.currentThread().getContextClassLoader().getResource(resourcePath));

    }
    public void stop(BundleContext context) throws Exception {
        System.out.println("Goodbye World!!");
    }
}

      

Now load the resource using the class loader using Activator.class.getClassLoader. But not with Thread.currentThread (). GetContextClassLoader (). There I get:

ERROR: Bundle info.gamlor.osgi [26] Unable to get module class path. (java.lang.NullPointerException)
java.lang.NullPointerException
        at org.apache.felix.framework.BundleRevisionImpl.calculateContentPath(BundleRevisionImpl.java:410)
        at org.apache.felix.framework.BundleRevisionImpl.initializeContentPath(BundleRevisionImpl.java:347)
        at org.apache.felix.framework.BundleRevisionImpl.getContentPath(BundleRevisionImpl.java:333)
        at org.apache.felix.framework.BundleRevisionImpl.getResourceLocal(BundleRevisionImpl.java:472)
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432)
        at org.apache.felix.framework.BundleWiringImpl.getResourceByDelegation(BundleWiringImpl.java:1360)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.getResource(BundleWiringImpl.java:2256)
        at info.gamlor.osgi.Activator.start(Activator.java:23)
        at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
        ...
org.osgi.framework.BundleException: Activator start error in bundle info.gamlor.osgi [29].
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:2027)
        at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
        at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
        at org.apache.felix.gogo.command.Basic.start(Basic.java:729)
        ...
Caused by: java.lang.NullPointerException
        at org.apache.felix.framework.BundleRevisionImpl.getResourceLocal(BundleRevisionImpl.java:474)
        at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1432)
        at org.apache.felix.framework.BundleWiringImpl.getResourceByDelegation(BundleWiringImpl.java:1360)
        at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.getResource(BundleWiringImpl.java:2256)
        at info.gamlor.osgi.Activator.start(Activator.java:23)
        at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
        at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
        ... 32 more

      

Now, when you just set the thread context class loader, it works just fine:

Thread.currentThread().setContextClassLoader(Activator.class.getClassLoader());

      

But it has a hackish feel to it. This feeling will bite me later.

+3


source to share


1 answer


I'm not sure why you were surprised by this. The thread context class loader is by default set to this parent's class loader, which is set to the system class loader first. So, unless you are doing anything special, the classloader is the system classloader, which is not the same as your classloader, so it cannot find your resource.

I agree that installing a contextual classloader has a hackish feel to it, but some libraries require it. I would do something like:



ClassLoader previous = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
badlyBehavedLibraryCall();
Thread.currentThread().setContextClassLoader(previous);

      

+4


source







All Articles