OSGi Bundle getting Loaded through another bundle - osgi

I am having an issue where one of my bundles is getting loaded through another bundle even when the two don't have any direct dependency on each other. Here's the scenario.
I have 3 bundles. Bundle A, B & C. The process flow is A->B->C. Hence there is no dependency between A & C.
When I deploy these 3, then for some reason bundle C is loaded through bundle A. I am using Jboss Fuse and through the karaf console, when I execute dev:show-tree on bundle A, it shows bundle C wired into bundle A.
If I remove bundle A, bundle C gets loaded on its own and I don't get any errors either.
I have inspected the features.xml file and pom for both A & C to see if they have any dependency whatsoever, but could not find anything.
Does anyone have any ideas on what else I could try or is there something that I am missing ?

Perhaps you have an optional Import-Package in bundle A that is exported by bundle C. Take a look at package:exports and bundle:headers.

Looks like pure case of Transitive dependencies. From the OSGI in action book's "2.5.3 Code visibility" section, here is the definition of Transitive dependency.
"Transitive dependencies occur when bundle A depends on packages
from bundle B and bundle B in turn depends on packages from bundle C. To use
bundle A, you need to resolve the dependencies of both bundle B and bundle C."
There might be possibility of your bundle A exposing a package of higher version than the one present in its absence which is used by bundle C.
Regards,
Gopal

Related

How to update a bundle from Maven artifact with running Apache Felix

Currently I have a situation, where I develop a project, then run mvn install and it get's put into my local Maven repository as a simple JAR file
Then, I have a crafted by some other guys "environment" which includes a whole lot of bundles and stuff, and is ultimately run via mvn pax:run and it takes like 5 minutes to run
I would like to be able to just run felix:update <bundle-name> but I cannot fill the gap between a Maven JAR artifact in local Maven repo, and a ready-for-provisioning bundle that I could put somewhere to just run felix:update or whatever, maybe uninstall/install
When I try to run mvn pax:create-bundle with my project, it throws a Containing project does not have packaging type 'pom' exception
Any help is highly appreciated
UPDATE: I've noticed that problems with re-installed bundle begin in it's activator, with a ClassNotFoundException (although the class mentioned is and always present in the bundle, so it must an issue with classpath, ClassLoader setup or whatever)
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation BundleWiringImpl.java:1574 at org.apache.felix.framework.BundleWiringImpl.access$400 BundleWiringImpl.java:79 at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass BundleWiringImpl.java:2018 at java.lang.ClassLoader.loadClass ClassLoader.java:357 at some.external.adapters.package.guice.SomeModule.configure SomeModule.java:46 at com.google.inject.AbstractModule.configure AbstractModule.java:59
If you have a path to a file which is the newly built bundle, you can update it from the Gogo shell as follows:
felix:update <bundleid> file:/path/to/file
refresh
Where <bundleid> is the numeric ID of the bundle that you want to update. The refresh command is needed in case any bundles depend on or import packages from the bundle you are updating; this command will cause the Framework to attempt to re-resolve them using the new dependency.
I am happy to accept #neil-bartlett's answer, though I have to add some more context:
1) one of the biggest issues I had initially is that a JAR-file in local Maven repo IS NOT THE SAME as an OSGi bundle. In order to create bundle, I had to run mvn bundle:bundle AFTER mvn install. And the bundle got created in target/ folder.
2) afterwards, in a GoGo shell, I could indeed run felix:update <bundle-id> file:C:/Users/blablabla/bundle-SNAPSHOT-2.0.jar, and for some reasons, these days it just works. The exceptions, mentioned in updates to original post, are indeed occurring, but they do not prevent proper installation of an updated bundle.

Unable to auto-deploy bundle to Karaf

