[slf4j-dev] [JIRA] Updates for SLF4J-586: MANIFEST.MF exports a package with a former version number

slf4j developers list slf4j-dev at qos.ch
Mon Mar 27 21:54:00 CEST 2023


SLF4J / SLF4J-586 [Open]
MANIFEST.MF exports a package with a former version number

==============================

Here's what changed in this issue in the last few minutes.


There is 1 comment.


View or comment on issue using this link
https://jira.qos.ch/browse/SLF4J-586

==============================
 1 comment
------------------------------

Hannes Wellmann on 27/Mar/23 21:42

Thank you for your elaboration and I want to say in advance that the intention and purpose of that change was to make the live of application packagers (and everybody else) easier.

While you are absolutely right that one can load multiple bundles with the same Bundle-SymbolicName and same exported packages in different versions, I'm convinced that in case of SLF4J you should really only have one version of the slf4j.api bundle install in your OSGi runtime. Because slf4j.api 1 and 2 use different mechanism to wire the slf4j.api with a binding/provider you also need two bindings/providers, one for each version, that both have to be configured properly etc. and with other corner cases one probably gets a hard time setting up the loggers reliably. Although I have to admit that I have not yet tried it, but setting up one version of slf4j in OSGi can be difficult enough.
And that is also what SLFJ4-579 should help with, because it allows you to only install one version of the slf4j.api bundle (i.e. version >=2.0.7) in your runtime and serve with it both kind of bundles, those that import the package org.slf4j with a 1.x and those that import a 2.x version range.

You then only have to make sure that libraries that import the package {{{}org.slf4j.event{}}}, {{org.slf4j.helpers}} or {{org.slf4j.spi}} are compatible with slf4j-2. They either they have a version dedicated for slf4j-2 (and requires slf4j-2) or if they are compatible with both, they can just widen the version ranges for the imports of those packages to something like {{{}[1.7,3){}}}. See for example https://github.com/apache/mina-sshd/pull/336.

 

> Both version 1.7.36 and 2.0.7 will be loaded in memory, each contained in their own Classloader, both expose the package org.slf4j as version "1.7.36" but its more than likely that for dependency resolution the OSGi bundle container will pick the first being declared, as on face value, they are equivalent.

The former statement is correct, for the latter statement it depends how 'greedy' the resolver of your OSGi runtime is in your case, but in general a OSGi resolver usually (AFAIK, but I'm not sure how much this is mandated) tries to minimise the number of wires and resolved/wired bundles.

> However this is untrue, because as example, the library 2.0.7 exposes new methods "org.slf4j.MDC.pushByKey", "org.slf4j.MDC.pushByKey" and "org.slf4j.MDC.getCopyOfDequeByKey", so if my second plugin that relies on version 2.0.7 needs to use any of these methods, it will end in a "NoSuchMethodError" error.

In that case your second Plugin/Bundle must import the package {{org.slf4j}} with a version range that has a lower bound of 2.0.7, then the {{NoSuchMethodError}} cannot happen because the second Plugin will always be wired to slf4j.api version 2.0.7 or above. If you have not specified such version range I can only encourage you to do so, to guard yourself from such errors.

 

> In the opposite situation, if by any chance it is the version 2.0.7 that is taken into account along with package "org.slf4j.spi" of the version 1.7.36 then you will encounter a "NoSuchClassError" as the "org.slf4j.spi.SLF4JServiceProvider" class used by "org.slf4j.MDC" class does not exist in version 1.7.36 (I think this is less likely as I believe the OSGI container will try to resolve with the package dependency with the first bundle that matches the requirement)

If a Plugin/Bundle imports the packages {{org.slf4j}} and {{org.slf4j.spi}} both with a version range like [1.7,2) then the described case should also not be possible, because when exported packages use the {{{}uses{}}}-directive the OSGi container ensures classspace consistency and will not wire the slf4j.api-2 bundle to that Plugin in any case. I have written 'should' because the slf4j.api bundle in version 1 does not have those {{uses}} directives for its exported packages, only slf4j.api since version 2.0.6 has them. If slf4j.api version 1.7.x would have them too, the situation you have described would be definitely impossible. Nevertheless I believe that even at the moment it is unlikely because the OSGi resolver will probably minimize the number of wire providers for one bundle and will likely wire the Plugin you have described to slf4.api-1.


==============================
 This message was sent by Atlassian Jira (v9.6.0#960000-sha1:a3ee8af)



More information about the slf4j-dev mailing list