4

I'm getting a NoClassDefFoundError at runtime and I thought the "uses" directive would avoid this because I thought it created transitivity (correct me if I'm wrong). Here is my configuration:

Bundle 1 
  Export-package A

Bundle 2 
  Export-package B, uses "A"
  Import-package A

Bundle 3
  Import-package B

Now, the exception happens when Bundle 3 makes a call to a class in B which in turn makes a call to a class in A. Based on the console, i can see that the BundleClassLoader looks for the class in bundle 3 (in other words, in itself), but not in Bundle 1 where it would find it. If i force BND to import A in Bundle 3 everything works fine, but it looks too labor intensive. i feel like I'm missing something. Shouldn't equinox use the info in the manifests to set the bundle classpath? or in the worst case, shouldn't BND detect the dependency of 3 on 1 and import package A in the manifest of 3?

All my bundles are active and i have no uses constraint violations

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
Hilikus
  • 9,954
  • 14
  • 65
  • 118

1 Answers1

1

Bundle 2 must also import A. The uses A says that any bundle that imports my B and also imports A must import the same A as me. Since bundle 2 does not import A, this doesn't work. Also, bundle 3 needs to import A since B uses A. Any importer of B is also a user of A and so must import A.

BJ Hargrave
  • 9,324
  • 1
  • 19
  • 27
  • sorry, i do have the import of A in 2, i missed it. Will update the question. Your second part is the answer i was looking for. But does that mean that if A -> B, B -> C, C -> D, D -> E .... then A needs to import B, C, D, E; B needs to import C, D, E; C needs to import D, E, etc?? it sounds very inconvenient – Hilikus Dec 14 '12 at 02:34
  • 1
    Yes it sounds inconvenient, so you probably shouldn't design your packages like that. Remember that the `uses` constraint only exists because package B exposes A directly in its public interfaces, e.g. as a method parameter. Internal usage does NOT create a uses constraint. On the other hand if you do design your packages like this, bnd should detect that and create all the required imports and uses constraints. – Neil Bartlett Dec 14 '12 at 08:17
  • It is necessary. For a concrete example, think about javax.servlet.http.HttpServlet extends javax.servlet.GenericServlet implements javax.servlet.Servlet. This is a clear case of javax.servlet.http uses javax.servlet. So if your bundle implements an http servlet, you obviously need to import javax.servlet.http. But you also need to import javax.servlet since your bundle also needs access to those types. – BJ Hargrave Dec 14 '12 at 12:57
  • @NeilBartlett thanks for the info. I didn't know that it was only when it exposed it in a public interface and not in internal usage. However, your last comment confused me. You say BND should detect a case like the one in my question? it doesn't. Maybe i missunderstood your comment?? – Hilikus Dec 14 '12 at 13:32
  • Yes it does... if you use a package then bnd will add that to the `Import-Package`. Did you actually build all of these bundles with bnd? Can you describe your problem in more detail? – Neil Bartlett Dec 14 '12 at 14:21
  • BND did add the `use`d package to `Import-Package` (in Bundle 2 in my example) but it did not add the `Import-Package` in the original caller (Bundle 3). I did build everything with maven-bundle-plugin; not at the same time though – Hilikus Dec 14 '12 at 14:50