This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new f4ac7fb1c76e CAMEL-25495: camel-jbang: pick the Quarkus Dockerfile by
--java-version
f4ac7fb1c76e is described below
commit f4ac7fb1c76e554b662fe2ad0ef74b23c1029681
Author: Thomas Raddatz <[email protected]>
AuthorDate: Fri Oct 9 22:27:09 2026 +0200
CAMEL-25495: camel-jbang: pick the Quarkus Dockerfile by --java-version
camel export --runtime=quarkus wrote src/main/docker/Dockerfile and
Dockerfile.jvm with a fixed ubi9/openjdk-21-runtime base image, whatever
--java-version said. A project exported with --java-version=25 was
compiled for Java 25 but started on a Java 21 runtime, so the container
failed with UnsupportedClassVersionError.
The Quarkus fast-jar Dockerfile is now picked by Java version from the
FreeMarker templates Dockerfile-quarkus21.ftl and Dockerfile-quarkus25.ftl,
as Camel Main and Spring Boot already do. That selection moves into
Export.processDockerfileTemplate. It falls back to the Java 21 template
only when no template exists for the requested version
(TemplateNotFoundException). Any other template error is now raised
instead of silently producing the Java 21 image. Camel Main and Spring
Boot export the same Dockerfiles as before.
Closes #27617
Co-authored-by: Claude <[email protected]>
---
.../camel/dsl/jbang/core/commands/Export.java | 21 ++++++++-----
.../dsl/jbang/core/commands/ExportQuarkus.java | 8 ++---
.../Dockerfile-quarkus21.ftl} | 18 +++++++++++
.../Dockerfile-quarkus25.ftl} | 20 +++++++++++-
.../camel/dsl/jbang/core/commands/ExportTest.java | 36 ++++++++++++++++++++++
.../dsl/jbang/core/common/TemplateHelperTest.java | 20 ++++++++++++
6 files changed, 108 insertions(+), 15 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
index d4614dcbb880..2cce9a74076c 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Export.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import freemarker.template.TemplateNotFoundException;
import org.apache.camel.dsl.jbang.core.common.CamelJBangConstants;
import org.apache.camel.dsl.jbang.core.common.PropertyResolver;
import org.apache.camel.dsl.jbang.core.common.RuntimeType;
@@ -329,17 +330,21 @@ public class Export extends ExportBaseCommand {
model.put("Version", ids[2]);
model.put("AppJar", ids[1] + "-" + ids[2] + ".jar");
- String ftlName = getDockerfileTemplateName() + javaVersion + ".ftl";
- String context;
+ String context =
processDockerfileTemplate(getDockerfileTemplateName(), model);
+ Files.writeString(docker.resolve("Dockerfile"), context);
+ }
+
+ // Process the Dockerfile template for the Java version, e.g.
Dockerfile25.ftl for Java 25.
+ protected String processDockerfileTemplate(String templateName,
Map<String, Object> model) throws IOException {
+ String ftlName = templateName + javaVersion + ".ftl";
try {
- context = TemplateHelper.processTemplate(ftlName, model);
- } catch (IOException e) {
- // fallback to JDK 21 template
- String fallback = getDockerfileTemplateName() + "21.ftl";
+ return TemplateHelper.processTemplate(ftlName, model);
+ } catch (TemplateNotFoundException e) {
+ // fallback to JDK 21 template (other errors, e.g. a malformed
template, are not hidden by the fallback)
+ String fallback = templateName + "21.ftl";
printer().printf("No Dockerfile template for Java %s, falling back
to Java 21 template%n", javaVersion);
- context = TemplateHelper.processTemplate(fallback, model);
+ return TemplateHelper.processTemplate(fallback, model);
}
- Files.writeString(docker.resolve("Dockerfile"), context);
}
protected String getDockerfileTemplateName() {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
index 30a1fdbd29e7..a5ed9e87eea0 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java
@@ -347,12 +347,8 @@ class ExportQuarkus extends Export {
super.copyDockerFiles(buildDir);
} else {
Files.createDirectories(dockerSrc);
- try (InputStream is
- =
ExportQuarkus.class.getClassLoader().getResourceAsStream("quarkus-docker/Dockerfile.jvm"))
{
- if (is != null) {
- PathUtils.copyFromStream(is,
dockerSrc.resolve("Dockerfile"), false);
- }
- }
+ String context = processDockerfileTemplate("Dockerfile-quarkus",
Map.of());
+ Files.writeString(dockerSrc.resolve("Dockerfile"), context);
}
// Create Dockerfile.jvm to satisfy Quarkus container build tooling
defaults if users choose to use it
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/quarkus-docker/Dockerfile.jvm
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile-quarkus21.ftl
similarity index 69%
copy from
dsl/camel-jbang/camel-jbang-core/src/main/resources/quarkus-docker/Dockerfile.jvm
copy to
dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile-quarkus21.ftl
index 2e3a0e7ec2c8..07459d724452 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/quarkus-docker/Dockerfile.jvm
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile-quarkus21.ftl
@@ -1,3 +1,21 @@
+<#--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/quarkus-docker/Dockerfile.jvm
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile-quarkus25.ftl
similarity index 67%
rename from
dsl/camel-jbang/camel-jbang-core/src/main/resources/quarkus-docker/Dockerfile.jvm
rename to
dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile-quarkus25.ftl
index 2e3a0e7ec2c8..f827c6ad3d86 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/resources/quarkus-docker/Dockerfile.jvm
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/Dockerfile-quarkus25.ftl
@@ -1,3 +1,21 @@
+<#--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -32,7 +50,7 @@
# docker run -i --rm -p 8080:8080 quarkus/camel-app
#
###
-FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.24
+FROM registry.access.redhat.com/ubi9/openjdk-25-runtime:1.24
ENV LANGUAGE='en_US:en'
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
index 9eab6173b79c..c10b7cbfcde6 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ExportTest.java
@@ -605,6 +605,42 @@ class ExportTest {
Assertions.assertTrue(new File(workingDir, "readme.md").exists(),
"Missing readme.md");
}
+ private static Stream<Arguments> runtimeAndJavaVersionProvider() {
+ return runtimeProvider()
+ .flatMap(rt -> Stream.of("21", "25").map(java ->
Arguments.of(rt.get()[0], java)));
+ }
+
+ @ParameterizedTest
+ @MethodSource("runtimeAndJavaVersionProvider")
+ public void shouldUseJavaVersionInDockerFiles(RuntimeType rt, String
javaVersion) throws Exception {
+ LOG.info("shouldUseJavaVersionInDockerFiles {} {}", rt, javaVersion);
+ Export command = createCommand(rt, new String[] {
"src/test/resources/route.yaml" },
+ "--gav=examples:route:1.0.0", "--dir=" + workingDir,
"--quiet", "--java-version=" + javaVersion);
+ int exit = command.doCall();
+
+ assertThat(exit).isZero();
+ String other = "21".equals(javaVersion) ? "25" : "21";
+ List<Path> jvmDockerFiles;
+ try (Stream<Path> files =
Files.list(workingDir.toPath().resolve("src/main/docker"))) {
+ jvmDockerFiles = files.filter(f ->
readString(f).contains("ubi9/openjdk-")).toList();
+ }
+ assertThat(jvmDockerFiles).isNotEmpty();
+ for (Path dockerfile : jvmDockerFiles) {
+ assertThat(readString(dockerfile))
+ .as(dockerfile.getFileName().toString())
+ .contains("ubi9/openjdk-" + javaVersion)
+ .doesNotContain("ubi9/openjdk-" + other);
+ }
+ }
+
+ private static String readString(Path file) {
+ try {
+ return Files.readString(file);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
// Each runtime may have a different logic
public void assertApplicationPropertiesContent(RuntimeType rt, File
appProps) throws Exception {
try (FileInputStream fis = new FileInputStream(appProps)) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java
index f583461a359c..ec2e5a3049b0 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/TemplateHelperTest.java
@@ -132,6 +132,26 @@ class TemplateHelperTest {
assertTrue(result.contains("my-app-2.0.0.jar"));
}
+ @Test
+ void testDockerfileQuarkus21Template() throws IOException {
+ String result =
TemplateHelper.processTemplate("Dockerfile-quarkus21.ftl", new HashMap<>());
+
+ assertNoLicenseHeader(result);
+ assertNoUnresolvedInterpolations(result);
+ assertTrue(result.contains("FROM
registry.access.redhat.com/ubi9/openjdk-21-runtime:"));
+
assertTrue(result.contains("JAVA_APP_JAR=\"/deployments/quarkus-run.jar\""));
+ }
+
+ @Test
+ void testDockerfileQuarkus25Template() throws IOException {
+ String result =
TemplateHelper.processTemplate("Dockerfile-quarkus25.ftl", new HashMap<>());
+
+ assertNoLicenseHeader(result);
+ assertNoUnresolvedInterpolations(result);
+ assertTrue(result.contains("FROM
registry.access.redhat.com/ubi9/openjdk-25-runtime:"));
+
assertTrue(result.contains("JAVA_APP_JAR=\"/deployments/quarkus-run.jar\""));
+ }
+
@Test
void testReadmeTemplate() throws IOException {
Map<String, Object> model = new HashMap<>();