Federico Mariani created CAMEL-25921:
----------------------------------------

             Summary: camel-jbang - plugins resolve with no dependencies (or 
are re-downloaded) when the local Maven repository was written by Maven 3.10
                 Key: CAMEL-25921
                 URL: https://issues.apache.org/jira/browse/CAMEL-25921
             Project: Camel
          Issue Type: Bug
          Components: camel-jbang
    Affects Versions: 4.22.1, 4.18.4, 4.20.0
            Reporter: Federico Mariani
            Assignee: Federico Mariani


Since Maven 3.10.0 (Maven Resolver 2.0.23+), the local repository tracking 
files ({{_remote.repositories}}) record artifact provenance with a 
URL-qualified repository key, e.g.

{noformat}
langchain4j-bom-1.13.0.pom>central-8fac3ebd6edbaca3c794783fa38088af0aa128e7=
{noformat}

instead of the legacy ID-only key ({{langchain4j-bom-1.13.0.pom>central=}}). 
This is the new default of {{aether.system.trackingRepositoryKeyFunction}} 
({{nid_hurl}}), introduced as hardening against local repository poisoning.

{{camel-tooling-maven}} embeds Maven Resolver 1.9.27 (via MIMA), which only 
understands ID-only entries. With a local repository populated by Maven 3.10, 
every cached artifact is considered "not downloaded from this repository 
before", which leads to two problems in Camel JBang plugin resolution.

h3. 1. Offline-first plugin resolution silently returns no dependencies (4.20+ 
/ 4.22)

{{PluginHelper.downloadPlugin}} sets {{preferLocal=true}}, so 
{{MavenDownloaderImpl.resolveArtifacts}} first resolves offline when the 
requested GAV exists in the local repository. When the plugin POM model cannot 
be built offline (e.g. its parent imports BOMs that are "invisible" because of 
the tracking keys above), Maven Resolver's default {{ArtifactDescriptorPolicy}} 
ignores the missing/invalid descriptor and returns the plugin with *no* 
transitive dependencies. No exception is thrown, so the online fallback never 
runs, and {{writeCache}} persists the incomplete classpath in 
{{~/.camel-jbang-plugins.json}}:

{noformat}
"classpath": [
  ".../camel-jbang-parent-4.22.1.pom",
  ".../camel-jbang-plugin-forage-1.6.2-SNAPSHOT.jar"
]
{noformat}

Loading the plugin then fails while picocli reflects the command classes:

{noformat}
Exception in thread "main" java.lang.NoClassDefFoundError: 
io/kaoto/forage/catalog/reader/ForageCatalogReader$FactoryMetadata
        at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
        ...
        at picocli.CommandLine.<init>(CommandLine.java:199)
        at io.kaoto.forage.plugin.ForagePlugin.customize(ForagePlugin.java:33)
        at 
org.apache.camel.dsl.jbang.core.common.PluginHelper.addPlugins(PluginHelper.java:179)
        at 
org.apache.camel.dsl.jbang.core.commands.CamelJBangMain.execute(CamelJBangMain.java:245)
{noformat}

The same resolution with a local repository written by Maven 3.9 resolves 46 
classpath entries and the plugin loads.

h3. 2. Everything is re-downloaded (4.18.x)

Without the offline-first path, the resolver logs "Artifact ... is present in 
the local repository, but cached from a remote repository ID that is 
unavailable in current build context" for every artifact and downloads it 
again, making plugin/dependency resolution much slower.

h3. Reproducer

Linux container ({{eclipse-temurin:21-jdk}}), Maven 3.10.0, Camel JBang 4.22.1, 
any third-party plugin whose POM parent imports BOMs (here: Kaoto Forage, 
{{io.kaoto.forage:camel-jbang-plugin-forage}}):

{noformat}
# 1. populate ~/.m2 with Maven 3.10.0 (e.g. build a project / 
dependency:resolve)
mvn -B -DskipTests verify ...
grep -v '^#' 
~/.m2/repository/dev/langchain4j/langchain4j-bom/1.13.0/_remote.repositories
#   langchain4j-bom-1.13.0.pom>central-8fac3ebd6edbaca3c794783fa38088af0aa128e7=

# 2. add and load the plugin
jbang -Dcamel.jbang.version=4.22.1 camel@apache/camel plugin add forage --gav 
io.kaoto.forage:camel-jbang-plugin-forage:<version>
jbang -Dcamel.jbang.version=4.22.1 camel@apache/camel forage --help
#   NoClassDefFoundError (plugin classpath = parent pom + plugin jar only)
{noformat}

Running step 1 with 
{{MAVEN_ARGS=-Daether.system.trackingRepositoryKeyFunction=nid}} (legacy 
tracking) makes step 2 work.

This hits CI first: GitHub-hosted runners now ship Maven 3.10.0, so any job 
whose Maven cache is (re)built by Maven 3.10 breaks, while jobs restoring an 
older cache keep working.

h3. Suggested fixes

* Upgrade the Maven Resolver embedded in {{camel-tooling-maven}} to 2.0.23+ 
(which reads both legacy and URL-qualified tracking entries), or configure the 
tracking key function of the embedded session accordingly.
* In {{MavenDownloaderImpl}}, do not treat an offline resolution as successful 
when the root artifact's descriptor could not be read (or resolved with no 
dependencies although the POM declares some): fall back to online resolution 
instead, and avoid caching such a classpath in {{PluginHelper.writeCache}}.

h3. Workaround

Set {{-Daether.system.trackingRepositoryKeyFunction=nid}} for the Maven builds 
that populate the local repository used by Camel JBang (e.g. {{MAVEN_ARGS}} in 
CI).



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to