The OSGi plugin has several flaws

A user of Gradle complained about bnd on the bnd(tools) mailing list that turned out to be caused by the use of bnd in the Gradle OSGi plugin.

  1. bnd need to see the resources in the target bundle, that is, they need to be in the JAR given to the analyzer. Currently it can only see the classes folder (At least that explains what I see). In this case the user used Bundle-ClassPath; this failed because bnd could not find the included JARs. However, there are many other checks done that are related to resources. At least, you should add the resources to the Jar object that you pass to the Analyzer with setJar(Jar).

  2. bnd has VERY extensive error checking; unfortunately, looking at the source code these are completely totally utterly ignored. In general you can do analyzer.check(), if this returns true than you have a happy Analyzer. Otherwise there are errors (getErrors()). You can get the warnings (which are often quite useful) with getWarnings(). The check() method takes a list of strings that are regexps. These regexps are applied against warnings and errors, which are then subsequently removed.

  3. You’re using an Analyzer, it would be better to use a Builder. However, in that case you should allow bnd to create the final JAR. This is more logical for bnd and there a myriad of very useful OSGi related functions that can then be used (-includeresource comes to mind). There are other functions like (conditionally) copying packages from the classpath in the bundle, something very important to make good bundles. If you use the Builder, I would use the following defaults:

-includeresource: resources, classes

For the class path, you should add your classes folder. This allows people to create proper OSG bundles by specifying the packages that should be used.This defaults make it work out of the box for your current users and allow all the added capabilities of bnd to be used. The current setup will confuse people because not all bnd’s instructions are available.

  1. It would be very nice if there would be a possibility to see the property and the class path of the Analyzer (or Builder) before calcManifest is called. This would make debugging a lot easier

  2. The manifest in bnd is sorted and made canonical. By copying the manifest into another Map you likely screw up this order. Again, if bnd is allowed to write the JAR this will be done correctly. It would be nice to add a header in the manifest that this manifest is not generated by bnd.

  3. Some of the defaults are wrong:

a) Import-Package default

“, !org.apache.ant., !org.junit., !org.jmock., !org.easymock., !org.mockito.”);

This is completely arbitrary and should not be a default. On top of that, it does not work since the * will import already anything and the remainder is ignored. ! instructions should always precede the wildcard. These instructions are processed sequentially. Please, please, let bnd handle the default.

b) Export-Package

“*;-noimport:=false;version=” + getVersion());

Hmm. Where to start:

i) Modularity is about NOT exporting. Most bundles I make have no exports. So the default should never be *, it is the antithesis of modularity.

ii) If you insist, change this to -exportcontents. This is very confusing since the Builder will include the whole class path for this instruction

iii) -noimport should not be set. bnd is very clever in detecting if something does not have to be imported, if it does, there are sound reasons. You should rarely have to override bnd’s defaults.

iv) Exporting a package with the bundle’s version is wrong

v) Even if you export the package with the bundle version, you should be consistent. If the Bundle-Version instruction is set you will get a different version for the bundle and packages, which will be really confusing.

vi) Setting the version on the exports will override any version information bnd can find in the package’s packageinfo file or the annotations on package-info.java, or the manifest if bundles on the class path.

  1. Manifest digests calculated by bnd are not copied to the destination manifest.

Hope this helps, let me know if I can help improving this plugin further.

1 Like

These points are spot-on and vital – nearly all of them have bit us several times. I’m interested in contributing fixes if there is agreement on the issues…

I would love to see this and see the doc improved

I’m not sure the existing plugin can really be fixed due to backwards compatibility constraints. It’s in use by some people and they have (through sheer hard work) got it to do what they need.

It might be better to start again from scratch.

Moreover, realistically this going to require a domain expert to contribute to get this right.

Maybe Peter can help here? It sounded to me like he was willing to but not sure.

I can help out. Want to setup a Skype call to get a feeling what you want.

We are in bndtools also looking at gradle so maybe we can align some forces.

Will continue over email.

Luke and Peter I and maybe others in the community are interested in the outcome. Is there any way to stay involved in what is happening?

Sure, before any work is planned/started etc. this post will be updated.

I just stumbled across this thread and wondered if there’s been any progress, or at least agreement on how to proceed, since the last comment 4 months ago?

Unfortunately, nothing has.

Peter and I were unable to find a suitable time to discuss what needs to be done.

I’m also interested in this.

The proposed changes would be really nice. I’m also interested in seeing this resolved.

My company is planning on finding some developer time over the next couple of weeks to create a plugin based on Peter’s suggested approach i.e. using a bnd Builder to create the JAR. The code will be open-source. I will post an update on here when there’s something to share.

Great. Please tell if you need help :slight_smile:

The first version of an alternative OSGi bundle plugin: https://github.com/tomdmitriev/gradle-bundle-plugin

It uses BND to generate the entire JAR (rather than just the manifest) as per Peter Kriens’ original post.

Awesome! I’m excited to try it out.

Yes indeed, OSGi support in gradle should be as good as in maven, and this plugin points in the right direction.