davsclaus commented on code in PR #26575:
URL: https://github.com/apache/camel/pull/26575#discussion_r4046197003
##########
dsl/camel-kamelet-main/src/test/java/org/apache/camel/main/download/KnownDependenciesResolverTest.java:
##########
@@ -53,4 +53,38 @@ void mavenGavForClass_returnsPackageScopedDependency() {
public static class SomeClass {
}
+
+ @Test
+ void theShippedMappingResolvesThirdPartyClassesByPackage() {
+ // CAMEL-24809: one line per library, matched by walking up the
package; the Artemis package sits under the
+ // classic ActiveMQ one and must win for its own classes
+ KnownDependenciesResolver resolver = new KnownDependenciesResolver(new
SimpleCamelContext(), null, null);
+ resolver.loadKnownDependencies();
+
+ assertGav(resolver, "org.postgresql.ds.PGSimpleDataSource",
"org.postgresql", "postgresql");
+ assertGav(resolver, "org.postgresql.ds.PGConnectionPoolDataSource",
"org.postgresql", "postgresql");
+ assertGav(resolver, "org.h2.jdbcx.JdbcDataSource", "com.h2database",
"h2");
+ assertGav(resolver, "com.zaxxer.hikari.HikariConfig", "com.zaxxer",
"HikariCP");
+ assertGav(resolver,
"org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory",
"org.apache.activemq",
+ "artemis-jakarta-client-all");
+ assertGav(resolver, "org.apache.activemq.ActiveMQConnectionFactory",
"org.apache.activemq", "activemq-client");
+ assertGav(resolver, "org.apache.qpid.jms.JmsConnectionFactory",
"org.apache.qpid", "qpid-jms-client");
+ assertGav(resolver, "com.fasterxml.jackson.databind.ObjectMapper",
"com.fasterxml.jackson.core", "jackson-databind");
+ assertGav(resolver, "com.fasterxml.jackson.dataformat.xml.XmlMapper",
"com.fasterxml.jackson.dataformat",
+ "jackson-dataformat-xml");
+ assertGav(resolver, "org.apache.commons.csv.CSVFormat",
"org.apache.commons", "commons-csv");
+ assertGav(resolver, "software.amazon.awssdk.services.sqs.SqsClient",
"software.amazon.awssdk", "sqs");
+ assertGav(resolver, "org.infinispan.client.hotrod.RemoteCacheManager",
"org.infinispan", "infinispan-client-hotrod");
+ assertGav(resolver, "org.infinispan.manager.DefaultCacheManager",
"org.infinispan", "infinispan-core");
+ assertGav(resolver, "freemarker.template.Configuration",
"org.freemarker", "freemarker");
+ // a shared parent package is deliberately not mapped
+ assertEquals(null,
resolver.mavenGavForClass("org.apache.commons.Anything"));
+ }
+
+ private static void assertGav(KnownDependenciesResolver resolver, String
className, String groupId, String artifactId) {
+ MavenGav gav = resolver.mavenGavForClass(className);
+ assertNotNull(gav, className);
+ assertEquals(groupId, gav.getGroupId(), className);
+ assertEquals(artifactId, gav.getArtifactId(), className);
+ }
Review Comment:
Applied as suggested in c20d93c65b1c: assertGav asserts the version is
present and not an unresolved placeholder, with the assertFalse import. Thanks,
the test reads the generated file so this is the right place for it.
##########
tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/PrepareKameletMainMojo.java:
##########
@@ -104,6 +149,175 @@ public void execute() throws MojoExecutionException,
MojoFailureException {
} catch (Exception e) {
throw new MojoFailureException("Error updating
camel-factoryfinder-known-dependencies.properties", e);
}
+ try {
+ updateKnownThirdPartyDependencies();
+ } catch (MojoFailureException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new MojoFailureException("Error updating
camel-thirdparty-known-dependencies.properties", e);
+ }
+ }
+
+ /**
+ * Generates camel-thirdparty-known-dependencies.properties from the
curated list of third-party libraries
+ * (CAMEL-24809). Each input line maps a package to
groupId:artifactId:version, where the version is a ${property}
+ * of the project (inherited from camel-parent) or
@bom(groupId:artifactId:${property}) for a library whose version
+ * a BOM manages. The version is resolved here, so the runtime needs no
lookup, and a property that does not exist
+ * or a literal version fails the build. With verifyThirdPartyJars every
jar is resolved and the mapped package must
+ * be found in it.
+ */
+ protected void updateKnownThirdPartyDependencies() throws Exception {
+ File input = thirdPartyLibraries.isAbsolute()
+ ? thirdPartyLibraries : new File(project.getBasedir(),
thirdPartyLibraries.getPath());
+ if (!input.exists()) {
+ getLog().info("No " + input + ":
camel-thirdparty-known-dependencies.properties not generated");
+ return;
+ }
+ Properties in = new Properties();
+ try (InputStream is = new FileInputStream(input)) {
+ in.load(is);
+ }
+ Map<String, String> boms = new LinkedHashMap<>();
+ List<String> problems = new ArrayList<>();
+ Map<String, String> resolved = new TreeMap<>();
+ for (String pkg : in.stringPropertyNames()) {
+ String gav = in.getProperty(pkg).trim();
+ int i = gav.indexOf(':');
+ int j = gav.indexOf(':', i + 1);
+ if (i < 0 || j < 0) {
+ problems.add(pkg + " = " + gav + ": expected
groupId:artifactId:version");
+ continue;
+ }
+ String groupId = gav.substring(0, i);
+ String artifactId = gav.substring(i + 1, j);
+ String version = gav.substring(j + 1);
+ Matcher pm = PROPERTY_VERSION.matcher(version);
+ Matcher bm = BOM_VERSION.matcher(version);
+ if (pm.matches()) {
+ String value =
project.getProperties().getProperty(pm.group(1));
+ if (value == null) {
+ problems.add(pkg + ": no property " + pm.group(1) + " in
parent/pom.xml");
+ continue;
+ }
+ version = value;
+ } else if (bm.matches()) {
+ String bomVersion =
project.getProperties().getProperty(bm.group(3));
+ if (bomVersion == null) {
+ problems.add(pkg + ": no property " + bm.group(3) + " in
parent/pom.xml");
+ continue;
+ }
+ String bomKey = bm.group(1) + ":" + bm.group(2) + ":" +
bomVersion;
+ version = managedVersion(boms, bomKey, groupId, artifactId);
+ if (version == null) {
+ problems.add(pkg + ": " + groupId + ":" + artifactId + "
is not managed by " + bomKey);
+ continue;
+ }
+ } else {
+ problems.add(pkg + " = " + gav + ": a literal version; add a
<" + artifactId.toLowerCase(Locale.ROOT)
+ + "-version> property to parent/pom.xml and use
${...}");
+ continue;
+ }
+ resolved.put(pkg, groupId + ":" + artifactId + ":" + version);
+ }
+ if (!problems.isEmpty()) {
+ throw new MojoFailureException("Problems in " + input + ":\n " +
String.join("\n ", problems));
+ }
+ if (verifyThirdPartyJars) {
+ verifyPackagesInJars(resolved);
+ }
+ List<String> lines = new ArrayList<>();
+ lines.add("# Generated by
camel-package-maven-plugin:prepare-kamelet-main from src/main/"
+ + input.getName() + " (CAMEL-24809). Do not edit.");
+ lines.add("# Third-party libraries camel run downloads on demand,
mapped by package; the resolver matches the class"
+ + " and then each enclosing package.");
+ for (Map.Entry<String, String> e : resolved.entrySet()) {
+ lines.add(e.getKey() + " = " + e.getValue());
+ }
+ try (InputStream is =
getClass().getClassLoader().getResourceAsStream("license-header.txt")) {
+ this.licenseHeader = loadText(is);
+ }
Review Comment:
Applied as suggested in c20d93c65b1c: the license-header load in
updateKnownThirdPartyDependencies now has the same catch and
MojoFailureException as the two sibling methods. It was an omission on my side.
##########
dsl/camel-kamelet-main/src/main/resources/camel-main-known-dependencies.properties:
##########
@@ -88,3 +78,71 @@ dev.langchain4j.model.embedding.onnx =
dev.langchain4j:langchain4j-embeddings:${
org.apache.camel.component.ai.observability.GenAiObservabilityImpl =
camel:ai-observability
# camel-main property prefix (same pattern as camel.opentelemetry) — resolves
ai-observability when GenAI observability config is accessed
camel.aiObservability = camel:ai-observability
+
+# Third-party libraries by package (CAMEL-24809). The resolver matches the
class name and then each enclosing
+# package, so one line per library covers every class in it: org.postgresql
covers the Driver, PGSimpleDataSource,
+# the pooling datasources and the rest of the jar. Map at the library's own
package, never a shared parent such
+# as org.apache.commons, or the walk up the package would pick the wrong jar.
Versions are the properties of
+# camel-dependencies (KnownDependenciesVersionResolver); a literal version is
used where no property exists.
+
+# JDBC drivers, datasources and connection pools
+org.postgresql = org.postgresql:postgresql:${pgjdbc-driver-version}
+com.mysql.cj = com.mysql:mysql-connector-j:${debezium-mysql-connector-version}
+org.mariadb.jdbc = org.mariadb.jdbc:mariadb-java-client:${mariadb-version}
+com.microsoft.sqlserver.jdbc = com.microsoft.sqlserver:mssql-jdbc:12.10.0.jre11
+oracle.jdbc = com.oracle.database.jdbc:ojdbc17:23.8.0.25.04
+org.h2 = com.h2database:h2:${h2-version}
+com.zaxxer.hikari = com.zaxxer:HikariCP:6.3.0
+com.mchange.v2.c3p0 = com.mchange:c3p0:${c3p0-version}
+org.apache.commons.dbcp2 =
org.apache.commons:commons-dbcp2:${commons-dbcp2-version}
+
+# Messaging clients (the Artemis package is deeper than the classic ActiveMQ
one and is matched first)
+org.apache.activemq.artemis =
org.apache.activemq:artemis-jakarta-client-all:${activemq-artemis-version}
+org.apache.activemq = org.apache.activemq:activemq-client:${activemq6-version}
Review Comment:
Kept on the ActiveMQ 6 client, and the comment in the input file now states
the choice and the override (c20d93c65b1c). The 6 client is the Jakarta one
Camel 4 needs and speaks OpenWire to 5.x brokers too. A project that must use
the 5.x Jakarta client declares org.apache.activemq:activemq-client-jakarta
itself: a declared dependency puts the class on the classpath before any
lookup, so no download is attempted. The suggested anchor
org.apache.activemq.activemq6 is not a package that exists, so it cannot serve
as a key. The limitation is also documented in the new advanced section of
camel-jbang-running.adoc.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]