[ https://issues.apache.org/jira/browse/TEXT-233?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17817498#comment-17817498 ]
Gary D. Gregory edited comment on TEXT-233 at 2/14/24 10:23 PM: ---------------------------------------------------------------- See also * [https://github.com/bndtools/bnd/issues/544] * https://issues.apache.org/jira/browse/FELIX-4626 Reproducer: {noformat} git clone https://gitbox.apache.org/repos/asf/commons-text.git git checkout 1001fb35902e52f1c19442a197a5ff914f7d8432 mvn clean verify unzip -p target/commons-text-1.11.1-SNAPSHOT.jar META-INF/MANIFEST.MF {noformat} was (Author: garydgregory): See also * [https://github.com/bndtools/bnd/issues/544] * https://issues.apache.org/jira/browse/FELIX-4626 Reproducer: {noformat} git clone [https://gitbox.apache.org/repos/asf/commons-text.git] git checkout 1001fb35902e52f1c19442a197a5ff914f7d8432 mvn clean verify unzip -p target/commons-text-1.11.1-SNAPSHOT.jar META-INF/MANIFEST.MF {noformat} > Missing OSGi import-package commons-lang3 version can make commons-text > unusable in OSGi > ---------------------------------------------------------------------------------------- > > Key: TEXT-233 > URL: https://issues.apache.org/jira/browse/TEXT-233 > Project: Commons Text > Issue Type: Bug > Affects Versions: 1.11.0 > Reporter: K P > Priority: Major > > Since commons-text 1.11.0, there's commons-text codes that requires the > presence of commons-lang3 3.13.0 or higher. However, in an OSGi environment, > this requirement is not enforced due to shortcoming an the commons-text > 1.11.0 MANIFEST.MF, which may lead to unpredictable, uncontrollable failure > when trying to use commons-text 1.11.0. > Some more detail: > Since commons-text 1.11.0, the NumericEntityEscaper makes uses of the method > *Range.{_}+of+{_}(...)* in commons-lang3 : > > {code:java} > private NumericEntityEscaper(final int below, final int above, final boolean > between) { > this.range = Range.of(below, above); > this.between = between; > }{code} > > Method Range.of(...) was added in *commons-lang3 3.13.0* : > > {code:java} > * @since 3.13.0 > */ > public static <T extends Comparable<? super T>> Range<T> of(final T > fromInclusive, final T toInclusive) {{code} > > Previously, in commons-text 1.10.0 or earlier, NumericEntityEscaper made use > of the the commons-lang3 method *Range.{_}+between+{_}(...)* (which is now > marked as deprecated since commons-lang3 3.13.0) > > {code:java} > private NumericEntityEscaper(final int below, final int above, final boolean > between) { > this.range = Range.between(below, above); > this.between = between; > }{code} > > This is all fine in a non-OSGi environment. > > However, to always resolve this correctly in an OSGi environment, some > essential information is missing in the commons-text 1.11.0 {*}MANIFEST.MF{*}. > The commons-text 1.11.0 declares the following *Import-Package* in its > manifest: > > {noformat} > Import-Package: javax.script,javax.xml.xpath,org.apache.commons.lang3,or > g.apache.commons.lang3.time,org.xml.sax > {noformat} > Notice how this indeed imports the required package > "{_}org.apache.commons.lang3{_}", but this import {+}is not qualified with a > version number{+}. > When an OSGi package is not qualified by a version number or version range, > then during package resolution, OSGi may resolve this import against whatever > version of commons-lang3 it can find and that exports this package. > In other words, because there's no version restriction in this import as far > as OSGi is concerned : if you have an OSGi environment where also an older > version older version of commons-lang3 is already present, e.g. commons-lang > "3.12.0", then the import-package of commons-text 1.11.0 will happily be > satisfied by that package and resolve and link its import-package requirement > against the 3.12.0 version. > So when loading these OSGi bundles, all will look fine. The OSGi will nicely > resolve everything without complaining at this point. > However in the above example environment, maybe much much later, when at a > given moment a user of the 1.11.0 commons-text NumericEntityEscaper (e.g. > some of the StringEscapeUtils method being called by user code) is invoked, > then that commons-text 1.11.0 NumericEntityEscaper will see the 3.12.0 > version of the Range class in its classpath. It will try to invoke the method > Range.of(...) ... but this method didn't exist yet in this 3.12.0 version of > the Range class. > Which will fail with a NoSuchMethodError: > > {noformat} > java.lang.NoSuchMethodError: > org.apache.commons.lang3.Range.of(Ljava/lang/Comparable;Ljava/lang/Comparable;)Lorg/apache/commons/lang3/Range; > at > org.apache.commons.text.translate.NumericEntityEscaper.<init>(NumericEntityEscaper.java:97) > ~[?:?]{noformat} > > To avoid this, it is +required+ that the commons-text 1.11.0 *MANIFEST.MF* > correctly specifies the minimally required version of the commons-lang3 > package in its Import-Package: > E.g. by adding a version directive: *{{;version="3.13"}}* : in OSGi, 1 single > version number means a minimal version number, i.e. an open range 3.13.0 or > higher. > Example: > {code:java} > Import-Package: > javax.script,javax.xml.xpath,org.apache.commons.lang3;version="3.13",or > g.apache.commons.lang3.time;version="3.13",org.xml.sax{code} > That way, when OSGi resolves commons-text 1.11.0, it will now only be > satisifed by version 3.13 of those package, or higher, and therefore be > guaranteed to link its org.apache.commons.lang3 Import-Package against the > package from commons-lang3 3.13.0 or higher. > Then at runtime, whenever the NumericEntityEscaper calls a method on the > Range class, it sees a 3.13.0 (or higher) version of the Range class, where > the method Range.of(...) exists. > (Note: a manifst example from another Apache Project: > this snippet is from the MANIFEST.MF of the Apache Velocity Engine jar: > > {code:java} > Import-Package: javax.naming,javax.sql,org.apache.commons.lang3;versio > n="[3.11,4)", > {code} > Notice how they've specified a version range, which is also a possibility in > OSGi: range _"[3.11,4)"_ means: import from any version from 3.11 (inclusive) > to version 4 (exclusive). ) > > I know that the commons-text OSGi MANIFEST.MF headers are generated by the > "maven-bundle-plugin", which is defined somewhere in the "commons-parent" > pom.xml I believe? But I assume that it should be possible to overrule some > of the default (wildcard) generic maven-bundle-plugin settings with > project-specific Import-Package directives, so that a version number (3.13) > can be specified explicitly org.apache.commons.lang3 packages? > > {color:#000000} In the current state, as shown above, the commons-text 1.11.0 > code may fail unpredictably in an OSGi environment. Due to the dynamic nature > of OSGi, bundles (jars) may come and go. Older versions of commons-lang3 may > be present or not. So when the commons-text import-package doesn't impose a > minimal version number in its Import-Package, it may unpredictably resolve > against a commons-lang3 3.13. or 3.14.0, but just as well against an older > version where the required Range.of() method is missing, causing the failure. > In a dynamic environment, such application may sometimes run successfully by > chance, but may just unpredictably fail later, outside the control of the > developer or user.{color}{color:#7f0055} > {color} -- This message was sent by Atlassian Jira (v8.20.10#820010)