I am developing an OSGI-based application, which deploys to Karaf container. Karaf has an auto-deployment feature, whereby copying a bundle to its karaf/deploy directory should automatically deploy that bundle into the container. More often than not, however, I am getting errors similar to the one below when I copy bundles into the deploy directory:
org.osgi.framework.BundleException: Bundle symbolic name and version are not unique: legacy-services-impl:8.0.0.ALPHA-SPRINT9-SNAPSHOT
at org.apache.felix.framework.BundleImpl.createRevision(BundleImpl.java:1225)
at org.apache.felix.framework.BundleImpl.<init>(BundleImpl.java:95)
at org.apache.felix.framework.Felix.installBundle(Felix.java:2979)
at org.apache.felix.framework.BundleContextImpl.installBundle(BundleContextImpl.java:165)
at org.apache.felix.fileinstall.internal.DirectoryWatcher.installOrUpdateBundle(DirectoryWatcher.java:1030)[6:org.apache.felix.fileinstall:3.3.11.fuse-71-047]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.install(DirectoryWatcher.java:944)[6:org.apache.felix.fileinstall:3.3.11.fuse-71-047]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.install(DirectoryWatcher.java:857)[6:org.apache.felix.fileinstall:3.3.11.fuse-71-047]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:483)[6:org.apache.felix.fileinstall:3.3.11.fuse-71-047]
at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:291)[6:org.apache.felix.fileinstall:3.3.11.fuse-71-047]
Instead of redeploying an already deployed bundle, the container tells me that I am trying to deploy a duplicate bundle.
The Karaf indeed has that bundle deployed, but why wouldn't it redeploy the bundle? What is causing this behavior? How to avoid such errors on auto-deploy?
Thank you,
Michael
I suspect that your bundle does not stop correctly. That may be the reason why karaf thinks it is still there. Do you have some code in your activator that is executed when stopping? Perhaps you are also running some threads. You should make sure the stop method of your activator works and cleanly closes all resources and stops all threads of your bundle.

How Apache Karaf sorts bundles to install and start?

I have defined four bundles:
bundle 1 : export package x version 1
bundle 2 : import package x ver [1,2] and export package y;y uses x
bundle 3 : export package x version 2
bundle 4 : import package y and also import package x version 2
Using apache felix (distribuable binary), I found that I should manually impose to not resolve (or start) the bundle 1 and then bundle 2 before starting the bundle 3 (otherwise a uses constraint problem appears because bundle 2 will use package x version 1 and in bundle 4 will appear package x version 1 and version 2 --> uses constraint violation).
Thanks to the authors of these posts:
http://njbartlett.name/2011/02/09/uses-constraints.html
http://blog.springsource.com/2008/10/20/understanding-the-osgi-uses-directive/
I don't like to impose order to my bundles, I need to copy all my bundles in the /bundle directory and then the instance of framework install and start them.
I noticed that Apache felix sorts the bundles to be installed alphabetically (so bundle 1 will be installed and then started the first).
I tried with Apache karaf, I copied my bundles into /deploy and I found that the problem disappears, so my question is:
Does Apache Karaf, (or felix file install) apply a strategy to impose any order for starting bundles in order to avoid these kind of problems ?
You should try to use a Karaf feature for this kind of deployment. You create a feature file with one feature in it and add all the bundles to this feature. Karaf will then load all the bundles and resolve and start them in one pass. So the resolver should bee able to correctly resolve all your bundles.
Apache Karaf does automatically add a startlevel to the bundles in the deploy folder this is configurable. The default of it is 50. So all your custom bundles are installed as StartLevel 50. This also makes sure the basic bundles of karaf itself are already up and running, especially the file-installer bundle.
Felix FileInstall does not have any ordering capability.
Start order isn't really important (bundles should be able to be started in any order), but a good Management Agent should be able to install and resolve a batch of bundles as a single operation. However FileInstall installs/resolves/starts bundles whenever it happens to poll the filesystem directory. Therefore FileInstall is not really usable for production deployment.
I don't know anything about Karaf, but any management agent that simply polls a directory is likely to have the same problem.

Check whether a file is an OSGi bundle (and find the bundle name) without installing it in the OSGi framework

Is it possible? Or do I have to try to install it?
I'll assume you're talking about OSGi Release 4, since in OSGi Release 3 and earlier any valid JAR file was also a valid OSGi bundle.
Simply read the JAR's manifest using the standard Java APIs in the java.util.jar package. The minimum headers required to be a valid R4 bundle are:
Bundle-ManifestVersion: 2
Bundle-SymbolicName: ...
As BJ points out, the "id" of the bundle is assigned when it is installed, but what many people take to be the "id" is actually the Bundle Symbolic Name.
You can check for the Bundle-Name, or a host of Bunde-XXX properties within the *meta-inf/manifest.m*f jar file.
The bundle id is assigned by the framework when the bundle is installed. Thus only an installed bundle has a bundle id.

How to create a working OSGI bundle for Apache POI 3.8?

