Export-Package from OSGi bundle with bundled jars - java

I need some help to access exported packages for an OSGi bundle.
I have a simple OSGi bundle jar which essentially bundles some other non-OSGi jars and exports their packages. This OSGi jar is structured like:
root/
lib/
mylib.jar
META-INF
MANIFEST.MF
It's MANIFEST.MF looks as below. The package mylib.mypackage is available in the bundled jar lib/mylib.jar.
Manifest-Version: 1.0
Bundle-Name: my.osgi.bundle
....
Bundle-ClassPath: .,lib/mylib.jar
Export-Package: mylib.mypackge
I need to access the package mylib.mypackage from a plain Java application. I have tried following construct by leveraging eclipse or equinox:
/*
the installBundle() is used to load the packages & packages from myosgi.jar
because it is not directly added to the class-path
*/
....
EclipseStarter.getSystemBundleContext().installBundle("file:<<path-to>>\\myosgi.jar");
EclipseStarter.run(null);
mylib.mypackge.MySampleClass obj = new mylib.mypackge.MySampleClass();
....
The myosgi.jar is NOT added to the classpath directly and installBundle() API above is intended for class loading for myosgi.jar. Adding myosgi.jar in classpath anyway does not resolve mylib.mypackge.
However the above line fails with error ClassNotFoundException / ClassDefNotFoundError for mylib.mypackge.MySampleClass.
I need some guidance for:
How can I access the classes from the packages from myosgi.jar in a plain Java application? I am fine with initiating an OSGi runtime codefully inside my application.
Is there any way to auto-test the myosgi.jar to check if the packages exported by this jar are getting correctly resolved (in an OSGi env)? I don't have access to maven, we use ant for our builds. I would prefer to have minimal dependencies on any 3rd party jars for testing purpose.
Thanks in advance.
Regards,
Gau

Related

RCP ClassNotFoundException with nested jars

I have an RCP application with the following setup:
my.plugin.jar
|-->META-INF
|-----MANIFEST.MF
|-->A1.jar
|-->A2.jar
|-->A_Dependencies.jar (Jar of jars)
|----->X1.jar,X2.jar,...Xn.jar
When I run it I get ClassNotFoundExceptions relating to the nested jars (X1.jar, X2.jar, etc...)
My Manifests contain (among other things) the following entries:
my.plugin.jar
Bundle-ClassPath: .,A1.jar,A2.jar,A_Dependencies.jar
A1.jar
Bundle-ClassPath: .,A_Dependencies.jar
A2.jar
Bundle-ClassPath: .,A1.jar
A_Dependencies.jar
Bundle-ClassPath: X1.jar, X2.jar,...Xn.jar
Export-Package: (All the appropriate packages)
How do I properly set up the manifest to resolve these? A sample error would look like:
Caused by: java.lang.ClassNotFoundException: some.package.some.classfile cannot be found by my.plugin
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:439)
OSGi bundles nested inside another bundle are just considered ordinary jar files. Their manifest will not be picked up, and hence Bundle-ClassPath will not work. If you want to deploy all jars inside one bundle (why not deploy all bundles separately?), you need to flatten the structure so that all your dependency jars are directly under your bundle, and added to the Bundle-ClassPath of your manifest:
my.plugin.jar
Bundle-ClassPath: .,A1.jar,A2.jar,X1.jar,...,Xn.jar
From the error message, it seems your are running Equinox. I'm more familiar with Felix, and the maven-bundle-plugin, which can be configured to embed dependencies and add them to the classpath. The bundles created by the plugin are not tied to Felix, so you could take a look at that instead of manually write bundle manifests.

Is it required to import transitive dependencies as bundles to KURA

I am very new to OSGI and KURA. I am tackling with a problem since yesterday and I did not understand its reason.
Please, tell me if my way is wrong.
I am using dropbox-core-sdk (version 3.0.0) in my project. I have downloaded its jar and also, I have researched that it has a dependency on jackson-core (version 2.7.4). I have also downloaded its jar and I have created a bundle with dropbox-core-sdk.jar and jackson-core.jar.
Firstly, I have imported the dependencies (bundle with dropbox and jackson) and then imported my own project.
When I start my project, it throws the following exception;
java.lang.NoClassDefFoundError: javax/net/ssl/HttpsURLConnection
at com.dropbox.core.http.StandardHttpRequestor.prepRequest(StandardHttpRequestor.java:196)
at com.dropbox.core.http.StandardHttpRequestor.startPost(StandardHttpRequestor.java:70)
at com.dropbox.core.http.StandardHttpRequestor.startPost(StandardHttpRequestor.java:28)
at com.dropbox.core.DbxRequestUtil.startPostRaw(DbxRequestUtil.java:232)
at com.dropbox.core.v2.DbxRawClientV2$1.execute(DbxRawClientV2.java:100)
at com.dropbox.core.v2.DbxRawClientV2.executeRetriable(DbxRawClientV2.java:256)
at com.dropbox.core.v2.DbxRawClientV2.rpcStyle(DbxRawClientV2.java:97)
at com.dropbox.core.v2.users.DbxUserUsersRequests.getCurrentAccount(DbxUserUsersRequests.java:120)
at org.eclipse.kura.example.hello_osgi.DropBoxTransfer.<init>(DropBoxTransfer.java:37)
at org.eclipse.kura.example.hello_osgi.DropBoxUpdateJob.execute(DropBoxUpdateJob.java:20)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
I have two related questions;
When we create a bundle from a public api, should this bundle contain the transitive dependencies of the public api?
Even if I supplied the Dropbox api with its transitive dependencies, why threw the program such an exception?
Typically NoClassDefFoundError happens when a bundle loads a class that is not present in the bundle and there is not Import-Package statement for the package of the class.
When creating bundles make sure you use a bnd to auto create the Manifest with suitable Import-Package and Export-Package instructions.
I would always use the build to create a bundle from a jar. As I use maven I would use a maven plugin. See this question for some possible ways to create bundles.

