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)