bndtools / bnd

Bnd/Bndtools. Tooling to build OSGi bundles including Eclipse, Maven, and Gradle plugins.
https://bndtools.org
Other
526 stars 304 forks source link

Manual: Add section about Resolving Multi-Release JAR Files #6135

Closed chrisrueger closed 3 weeks ago

chrisrueger commented 1 month ago

Based on and almost quote of answer by @juergen-albert in https://bnd.discourse.group/t/questions-about-resolving-errors/450/3

I found your answer very good and thought this should be in the manual. Open for feedback or additions.

juergen-albert commented 1 month ago

LGTM. I'd suggest @pkriens takes a final look, as he wrote most of the code around it.

pkriens commented 4 weeks ago

This is not completely correct. There is only one bundle resource. This was a discussion when we developed the multi release jar support. @timothyjward wanted to model it as different bundles.

A Multi-Release JAR (MRJ) has directories in META-INF/versions/<release>. When the JAR is deployed on a VM with a given release R, that VM will preferentially load file resource from its own release R and then down to the main area. This means that a JAR can have different content depending on the VM it is deployed. For OSGi, this means that a bundle resource can have different requirements based on the runtime VM. The capabilities are the same since the public API must not change.

The problem is that this makes some requirements dependent on the VM. To model this, we introduced synthetic resource for each supported VM release that can only resolve on that release and when the release specific requirements of the bundle can be resolved.

This is only about modeling a JAR as a resource in an OSGi repository. Nothing is changed in the original JAR.

So we first treat the multi release bundle as any other bundle when we turn it into a resource, the release directories are ignored. If there are none, we're actually done.

Otherwise, we add a single requirement to a bnd.multirelease capability unique for this bundle. This namespace only has the properties bnd.multirelease=<bsn> and version=<version>. By requiring another resource, we can generate a synthetic resource for each VM release that the bundle supports. This is depicted here, where mrj is bnd.multirelease.

image

For the osgi.identity capability, we have to create a resource name that is unique. To keep it readable, the name is the original bsn + "__" + release. The version is the original bundle's version. We introduced a new type for these synthetic resources: bnd.synthetic.

We also add the requirements of the bundle if it would run on that release.

The synthetic resources are added to the same repository of the original bundle.

rotty3000 commented 4 weeks ago

I might be misunderstanding the image @pkriens, but are the versions in the green boxes flipped; where:

?

Aside from that, great explanation!

pkriens commented 4 weeks ago

You're right. Will fix it.

chrisrueger commented 4 weeks ago

thanks @pkriens I have taken your answer and updated the text. see 4589c54 and added my example and the image. Feel free to adjust this as needed. I feel that it could need an additional summary like sentence which nails it for a 5-year old but I am not capable of producing this sentence :)

image

I asked ChatGPT to summarize what you have written, but it basically repeated the same what you said, just structured a little bit different.

pkriens commented 3 weeks ago

LGTM, go ahead and merge.

It is really hard to explain this stuff because in my mind it is so obvious, logical, and simple :-)

chrisrueger commented 3 weeks ago

@pkriens any idea why the DCO failed? I have signed off as usual.

pkriens commented 3 weeks ago

Commit sha: 4589c54, Author: Christoph Rueger, Committer: Christoph Rueger; Expected "Christoph Rueger chrisrueger@gmail.com", but got "Christoph chrisrueger@gmail.com".

Not sure what it means but I guess you can fix it? Otherwise just merge it .... if it happens again we can fix it.