0

I have a little problem with a software solution I'm maintaining. We have previously moved the entire solution from Java 1.7 to Java 1.8 and are finally having most things run again.

Now I have encountered a problem. In my built product a certain class seems to be unable to load. This class comes from a bundle in a jar, which is a required-Bundle in the manifest of the calling bundle.

Weirdly enough the bundle seems to be resolved when starting the osgi environment, so I suppose the .jar is found correctly. Once the program tries to load a certain dialogue though, I get a ClassNotFoundException.

Within my IDE the dialogue works flawlessy, just the built product doesn't seem to be able to load the class at runtime (even though the bundle containing it resolves).

A graphic representation of what's happening:

+-----------------------+   +---------------------------+
|xtext....jar           |   |MyProject                  |
|.                      |   |.                          |
|.                      |   |.                          |    +-------------------------+
|.                      |   | MANIFEST.MF               |    |ClassNotFoundException   |
|  MANIFEST.MF          +---> -Bundle-Name:MyBundle     +--->+at runtime in built      |
|  -Bundle-Name:X-Bundle|   | -Require-Bundle:X-Bundle  |    +version                  |
|  -Export-Package:x    |   |                           |    +-------------------------+
|.                      |   |                           |
|.                      |   +---------------------------+
|DeltaConverter.class   |
|                       |
+-----------------------+

The class DeltaConverter is not found in the built version at runtime, although the bundle is resolved and I have a require bundle in place for the bundle using it.

Any hints, what could be happening here?

Radioo
  • 422
  • 5
  • 18
  • You might want to look at tool support if you're having these kind of problems. With proper tooling this should never happen. – Peter Kriens May 20 '19 at 13:41

2 Answers2

1

TL;DR:

Make sure that your classes package is exported in META-INF/MANIFEST.MF.


Long version:

Even if the Bundle is resolved and active it does not mean that the class is available in other bundles or parts of the system.

The package that the class resides in has to be exported. Every bundle has a META-INF/MANIFEST.MF. This is basically like a bundle description.

Within that description there is a field called Export-Package, which contains a list of all the packages that are exported and therefore can be used within other bundles.

Usually, the META-INF/MANIFEST.MFis created during your build in Maven or Gradle through plugins. Check the configuration of those plugins or see how they work. Certain plugins for example won't export packages below impl packages.

So if you class is in a package com.example.awesomeapp.impl.services then the service package won't be exported. But this depends on the plugin you use etc.

All of this works in your IDE, because it handles the classpath differently than your OSGi environment. In short: Your IDE knows more or less only one classpath that contains all classes, while OSGi uses a lot of classpaths (one per bundle and a couple of other classpaths) and therefore "hides" classes from each other. That's why your IDE can load a class and your OSGi bundles don't.

Jens
  • 20,533
  • 11
  • 60
  • 86
  • So this means, that the jar-file containing the class does not necessarily export that package if it has a Manifest in it? I would myself have to export that package from the bundle, that has the jar on it's classpath? – Radioo May 16 '19 at 15:21
  • @Radioo Not quite. You have to make sure that the `MANIFEST.MF` has an entry for the package you want to export. And for the sake of completness: The other bundles `MANIFEST.MF` has to list the same package in the `Import-Package` field. – Jens May 16 '19 at 16:50
  • @Radioo Can you please add some sort of diagram (like an ASCII diagram) to your question because it is really hard to follow how many bundles are involved, which bundle exports, which bundle imports and where the classes in question are really located. From your comment it reads like you have two bundles, one exporting, one importing and the exporting bundle contains a different `jar` which actually contains the class etc. But it is really hard to tell. – Jens May 21 '19 at 07:09
  • I've checked back and the `MANIFEST.MF` of the failing bundle has a `Require-Bundle` for the whole bundle containing the class that can't be loaded. Is a require bundle in that case not enough? I thought that's the most restrictive kind of importing. Do I still have to import the package, even though I have a `Require-Bundle` in place? – Radioo May 21 '19 at 07:15
  • I've added a crude visualisation of the problem, hope this gets the issue across a bit clearer. I'm actually not quite sure, if the problem occurs within myProject, or bundle from yet another jar, that also (per manifest) requires the jar from xtext...jar. – Radioo May 21 '19 at 08:57
  • I'm noot quite sure if the problem is even OSGi related anymore. I've double checked, that the plugin is part of a feature that is part of the product file, and have added some other plugins aswell, to verify the feature is actually built, and those plugins work. I've also run `ss` in the felix gogo shell at runtime, and the bundle that contains the class the classloader can't find, is resolved. I've also manually activated the bundle via the console, but the issue persists. – Radioo May 21 '19 at 11:04
  • It seems to work now. I'm still not really sure what the issue was though. I had 2 seemingly unrelated jar files (org.objectweb.asm_3.3.1 and org.objectweb.asm_5.0.1). The build was using the older version which I then deleted from the build server, so he uses the newer one. After changing this char, everything seems to work now, even though I really don't why this solved the issue. I was originally trying to fix another issue by removing the old jar file. Anyway the issue seems resolved. – Radioo May 21 '19 at 12:32
  • @Radioo Can you please answer your own question (create a dedicated answer and _not_ edit your question) and accept it, so that others who find this question know what helped you. – Jens May 22 '19 at 11:52
0

It seems to work now. The issue disappeared, when I tried to fix an issue I thought was unrelated to this one. I had 2 seemingly unrelated jar files (org.objectweb.asm_3.3.1 and org.objectweb.asm_5.0.1) on our build server. The build was using the older version which I then deleted from the build server, so it can only use the newer one. After changing this, everything seems to work now, even though I really don't why this solved the issue. Weird is, that neither this jar, nor any of the packages or classes contained in this jar where directly mentioned in the stacktraces I received from my Exceptions.

Radioo
  • 422
  • 5
  • 18