My goal is to create an Excel 2007 document (XLSX) in an Eclipse RCP Environment (Excel 2003 is simple). I don't want to place the POI jars inside a /lib folder, instead I want to use a working POI OSGI bundle from my target definition.
All my attempts so far have failed to create a working OSGI bundle of POI 3.8. What I did so far:
I merged all relevant JAR files with the Ant zip task:
poi-3.8-beta3-20110606.jar
poi-ooxml-3.8-beta3-20110606.jar
poi-ooxml-schemas-3.8-beta3-20110606.jar
poi-scratchpad-3.8-beta3-20110606.jar
I ran the bnd tool with the wrap parameter: java -jar biz.aQute.bnd.jar wrap ./poi-3.8-beta3-20110606-merged.jar
I had to bundle the jars in the /ooxml-lib folder separately, with bnd:
xmlbeans-2.3.0.jar
stax-api-1.0.1.jar
dom4j-1.6.1.jar
This leads to ClassNotFoundExceptions for org.w3c.dom.Node because xmlbeans-2.3.0.jar exports four classes from this package org.w3c.dom. Normally the JavaSE-RuntimeEnvironment would export these.
I deleted the org/w3c/dom folder from xmlbeans-2.3.0.jar and rebundled the jar but I got other ClassNotFoundExceptions.
This is where I got so far. I think working with bnd wrap is not enough. Probably I must create a bnd.properties file and have explicit Export-Package/Import-Package statements but which work?
So, has anyone successfully managed to create a working POI 3.8 OSGI bundle?
If you don't need that specific version, simply use http://ebr.springsource.com/repository/app/bundle/version/detail?name=com.springsource.org.apache.poi&version=3.0.2.FINAL that page lists it's dependencies etc (which you can also download or reference if you're using Maven/Ivy)
May be http://engroup.sourceforge.net/maven2/engroup/osgi/commons/poi-osgi/3.1/ or http://ebr.springsource.com/repository/app/search?query=poi can provide some inspiration (in the first link there's a maven POM that lists the (bnd) instructions in the bundle plugin section).
Why are you merging the jars? Why not try wrapping each individually?
A second thing to try is to use existing OSGi'd jars of xmlbeans, stax-api and dom4j
Also you can configure what the JRE (system bundle) exports using "org.osgi.framework.system.packages" - so you can choose not to export org.w3c.dom
I was able to do after some serious head banging. You can see the POM file over here:
http://servicemix.396122.n5.nabble.com/Apache-Poi-3-7-component-tc4912054.html#a5009396
I had to repackage XMLBeans 2.3.0 and embed in the bundle.
Cheers,
Yogesh
I don't know about 3.8, but creating working OSGi bundle for 3.7 is quite easy with Bnd.
-classpath: poi-3.7-20101029.jar,
poi-ooxml-3.7-20101029.jar,
poi-ooxml-schemas-3.7-20101029.jar,
poi-scratchpad-3.7-20101029.jar
Bundle-Name: Apache POI
Bundle-SymbolicName: org.apache.poi
Bundle-Version: 3.7.0
Bundle-ClassPath: .
Private-Package: *
Export-Package: org.apache.poi.*;-split-package:=merge-first
Import-Package: !org.openxmlformats.schemas*, \
!schemasMicrosoftComOfficePowerpoint*, \
!schemasMicrosoftComOfficeWord*, \
junit*;resolution:=optional, \
org.apache.commons.logging;resolution:=optional, \
*
Include-Resource: #poi-3.7-20101029.jar, \
#poi-ooxml-3.7-20101029.jar, \
#poi-ooxml-schemas-3.7-20101029.jar, \
#poi-scratchpad-3.7-20101029.jar
If you are interested in a working example of the approach with BND, you can have a look at this project, providing a pom and a bnd file (inspired by Jarek's answer):
https://github.com/evandor/skysail-bundled-libraries/tree/master/skysail.bundles.poi
Running "mvn install" gives you an "OSGi-flavored" POI jar, which can be found as well here:
https://oss.sonatype.org/content/groups/public/de/twentyeleven/skysail/org.apache.poi-osgi/3.8/
You might have to play a bit with the bnd file to make it create the exact OSGi bundle you need (maybe you don't need all the dependencies, or you want to mark them as optional).
You will find all the documentation needed on the bnd homepage. I recommend starting with this page if you haven't used this great tool before.

Resources