class loading of OSGi on Required-Bundle and Imported-Package - osgi

For OSGi bundle, we can add dependencies by using Required-Bundle or Imported-Package. Now I have below case:
Both bundle A and bundle B export same packages, but bundle B with higher version, like:
bundle A:
Exported Packages:
xxx.a,
xxx.b,
xxx.c
bundle B:
Exported Packages:
xxx.a; version="5.0.0",
xxx.b; version="5.0.0",
xxx.c; version="5.0.0"
And bundle C has the dependency to package a, b, c, so it adds A in its Required-Bundle list, like
bundle C:
Required Bundles:
A
Let's assume both bundle A and B are resolved in the framework. So when resolving bundle C, which packages/classes are been loaded by C, the classes in A or classes B? I think is A. Am i right?

Yes, the packages from A are used because you require bundle A.
Please note that Require-Bundle is considered deprecated by most OSGi developers.

Related

How to organize my python modules and packages

So I have written a module A and a dedicated test-file. This module can be used alone, but I wrote it to be used as a "base" for a second module I wrote. This second module absolutely needs the first one, and also has it's own test-file.
Finaly, I wrote a third module that is based on the first two modules. In other words :
module A, can be used without B or C.
module B needs module A, and can be used without C
module C needs module B (and so also A)
My question is how do treat all these modules ? For example, should I make each module a package, and then import A in B, and B in C ? Or should I put them all in a single package ? Also, what do I do of all the test files (put them next to the module, or all in a single test-folder) ?
As of today, I am treating each one as a package, but it seems a bit heavy to have to install A and B for using C:
+ moduleA
- moduleA.py
- test_moduleA.py
+ moduleB
- moduleB.py
- test_moduleB.py
+ moduleC
- moduleC.py
- test_moduleC.py
So I was thinking about merging all like this :
+ moduleC
- moduleA.py
- moduleB.py
- moduleC.py
+ tests
- test_moduleA.py
- test_moduleB.py
- test_moduleC.py
Is that the pythonic way to wrap my module C (and all its components) ? Or should I nest the modules in subpackages (moduleC.moduleB.moduleA) ?
The goal of all this is to export to github-like platform, and eventually pip.
The modules seem to be independent so they should be developed separately: separate development directories, separate git repositories.
For proper installation the modules should declare dependencies: B depends on A and C directly depends on B and indirectly (transitively via B) depends on A. Such dependencies should be declared in setup.py:
In B:
setup(
…
install_requires=[A]
…
)
In C:
setup(
…
install_requires=[B]
…
)
No need to declare dependency on A as B when being installed brings A with it.
This way when installing pip install A A will be installed alone;
when installing pip install B B will be installed with A;
when installing pip install C C will be installed with both A and B.

How to provide additional class for a package on OSGi system classpath for J2SE 1.8 profile

Inside ee.j2se-1.8 the package org.w3c.dom is included.
org.osgi.framework.system.packages = \
...
org.w3c.dom,\
...
org.osgi.framework.bootdelegation = \
...
org.w3c.*,\
org.xml.*,\
....
The bundle xml-apis_1.4.1.20140905-131237.jar contains the same package org.w3c.dom, but with one important class more ... ElementTraversal.class more.
So here my questions...
How can I provide the missing class inside my Equinox OSGi runtime?
You are suffering from the fact that people do not take packages seriously. We have a similar problem in the jta API. The version delivered by the VM is not identical to the version that is delivered as a special package.
The solution is to include the JAR with the extra packages on the class path where the framework resides. It looks like you're using bnd (good!) so this would look like:
-runpath: xml-apis__xml-apis;version="[1.4.1,2.0.0)"
If this had been a bundle with proper exports then you would have automatically gotten its exports as system packages. Looking at the packages in this bundle it seems all packages are already in the standard exports of the VM. However, if you have packages int his JAR that are not exported by the VM then you can add them as follows:
-runsystempackages: javax.xml.foo

Unable to wire proper bundle with my own bundle in wso2 app server