How to specify order of JAR class loading in weblogic

I have an EAR file that contains two different jars that share some classes with an identical package.class name. These JARs are deployed in my APP-INF/lib directory.
Let's say A jar contains the latest version of classes and B contains the old version of classes. When a class is referenced Weblogic looks first into B jar and loads the old version which break some functionality.
How can I tell Weblogic to load jar A before B from APP-INF/lib? I need to define a specific order to avoid loading old classes.
I have already tried adding A jar to <classloader-structure> in weblogic-application.xml like so:
EAR structure:
EAR
\--->A.jar
\--->webapp.war
.....
weblogic-application.xml:
<classloader-structure>
<module-ref>
<module-uri>A.jar</module-uri>
</module-ref>
.......
</classloader-structure>
but then it throws error saying
weblogic.management.DeploymentException: classloader-structure element in weblogic-application.xml is referencing the module-uri A.jar which does not exist in this application.
Also one thing to remember is that A.jar is not a module, war or EJB it just a plain hibernate library: hibernate-jpa-2.0-api-1.0.1.Final.jar
I am using Weblogic 12c version.
You need to set parent last strategy for class-loader, refer http://www.rgagnon.com/javadetails/java-0551.html, as i remember there is a GUI in weblogic server to do the same.

org.apache.sling.api.resource,version=[2.3,3) -- Cannot be resolved

Hi I am not able to access content of my project, I have uploaded all the packages which are required to access content from CQ. Only thing I can see is
org.apache.sling.api.resource,version=[2.3,3) -- Cannot be resolved
Can this be the reason for exception and if yes please let me know how to resolve it.
CQ version 5.6
The error message means that the OSGi framework is unable to supply a version >= 2.3 and < 3 of the org.apache.sling.api.resource Java package for a bundle B that wants to import it.
As a result, bundle B cannot be activated, and parts of your system won't work.
Looking at the webconsole (under /system/console by default in Sling and CQ) you can see that this package is provided by the org.apache.sling.api bundle, so either you have an old version of that bundle in your system, or you have installed incompatible bundles that require a newer version of that package.
You can add the missing package by explicilty importring it. Accecess the pom.xml file in the core folder of your project core/pom.xml and list the dependency under Import-Package
<configuration>
<bnd><![CDATA[
Import-Package:
javax.annotation;version=0.0.0,
org.apache.sling.api.servlets;version="[2.3,3)",*
]]></bnd>
</configuration>
Check version of org.apache.sling.api.resource in package-info.class file in org.apache.sling.api.resource package in uber-jar.
You might have version between 2.3 and 3. Try installing lower version uber-jar that has package version <2.3

component-scan classpath subdirectory (a'la plugins + annotation capable)

Goal:
List item
I have a spring webapp project, which is using component scan for configuration and autowiring interface implementation through maven submodules
the main project is dependant on the other modules thus the jar's of the submodules are placed in the /WEB-INF/lib folder
the submodules (aka plugins) have common package parent name x.y.z.extension eg. x.y.z.extension.pluginA
the classes in this package are annotated with #Component or #Configuration
in the servlet xml configuration i have placed such component-scan information:
Code:
<context:spring-configured />
<context:component-scan base-package="x.y.z.extension" />
With the mentioned configuration everything is working correctly.
What I would like to achieve:
List item
remove dependency of the main webapp maven module and other modules - the core webapp will be shipped without plugins
create subfolder e.g. "WEB-INF/classes/plugins" in the classpath classes dir
put there the mentioned jar's from submodules (or extract the jar content to eg. WEB-INF/classes/plugins/pluginA) - this could be done during "plugin installation" with webapp restart after new plugin installation
spring automagically should detect annotated classes and load it into the application context (and use not annotated classes in the plugin jar (annotated classes are mainly interface implementation but they are using some not annotated classes in the jar))
and ... of course this does not work The classes are not found.
If it possible to achieve this only using spring ecosystem, or should I take a look into other examples e.g. jspf ?
How can I modify classpath scanning with spring and also keep automatic component scanning ?
thanks !

Categories

Resources