2

Bundle-A:

FooA.java

package com.foo.a;

import com.foo.b.FooB;

class FooA {
    FooB b = new FooB();
}

Bundle-B:

FooB.java:

package com.foo.b;

import com.foo.c.FooC;

class FooB {

    public FooC foo() {
       ...
    }
}

Bundle-C: ...

So in short, I have 3 bundles - A, B and C.

Bundle A references bundle B directly, and Bundle B references C. As you see, FooA doesn't use the method in FooB that returns FooC, so FooC is not referenced in bundle A directly.

Why is BND including the OSGi import-package to com.foo.c then? The way I understand it - bundle A only needs bundle B in order to be able to resolve itself. Bundle B on the other hand needs C. But why should A require C directly, if it's not used there?

mdzh
  • 1,030
  • 2
  • 17
  • 34

2 Answers2

2

I think that bnd imports all classes that are visible to the outside for classes you use. As you use class FooB you might need access to all classes it may need as parameters or return as results.

If you want to avoid the dependency you can create an interface that only shows the methods you really need. You can then create a service with that interface in bundle B and only access the service using the interface from bundle A.

Christian Schneider
  • 19,420
  • 2
  • 39
  • 64
  • Okay, I understand the idea with introducing the interface. But I'm not looking for a solution to this particular problem though. What I'm trying to do is to get an an understanding of the problem - why does BND include this package? Is the package really needed? If I delete the import manually, would this break classloading? Why? A is not using C directly... – mdzh Sep 14 '16 at 10:14
  • It all depends if java needs C to instantiate class A or to use it in your case. It would be interesting to see what happens if you remove the import. If it still works then maybe bnd can be improved but generally it is quite accurate .. Still you should really try to use interfaces and services... it is the only way to really decouple your modules. – Christian Schneider Sep 14 '16 at 16:03
2

Have a look on the bytecode of the FooA class. You will see FooC in it somehow. Use a Java Decompiler tool to see why it is used. Some decompilers create code that show a bit more information than the original java code. I do not see here, why, but here is another example:

Guess you have the following function:

public class ListProvider {

    public static ArrayList getMyList() { return null; }

}

And other class calls it like this:

List myVar = ListProvider.getMyList();

You will see ArrayList in the bytecode of the other class. The reason is that the function signature that is used on the bytecode leven contains the return type, too.

Balazs Zsoldos
  • 6,036
  • 2
  • 23
  • 31