I am using wso2 Application Server 5.1.0.
I have deployed my own bundle having name demo-service which contains import-package definition in its manifest as below:
>Bundle-SymbolicName = demo-service
Import-Package = javax.sql,org.apache.commons.dbcp;version="[1.4,2)"
I tried to diagnose the most popular "uses conflict" in OSGi world for my case and I found that commons-dbcp_1.4.0.wso2v1.jar and commons-dbcp-1.4.jar both were converted to OSGi bundle by container and exported their packages with version "0.0.0" which can be observed from the output below:
>osgi> packages org.apache.commons.dbcp
org.apache.commons.dbcp; version="0.0.0"<commons-dbcp_1.4.0.wso2v1 [49]>
compass_2.0.1.wso2v2 [60] imports
org.wso2.carbon.core_4.1.0 [256] imports
org.wso2.carbon.registry.core_4.1.0 [377] imports
org.wso2.carbon.tenant.mgt_2.1.0 [434] imports
synapse-commons_2.1.1.wso2v3 [528] imports
synapse-core_2.1.1.wso2v3 [529] imports
org.apache.commons.dbcp; version="0.0.0"<commons_dbcp_1.4_1.0.0 [57]>
According to the requirement of my demo-service bundle it's not able to find
org.apache.commons.dbcp;version="[1.4,2)"
Is there any way to export the packages of commons-dbcp-1.4.jar after it gets converted from non-osgi bundle to osgi bundle because I need to make sure that my demo-service bundle should wire with commons-dbcp-1.4.jar..
In brief, any version of thirdparty jar I put in WSO2_HOME\repository\components\lib folder container exports it with version="0.0.0" .. which discourages the main concept for classloading of OSGi
please suggest if any workaround is possible in this case .. :)
Thanks ..
When a version is not specified while exporting packages OSGi defaults to version 0.0.0. In this case as it's automatically converting to osgi bundle it might not be having version explicitly specified. Sometimes this also helps to ensure that multiple versions of packages are not present.
In your case as you need to use the packages in the bundle put in repository\components\lib folder you could manually specify the version. The OSGi-fied bundles of the jars you put in repository\components\lib can be found in repository\components\dropins folder. Inside that bundle you will find the OSGi manifest file. In the manifest file manually specify the versions for the required packages under Export-Package category as follows.
org.apache.commons.dbcp;version=1.4.1
Then on startup, it would use these bundles and you should be able to export packages with specified version.

Managing transitive package dependencies declared via uses constraints

I have bundles A, B and C. A contains a package 'a' that is depended on by code in packages b and c from bundles B and C respectively.
bundle A {
package a
export-package:a
}
bundle B {
package b.a
package b.b
package b.c
package b.d
package b.e
import-package: a
export-package:b.a;uses:=a,
b.b;uses:=b.a,
b.c;uses:=b.b,
b.d;uses:=b.c,
b.e;uses:=b.d
}
bundle C {
package c
import-package: b.e,
a
}
When I update all of these bundles together, I often get uses constraint violations (Felix reporting style):
Chain 1:
C [47.1]
import: (&(osgi.wiring.package=a)(version>=1.1.0))
|
export: osgi.wiring.package=a
A [9.1]
Chain 2:
C [47.1]
import: (&(osgi.wiring.package=b.e)(version>=1.0.0))
|
export: osgi.wiring.package=b.e; uses:=a
B [33.0]
import: (&(osgi.wiring.package=a)(version>=1.0.0))
|
export: osgi.wiring.package=a
C [9.0]
I was initially surprised that b.e generates a uses clause for 'a'. This is not declared in the Manifest nor the OBR repository.xml through which these bundles are provisioned. However, types in b.e expose types in a through their API, so I guess this is where it comes from.
The only way I find to resolve these is to increase the version number of the export and import of intermediate packages, e.g. b.e in this example. However, there are a lot of packages that ultimately use 'a', transitively.
This means every time I update 'a' I also need to update all transitive dependencies on a with new versions. Is it the correct thing to be doing to increase the version number of these packages? Is refactoring my code to be less interdependent the only other way?
The uses constraints are not handled transitively by the resolver.
If bundle C imports b.e and b.e used b.d, then bundle C also needs to import b.d. That is, the public signature of b.e includes a reference to something in b.d. This is why we say b.e uses b.d. Therefore, any bundle which imports b.e must also import b.d. Otherwise the bundle cannot properly use b.e since some type referenced in b.e is not visible to the bundle.
For the export of b.e, it should state it uses b.d, b.c, b.b, b.a and a since using b.d means you also use b.c and so on...
Did you hand generate your uses clauses? Or was this example derived from something bnd generated?

Access class of other OSGi bundle

My project has two bundles, lets say Bundle A and Bundle B.
Now Bundle A needs to access a class from Bundle B.
How can I do that?
There are two ways:
Add the dependency of bundle B to the Manifest of bundle A: Require-Bundle: bundle-id-of-bundle-A
Import the package of the wanted class in the Manifest of bundle A: Import-Package: package.of.your.class
In both situations, you need to export the package that contains your class in bundle B: Export-Package: package.of.your.class
Also, here's a good intro:
http://ctpjava.blogspot.com/2010/09/introduction-to-osgi.html
As #earcam wrote, it is strongly recommended to use Import-Package:.
Also, always add a version to the exported package in bundle B - this is good practice that you will appreciate later when you create the next version of bundles A and B.

Resources