I don’t know how broken version numbering is in general, but I would expect 
that a major version change normally indicates incompatibility, even if it 
doesn’t in this case. As such, I would expect any automated actions in the 
presence of such likely incompatibility would result in a selection of jars 
that just doesn’t work, and the only reasonable response I can think of is for 
maven to say “fix it yourself”.

What happens when there’s a minor version change in the jars?

I think any attempt to solve this problem will re-invent OSGI. I’ve heard there 
are problems with it but I personally haven’t encountered them, other than no 
one being willing to understand and use it properly.

David Jencks

> On Oct 12, 2025, at 10:50 AM, Vladimir Sitnikov <[email protected]> 
> wrote:
> 
>> 1. commons-compress 2 must not be compatible with v1 by commons rule (did
>> we miss it? the rule is to change the package to "2")
> 
> Romain, It sounds like you’re referring to an Apache Commons convention
> (e.g., commons-lang -> commons-lang3, package rename to allow side-by-side).
> 
> That can be useful for incompatible redesigns, but for a change like “keep
> the same APIs, just split one JAR into multiple modules,”
> forcing package renames places a significant burden on consumers.
> 
> More broadly, preserving backward compatibility lets users upgrade without
> code churn.
> FWIW, semver.org does not require “v2 must be incompatible with v1”
> 
>> 2. in your pom you can always exclude from a dep a transitive dep and
> enforce it explicitly
> 
> Could you please clarify with a concrete example?
> If you mean adding exclusions everywhere and then adding an explicit
> dependency on commons-compress,
> that’s exactly the kind of manual fix I’m hoping to avoid.
> 
> Here's the pom for the application:
> https://github.com/vlsi/jarsplit/blob/5e3fa1ecd3f26a2116aa83a92e85b69560a597f6/lib-user-maven4/pom.xml
> 
> Consider a novice user who depends on both lib-uses-v1 and lib-uses-v2.
> Today Maven resolves commons-compress to 1.0.0, and they get a
> NoSuchMethodError.
> The recommended fix becomes: “exclude commons-compress (which you never
> used directly) from multiple places
> and then add it back explicitly at the top level; and later remember to
> remove the workaround once transitive dependencies stabilize.”
> 
> I think the build tool can do better than that.
> 
> Here’s the kind of change I’m trying not to require users to hand-craft:
> 
> --- a/lib-user-maven4/pom.xml
> +++ b/lib-user-maven4/pom.xml
> @@ -6,15 +6,32 @@
>     <artifactId>app</artifactId>
>     <version>1.0.0</version>
>     <dependencies>
> +        <dependency>
> +            <groupId>org.example</groupId>
> +            <artifactId>commons-compress</artifactId>
> +            <version>2.0.0</version>
> +        </dependency>
>         <dependency>
>             <groupId>org.example</groupId>
>             <artifactId>lib-uses-v1</artifactId>
>             <version>1.0.0</version>
> +            <exclusions>
> +                <exclusion>
> +                    <groupId>org.example</groupId>
> +                    <artifactId>commons-compress</artifactId>
> +                </exclusion>
> +            </exclusions>
>         </dependency>
>         <dependency>
>             <groupId>org.example</groupId>
>             <artifactId>lib-uses-v2</artifactId>
>             <version>2.0.0</version>
> +            <exclusions>
> +                <exclusion>
> +                    <groupId>org.example</groupId>
> +                    <artifactId>commons-compress</artifactId>
> +                </exclusion>
> +            </exclusions>
>         </dependency>
>     </dependencies>
>     <build>
> 
> This is brittle and requires users to know internal transitive details they
> shouldn’t have to care about.
> 
> Note: the app does not use commons-compress, nor does it know there's
> commons-compress somewhere down the road.
> 
> Yes, I could add a top-level dependencyManagement:
> 
>    <dependencyManagement>
>        <dependencies>
>            <dependency>
>                <groupId>org.example</groupId>
>                <artifactId>commons-compress</artifactId>
>                <version>2.0.0</version>
>            </dependency>
>        </dependencies>
>    </dependencyManagement>
> 
> …but that’s precisely the point of my original request: the same
> dependencyManagement already exists in commons-compress-core:2.0.0,
> and I’d like Maven to honor it transitively so end users don’t need to
> duplicate it in their root POMs
> (which may not even “see” all the relevant transitive edges).
> 
>> 3. if 2 is bothering the common trick is to do a module with packaging=pom
>> doing the exclude+explicit dep and use this instead of the 3rd party
> ...
> 
> If by this you mean creating a wrapper module (a BOM or a “starter”) that
> either (a) manages versions or (b) carries curated dependencies plus
> exclusions,
> then yes, that’s a known workaround.
> It works, but it pushes complexity onto every consumer to adopt yet another
> indirection layer.
> 
> My goal is to avoid forcing all library users to create or adopt wrapper
> modules just to get a safe, convergent outcome.
> 
> I would much prefer Maven to honor the dependencyManagement present in
> transitive POMs (e.g., commons-compress:2.0.0 managing its split modules).
> That would let the ecosystem migrate from single-JAR to multi-JAR without
> package renames and without end-user boilerplate
> 
>> 4. maven enforcer or any other plugin to prevent
> 
> the usage of v1 (or v2 aggregator module) anywhere
> Enforcer is helpful for guardrails, agreed. I still want Maven to resolve
> to 2.0.0 automatically in the simple case where an application depends
> on two libraries that require different major lines of the same component.
> 
> Enforcer can catch regressions; it shouldn’t be the primary mechanism to
> coax Maven into a workable resolution.
> 
> Vladimir


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to