I am working on a project using karaf 4.0.5, and osgi. We have client side code to invoke a REST API, which requires to load 3 "*.properties" files. I have been given a client jar that I'm using to invoke the server side classes and methods (containing code that I cannot update). The required property files are present in the provided client jar, but their code still doesn't locate and load them.
On debugging my pax exam I found the below possible reasons for it not loading resource files from the jar.
getResource()
" method instead of the "getResourceAsStream()
" method.Alternatively, I tried adding the resources to a directory on my file system, and appending the classpath with the directory's location, as in:
"-cp .;C:/Users/abcUser/Desktop/resourceFolder/;
"
(windows 7, classpath entry added as a VM argument while executing pax exam using junit 4+ from eclipse) -> this doesn't work either and its still unable to locate these files. What other options do I have so the Bundle Classloader locates these files?
Note: We already have a bunch of other *.cfg files whose contents are loaded into beans using blueprint and are registered in the containers, but that's not what I need to do here. During runtime, these files should be available to the BundleClassloader, and should be retrieved by the "getResource()" method.
Update: Following the below portion of the accepted answer, the properties files were successfully loaded by the application.
Another thing to check is whether the client code is actually using the bundle classloader when trying to load these resources. In some cases the code tries to be clever by using the Thread Context Classloader, which would need to be set appropriately before calling the client code.
The code from the client jar was exactly as guessed: the resource loading was happening using the Thread.currentThread().getContextClassLoader()
. I was able to set the ContextLoader
to the CustomAbstractProcessor
's classloader and it now loads the properties files from that bundle's classpath!
ClassLoader previousCL = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(CustomAbstractProcessor.class.getClassLoader());
try {
//REST call to server using classes and methods from provided client jar.
}
finally {
Thread.currentThread().setContextClassLoader(previousCL);
}
I have been given a client jar that I'm using to invoke the server side classes and methods (containing code that I cannot update). The required property files are present in the provided client jar, but their code still doesn't locate and load them.
If this client jar is running as an OSGi bundle then it should be able to find resources using its own class loader (the bundle class loader) if (and only if) the resources are on the bundle's classpath.
The default classpath for an OSGi bundle is .
i.e. the root of the bundle. This can be overridden using the Bundle-ClassPath
manifest header and used to one or more locations in the bundle.
foo.properties
and the file is at `/props/foo.properties'it calls the
getResource()
method instead of thegetResourceAsStream()
method.
getResourceAsStream()
is just a null-safe version of getResource().openStream()
.
What other options do I have so the Bundle Classloader locates these files?
Another thing to check is whether the client code is actually using the bundle classloader when trying to load these resources. In some cases the code tries to be clever by using the Thread Context Classloader, which would need to be set appropriately before calling the client code.