validationQuerySql();
/**
- * Disable pooling to prevent reuse of Connections. Use this with when an external pool manages the life-cycle
+ * Disable pooling to prevent reuse of Connections. Use this when an external pool manages the life-cycle
* of Connections.
*/
@WithDefault("true")
diff --git a/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java b/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java
index 3099923f7efde..6d336c2e0875e 100644
--- a/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java
+++ b/extensions/reactive-datasource/runtime/src/main/java/io/quarkus/reactive/datasource/runtime/DataSourceReactiveRuntimeConfig.java
@@ -27,8 +27,8 @@ public interface DataSourceReactiveRuntimeConfig {
* The datasource URLs.
*
* If multiple values are set, this datasource will create a pool with a list of servers instead of a single server.
- * The pool uses a round-robin load balancing when a connection is created to select different servers.
- * Note: some driver may not support multiple values here.
+ * The pool uses round-robin load balancing for server selection during connection establishment.
+ * Note that certain drivers might not accommodate multiple values in this context.
*/
Optional> url();
diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java
index 84b2aaca206dc..3c0a43add0cad 100644
--- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java
+++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/vertx/http/deployment/HttpSecurityProcessor.java
@@ -215,9 +215,10 @@ SyntheticBeanBuildItem initBasicAuth(
&& !buildTimeConfig.auth.basic.orElse(false)) {
//if not explicitly enabled we make this a default bean, so it is the fallback if nothing else is defined
configurator.defaultBean();
- if (buildTimeConfig.auth.basic.isPresent() && buildTimeConfig.auth.basic.get()) {
- securityInformationProducer.produce(SecurityInformationBuildItem.BASIC());
- }
+ }
+
+ if (buildTimeConfig.auth.basic.isPresent() && buildTimeConfig.auth.basic.get()) {
+ securityInformationProducer.produce(SecurityInformationBuildItem.BASIC());
}
return configurator.done();
diff --git a/independent-projects/extension-maven-plugin/pom.xml b/independent-projects/extension-maven-plugin/pom.xml
index 8e928fdce58dc..165bdf86493a8 100644
--- a/independent-projects/extension-maven-plugin/pom.xml
+++ b/independent-projects/extension-maven-plugin/pom.xml
@@ -42,7 +42,7 @@
3.2.1
3.1.2
3.8.1
- 2.15.2
+ 2.15.3
1.3.2
5.10.0
diff --git a/independent-projects/resteasy-reactive/pom.xml b/independent-projects/resteasy-reactive/pom.xml
index adebdfe7cf3bc..e6772ee4d1df2 100644
--- a/independent-projects/resteasy-reactive/pom.xml
+++ b/independent-projects/resteasy-reactive/pom.xml
@@ -66,7 +66,7 @@
4.4.6
5.3.0
1.0.0.Final
- 2.15.2
+ 2.15.3
2.3.1
3.0.2
3.0.3
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java
index 82ae78192edf3..7e8e48c1ac190 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ExtensionUpdateInfo.java
@@ -93,4 +93,8 @@ public boolean isSimpleVersionUpdate() {
return VersionUpdateType.UPDATE_VERSION.equals(getVersionUpdateType())
|| VersionUpdateType.RECOMMEND_PLATFORM_MANAGED.equals(getVersionUpdateType());
}
+
+ public boolean isVersionUpdate() {
+ return !VersionUpdateType.ADD_VERSION.equals(getVersionUpdateType());
+ }
}
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java
index 77ab4634aaaf3..cef2daf98569f 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/ProjectExtensionsUpdateInfo.java
@@ -42,6 +42,10 @@ public List getSimpleVersionUpdates() {
return streamExtensions().filter(ExtensionUpdateInfo::isSimpleVersionUpdate).collect(Collectors.toList());
}
+ public List getVersionUpdates() {
+ return streamExtensions().filter(ExtensionUpdateInfo::isVersionUpdate).collect(Collectors.toList());
+ }
+
public boolean shouldUpdateExtensions() {
return streamExtensions().anyMatch(ExtensionUpdateInfo::shouldUpdateExtension);
}
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java
index efda3dc62d0b0..7d6e8f3960bfb 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdates.java
@@ -30,7 +30,7 @@ public static FetchResult createRecipe(MessageWriter log, Path target, MavenArti
request.currentVersion,
request.targetVersion,
request.projectExtensionsUpdateInfo
- .getSimpleVersionUpdates());
+ .getVersionUpdates());
QuarkusUpdateRecipe recipe = new QuarkusUpdateRecipe()
.buildTool(request.buildTool);
if (request.updateJavaVersion.isPresent()) {
diff --git a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java
index 46a8915571b79..57198af695eee 100644
--- a/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java
+++ b/independent-projects/tools/devtools-common/src/main/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepository.java
@@ -4,6 +4,7 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -56,7 +57,7 @@ public static FetchResult fetchRecipes(MessageWriter log, MavenArtifactResolver
final Artifact artifact = artifactResolver.resolve(DependencyUtils.toArtifact(gav)).getArtifact();
final ResourceLoader resourceLoader = ResourceLoaders.resolveFileResourceLoader(
artifact.getFile());
- final List recipes = fetchRecipesAsList(resourceLoader, "quarkus-updates", recipeDirectoryNames);
+ final Map recipes = fetchUpdateRecipes(resourceLoader, "quarkus-updates", recipeDirectoryNames);
final Properties props = resourceLoader.loadResourceAsPath("quarkus-updates/", p -> {
final Properties properties = new Properties();
final Path propPath = p.resolve("recipes.properties");
@@ -78,7 +79,7 @@ public static FetchResult fetchRecipes(MessageWriter log, MavenArtifactResolver
buildTool,
propRewritePluginVersion));
return new FetchResult(artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion(),
- recipes, propRewritePluginVersion);
+ new ArrayList<>(recipes.values()), propRewritePluginVersion);
} catch (BootstrapMavenException e) {
throw new RuntimeException("Failed to resolve artifact: " + gav, e);
} catch (IOException e) {
@@ -133,38 +134,55 @@ static boolean shouldApplyRecipe(String recipeFileName, String currentVersion, S
return currentAVersion.compareTo(recipeAVersion) < 0 && targetAVersion.compareTo(recipeAVersion) >= 0;
}
- static List fetchRecipesAsList(ResourceLoader resourceLoader, String location,
+ static Map fetchUpdateRecipes(ResourceLoader resourceLoader, String location,
Map recipeDirectoryNames) throws IOException {
return resourceLoader.loadResourceAsPath(location,
path -> {
try (final Stream pathStream = Files.walk(path)) {
return pathStream
.filter(Files::isDirectory)
- .flatMap(dir -> {
- String key = toKey(path.relativize(dir).toString());
- String versions[] = recipeDirectoryNames.get(key);
- if (versions != null && versions.length != 0) {
- try {
- Stream recipePath = Files.walk(dir);
- return recipePath
- .filter(p -> p.getFileName().toString().matches("^\\d\\H+.ya?ml$"))
- .filter(p -> shouldApplyRecipe(p.getFileName().toString(),
- versions[0], versions[1]))
- .map(p -> {
- try {
- return new String(Files.readAllBytes(p));
- } catch (IOException e) {
- throw new RuntimeException("Error reading file: " + p, e);
- }
- })
- .onClose(() -> recipePath.close());
- } catch (IOException e) {
- throw new RuntimeException("Error traversing directory: " + dir, e);
- }
- }
- return null;
-
- }).filter(Objects::nonNull).collect(Collectors.toList());
+ .flatMap(dir -> applyStartsWith(toKey(path, dir), recipeDirectoryNames).stream()
+ .flatMap(key -> {
+ String versions[] = recipeDirectoryNames.get(key);
+ if (versions != null && versions.length != 0) {
+ try {
+ Stream recipePath = Files.walk(dir);
+ return recipePath
+ .filter(p -> p.getFileName().toString()
+ .matches("^\\d\\H+.ya?ml$"))
+ .filter(p -> shouldApplyRecipe(p.getFileName().toString(),
+ versions[0], versions[1]))
+ .map(p -> {
+ try {
+ return new String[] { p.toString(),
+ new String(Files.readAllBytes(p)) };
+ } catch (IOException e) {
+ throw new RuntimeException("Error reading file: " + p,
+ e);
+ }
+ })
+ .onClose(() -> recipePath.close());
+ } catch (IOException e) {
+ throw new RuntimeException("Error traversing directory: " + dir, e);
+ }
+ }
+ return null;
+ }))
+ .filter(Objects::nonNull)
+ //results are collected to the map, because there could be duplicated matches in case of wildcard matching
+ .collect(Collectors.toMap(
+ sa -> sa[0],
+ sa -> sa[1],
+ (v1, v2) -> {
+ //Recipe with the same path already loaded. This can happen because of wildcards
+ //in case the content differs (which can not happen in the current impl),
+ //content is amended
+ if (!v1.equals(v2)) {
+ return v1 + "\n" + v2;
+ }
+ return v1;
+ },
+ LinkedHashMap::new));
} catch (IOException e) {
throw new RuntimeException("Error traversing base directory", e);
}
@@ -177,9 +195,20 @@ private static String toKey(ExtensionUpdateInfo dep) {
dep.getCurrentDep().getArtifact().getArtifactId());
}
- static String toKey(String directory) {
- return directory
+ static String toKey(Path parentDir, Path recipeDir) {
+ var _path = parentDir.relativize(recipeDir).toString();
+ return _path
.replaceAll("(^[/\\\\])|([/\\\\]$)", "")
.replaceAll("[/\\\\]", ":");
}
+
+ static List applyStartsWith(String key, Map recipeDirectoryNames) {
+ //list for all keys, that matches dir (could be more items in case of wildcard at the end
+ List matchedRecipeKeys;
+ //Current implementation detects whether key starts with an existing recipe folder
+ return recipeDirectoryNames.keySet().stream()
+ .filter(k -> k.startsWith(key))
+ .collect(Collectors.toList());
+ }
+
}
diff --git a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java
index 529aa24a6ef31..c262ae953f9b3 100644
--- a/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java
+++ b/independent-projects/tools/devtools-common/src/test/java/io/quarkus/devtools/project/update/rewrite/QuarkusUpdatesRepositoryTest.java
@@ -4,11 +4,14 @@
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
+import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
@@ -30,9 +33,69 @@ void testShouldLoadRecipesFromTheDirectory() throws IOException {
recipeDirectoryNames.put("core", new String[] { "2.7", "3.1" });
recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-core", new String[] { "2.7", "3.0" });
ClassPathResourceLoader resourceLoader = new ClassPathResourceLoader();
- List recipes = fetchRecipesAsList(resourceLoader, "dir/quarkus-update", recipeDirectoryNames);
+ Map recipes = fetchUpdateRecipes(resourceLoader, "dir/quarkus-update", recipeDirectoryNames);
int noOfRecipes = recipes.size();
assertEquals(3, noOfRecipes);
+ }
+
+ @Test
+ void testShouldLoadRecipesFromTheDirectoryWithWildcard() throws IOException {
+ Map recipeDirectoryNames = new LinkedHashMap<>();
+ recipeDirectoryNames.put("core", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-file", new String[] { "2.7", "3.0" });
+ ClassPathResourceLoader resourceLoader = new ClassPathResourceLoader();
+ Map recipes = fetchUpdateRecipes(resourceLoader, "dir/quarkus-update", recipeDirectoryNames);
+ int noOfRecipes = recipes.size();
+ assertEquals(3, noOfRecipes);
+ }
+
+ @Test
+ void testShouldLoadDuplicatedRecipesFromTheDirectoryWithWildcard() throws IOException {
+ Map recipeDirectoryNames = new LinkedHashMap<>();
+ recipeDirectoryNames.put("core", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-file", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-ftp", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-fhir", new String[] { "2.7", "3.1" });
+ ClassPathResourceLoader resourceLoader = new ClassPathResourceLoader();
+ Map recipes = fetchUpdateRecipes(resourceLoader, "dir/quarkus-update", recipeDirectoryNames);
+ int noOfRecipes = recipes.size();
+ assertEquals(3, noOfRecipes);
+ }
+
+ @Test
+ void testToKey() {
+ String key = toKey(Path.of("/home/app"),
+ Path.of("/home/app/target/classes/quarkus-updates/org.apache.camel.quarkus.camel-quarkus"));
+ assertEquals("target:classes:quarkus-updates:org.apache.camel.quarkus.camel-quarkus", key);
+
+ key = toKey(Path.of("/home/second-app"),
+ Path.of("/home/app/target/classes/quarkus-updates/org.apache.camel.quarkus.camel-quarkus"));
+ assertEquals("..:app:target:classes:quarkus-updates:org.apache.camel.quarkus.camel-quarkus", key);
+ }
+
+ @Test
+ @EnabledOnOs({ OS.WINDOWS })
+ void testToKeyWindows() {
+ String key = toKey(Path.of("C:\\a\\d\\"),
+ Path.of("C:\\a\\b\\quarkus-updates\\org.apache.camel.quarkus.camel-quarkus\\"));
+ assertEquals("..:b:quarkus-updates:org.apache.camel.quarkus.camel-quarkus", key);
+ }
+
+ @Test
+ void testApplyStartsWith() {
+ Map recipeDirectoryNames = new LinkedHashMap<>();
+ recipeDirectoryNames.put("core", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-something1", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-file", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-ftp", new String[] { "2.7", "3.1" });
+ recipeDirectoryNames.put("org.apache.camel.quarkus:camel-quarkus-fhir", new String[] { "2.7", "3.1" });
+
+ List matchedKeys = applyStartsWith("org.apache.camel.quarkus:camel-quarkus", recipeDirectoryNames);
+ assertEquals(3, matchedKeys.size());
+ assertTrue(!matchedKeys.contains("org.apache.camel.quarkus:camel-quarkus"));
+ matchedKeys = applyStartsWith("org.apache.camel.quarkus:camel", recipeDirectoryNames);
+ assertEquals(4, matchedKeys.size());
+ assertTrue(!matchedKeys.contains("org.apache.camel.quarkus:camel"));
}
}
diff --git a/independent-projects/tools/devtools-common/src/test/resources/dir/quarkus-update/org.apache.camel.quarkus/camel-quarkus-core/3.0.yaml b/independent-projects/tools/devtools-common/src/test/resources/dir/quarkus-update/org.apache.camel.quarkus/camel-quarkus/3.0.yaml
similarity index 100%
rename from independent-projects/tools/devtools-common/src/test/resources/dir/quarkus-update/org.apache.camel.quarkus/camel-quarkus-core/3.0.yaml
rename to independent-projects/tools/devtools-common/src/test/resources/dir/quarkus-update/org.apache.camel.quarkus/camel-quarkus/3.0.yaml
diff --git a/independent-projects/tools/pom.xml b/independent-projects/tools/pom.xml
index 624be6575399f..48814923bfe7a 100644
--- a/independent-projects/tools/pom.xml
+++ b/independent-projects/tools/pom.xml
@@ -52,7 +52,7 @@
3.24.2
- 2.15.2
+ 2.15.3
4.0.1
5.10.0
1.24.0
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/build.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/build.gradle
new file mode 100644
index 0000000000000..556e19daf2983
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/build.gradle
@@ -0,0 +1,32 @@
+plugins{
+ id "java"
+ id "io.quarkus"
+}
+
+
+
+group 'io.quarkus.test.application'
+version '1.0-SNAPSHOT'
+
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
+ implementation 'io.quarkus:quarkus-resteasy-reactive'
+ implementation ('org.acme.extensions:example-extension')
+
+ testImplementation 'io.quarkus:quarkus-junit5'
+ testImplementation 'io.rest-assured:rest-assured'
+}
+
+test {
+ useJUnitPlatform()
+}
+
+quarkusIntTest {
+ environment "MY_RT_NAME", "genadiy"
+}
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/gradle.properties b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/gradle.properties
new file mode 100644
index 0000000000000..ec2b6ef199c2c
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/gradle.properties
@@ -0,0 +1,2 @@
+quarkusPlatformArtifactId=quarkus-bom
+quarkusPlatformGroupId=io.quarkus
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/settings.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/settings.gradle
new file mode 100644
index 0000000000000..7eeaae22f27fc
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/settings.gradle
@@ -0,0 +1,20 @@
+pluginManagement {
+ repositories {
+ mavenLocal {
+ content {
+ includeGroupByRegex 'io.quarkus.*'
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+ //noinspection GroovyAssignabilityCheck
+ plugins {
+ id 'io.quarkus' version "${quarkusPluginVersion}"
+ }
+}
+
+includeBuild('../extensions/example-extension'){
+
+}
+rootProject.name='application'
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/integrationTest/java/org/acme/ExampleResourceIT.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/integrationTest/java/org/acme/ExampleResourceIT.java
new file mode 100644
index 0000000000000..6219887bad7f4
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/integrationTest/java/org/acme/ExampleResourceIT.java
@@ -0,0 +1,29 @@
+package org.acme;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusIntegrationTest
+public class ExampleResourceIT {
+
+ @Test
+ public void testHelloEndpoint() {
+ given()
+ .when().get("/hello")
+ .then()
+ .statusCode(200)
+ .body(is("hello cheburashka"));
+ }
+
+ @Test
+ public void testRuntimeName() {
+ given()
+ .when().get("/hello/runtime-name")
+ .then()
+ .statusCode(200)
+ .body(is("genadiy"));
+ }
+}
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/main/java/org/acme/quarkus/sample/HelloResource.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/main/java/org/acme/quarkus/sample/HelloResource.java
new file mode 100644
index 0000000000000..50a4aced5c534
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/main/java/org/acme/quarkus/sample/HelloResource.java
@@ -0,0 +1,33 @@
+package org.acme.quarkus.sample;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+import org.acme.example.extension.runtime.ExampleBuildOptions;
+import org.acme.example.extension.runtime.ExampleRuntimeConfig;
+
+@Path("/hello")
+public class HelloResource {
+
+ @Inject
+ ExampleBuildOptions buildOptions;
+
+ @Inject
+ ExampleRuntimeConfig rtConfig;
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String hello() {
+ return "hello " + buildOptions.name;
+ }
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @Path("/runtime-name")
+ public String runtimeName() {
+ return rtConfig.runtimeName;
+ }
+}
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/main/resources/application.properties b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/main/resources/application.properties
new file mode 100644
index 0000000000000..39fdee9f38d1e
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/application/src/main/resources/application.properties
@@ -0,0 +1 @@
+quarkus.example.runtime-name=${MY_RT_NAME:none}
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/build.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/build.gradle
new file mode 100644
index 0000000000000..464a421fce2a9
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/build.gradle
@@ -0,0 +1,34 @@
+plugins{
+ id 'java-library'
+ id 'maven-publish'
+}
+subprojects {subProject->
+ apply plugin: 'java-library'
+ apply plugin: 'maven-publish'
+
+ group 'org.acme.extensions'
+ version '1.0-SNAPSHOT'
+ publishing {
+ publications {
+ maven(MavenPublication) {
+ groupId = 'org.acme.extensions'
+ artifactId = subProject.name
+ version = '1.0-SNAPSHOT'
+ from components.java
+ }
+ }
+ }
+}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ groupId = 'org.acme.extensions'
+ artifactId = rootProject.name
+ version = '1.0-SNAPSHOT'
+ from components.java
+ }
+ }
+}
+group 'org.acme.extensions'
+version '1.0-SNAPSHOT'
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/build.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/build.gradle
new file mode 100644
index 0000000000000..3ce19bef01ea1
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/build.gradle
@@ -0,0 +1,18 @@
+plugins {
+ id 'java'
+ id 'java-library'
+}
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation platform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
+ annotationProcessor "io.quarkus:quarkus-extension-processor:${quarkusPlatformVersion}"
+
+
+ api project(':example-extension')
+ implementation 'io.quarkus:quarkus-arc-deployment'
+}
+
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/src/main/java/org/acme/example/extension/deployment/ExampleConfig.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/src/main/java/org/acme/example/extension/deployment/ExampleConfig.java
new file mode 100644
index 0000000000000..d92ed03d4757e
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/src/main/java/org/acme/example/extension/deployment/ExampleConfig.java
@@ -0,0 +1,14 @@
+package org.acme.example.extension.deployment;
+
+import io.quarkus.runtime.annotations.ConfigItem;
+import io.quarkus.runtime.annotations.ConfigRoot;
+
+@ConfigRoot
+public class ExampleConfig {
+
+ /**
+ * name
+ */
+ @ConfigItem(defaultValue = "none")
+ String name;
+}
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/src/main/java/org/acme/example/extension/deployment/ExampleProcessor.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/src/main/java/org/acme/example/extension/deployment/ExampleProcessor.java
new file mode 100644
index 0000000000000..7368451542ce0
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/deployment/src/main/java/org/acme/example/extension/deployment/ExampleProcessor.java
@@ -0,0 +1,30 @@
+package org.acme.example.extension.deployment;
+
+import jakarta.inject.Singleton;
+
+import org.acme.example.extension.runtime.ExampleBuildOptions;
+import org.acme.example.extension.runtime.ExampleRecorder;
+import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+
+class ExampleProcessor {
+
+ private static final String FEATURE = "example";
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ SyntheticBeanBuildItem syntheticBean(ExampleRecorder recorder, ExampleConfig config) {
+ return SyntheticBeanBuildItem.configure(ExampleBuildOptions.class)
+ .scope(Singleton.class)
+ .runtimeValue(recorder.buildOptions(config.name))
+ .done();
+ }
+}
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/gradle.properties b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/gradle.properties
new file mode 100644
index 0000000000000..ec2b6ef199c2c
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/gradle.properties
@@ -0,0 +1,2 @@
+quarkusPlatformArtifactId=quarkus-bom
+quarkusPlatformGroupId=io.quarkus
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/build.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/build.gradle
new file mode 100644
index 0000000000000..29ba93c67b5d6
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/build.gradle
@@ -0,0 +1,20 @@
+
+plugins {
+ id 'io.quarkus.extension'
+}
+
+quarkusExtension {
+ deploymentModule = 'example-extension-deployment'
+}
+
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+dependencies {
+ implementation platform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
+ annotationProcessor "io.quarkus:quarkus-extension-processor:${quarkusPlatformVersion}"
+ implementation 'io.quarkus:quarkus-arc'
+}
+
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleBuildOptions.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleBuildOptions.java
new file mode 100644
index 0000000000000..79c18d4929b67
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleBuildOptions.java
@@ -0,0 +1,10 @@
+package org.acme.example.extension.runtime;
+
+public class ExampleBuildOptions {
+
+ public final String name;
+
+ public ExampleBuildOptions(String name) {
+ this.name = name;
+ }
+}
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleRecorder.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleRecorder.java
new file mode 100644
index 0000000000000..3c41ac8f05ddc
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleRecorder.java
@@ -0,0 +1,13 @@
+package org.acme.example.extension.runtime;
+
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+
+@Recorder
+public class ExampleRecorder {
+
+ public RuntimeValue buildOptions(String name) {
+ System.out.println("ExampleRecorder.buildOptions " + name);
+ return new RuntimeValue<>(new ExampleBuildOptions(name));
+ }
+}
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleRuntimeConfig.java b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleRuntimeConfig.java
new file mode 100644
index 0000000000000..8e4890e928ce5
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/java/org/acme/example/extension/runtime/ExampleRuntimeConfig.java
@@ -0,0 +1,16 @@
+package org.acme.example.extension.runtime;
+
+import io.quarkus.runtime.annotations.ConfigItem;
+import io.quarkus.runtime.annotations.ConfigPhase;
+import io.quarkus.runtime.annotations.ConfigRoot;
+
+@ConfigRoot(phase = ConfigPhase.RUN_TIME)
+public class ExampleRuntimeConfig {
+
+ /**
+ * Whether the banner will be displayed
+ */
+ @ConfigItem(defaultValue = "none")
+ public String runtimeName;
+
+}
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/resources/META-INF/quarkus-extension.properties b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/resources/META-INF/quarkus-extension.properties
new file mode 100644
index 0000000000000..2e1a6326847e1
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/resources/META-INF/quarkus-extension.properties
@@ -0,0 +1 @@
+deployment-artifact=org.acme.extensions\:example-extension-deployment\:1.0
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000000000..12a5c710c9e82
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,12 @@
+---
+name: Quarkus Example Extension
+artifact: ${project.groupId}:${project.artifactId}:${project.version}
+metadata:
+ config:
+ - "quarkus.example.extension."
+ keywords:
+ - "logzio"
+ - "logging"
+ categories:
+ - "logging"
+description: "Quarkus example extension"
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/settings.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/settings.gradle
new file mode 100644
index 0000000000000..ca835fae5d2db
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/extensions/example-extension/settings.gradle
@@ -0,0 +1,21 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenLocal()
+ }
+ plugins {
+ id 'io.quarkus.extension' version "${quarkusPluginVersion}"
+ }
+}
+dependencyResolutionManagement {
+ repositories {
+ mavenLocal()
+ mavenCentral()
+ }
+
+}
+rootProject.name = 'example-extension-parent'
+include(':deployment')
+include(':runtime')
+project(':deployment').name='example-extension-deployment'
+project(':runtime').name='example-extension'
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/gradle.properties b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/gradle.properties
new file mode 100644
index 0000000000000..8f063b7d88ba4
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/gradle.properties
@@ -0,0 +1,2 @@
+quarkusPlatformArtifactId=quarkus-bom
+quarkusPlatformGroupId=io.quarkus
\ No newline at end of file
diff --git a/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/settings.gradle b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/settings.gradle
new file mode 100644
index 0000000000000..53eb6f0795e29
--- /dev/null
+++ b/integration-tests/gradle/src/main/resources/system-props-as-build-time-config-source/settings.gradle
@@ -0,0 +1,18 @@
+pluginManagement {
+ repositories {
+ mavenLocal {
+ content {
+ includeGroupByRegex 'io.quarkus.*'
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+ //noinspection GroovyAssignabilityCheck
+ plugins {
+ id 'io.quarkus' version "${quarkusPluginVersion}"
+ }
+}
+
+includeBuild('extensions/example-extension')
+includeBuild('application')
\ No newline at end of file
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/SystemPropsAsBuildTimeConfigSourceTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/SystemPropsAsBuildTimeConfigSourceTest.java
new file mode 100644
index 0000000000000..a526a346c6580
--- /dev/null
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/SystemPropsAsBuildTimeConfigSourceTest.java
@@ -0,0 +1,52 @@
+package io.quarkus.gradle;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.Properties;
+
+import org.junit.jupiter.api.Test;
+
+public class SystemPropsAsBuildTimeConfigSourceTest extends QuarkusGradleWrapperTestBase {
+
+ @Test
+ public void testBasicMultiModuleBuild() throws Exception {
+
+ final File projectDir = getProjectDir("system-props-as-build-time-config-source");
+
+ final File appProperties = new File(projectDir, "application/gradle.properties");
+ final File extensionProperties = new File(projectDir, "extensions/example-extension/gradle.properties");
+
+ final Path projectProperties = projectDir.toPath().resolve("gradle.properties");
+
+ try {
+ Files.copy(projectProperties, appProperties.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(projectProperties, extensionProperties.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unable to copy gradle.properties file", e);
+ }
+
+ gradleConfigurationCache(false);
+ runGradleWrapper(projectDir,
+ "-Dquarkus.example.name=cheburashka",
+ "-Dquarkus.example.runtime-name=crocodile",
+ "-Dquarkus.package.type=mutable-jar",
+ ":example-extension:example-extension-deployment:build",
+ // this quarkusIntTest will make sure runtime config properties passed as env vars when launching the app are effective
+ ":application:quarkusIntTest");
+
+ final Path buildSystemPropsPath = projectDir.toPath().resolve("application").resolve("build").resolve("quarkus-app")
+ .resolve("quarkus").resolve("build-system.properties");
+ assertThat(buildSystemPropsPath).exists();
+ var props = new Properties();
+ try (var reader = Files.newBufferedReader(buildSystemPropsPath)) {
+ props.load(reader);
+ }
+ assertThat(props).doesNotContainKey("quarkus.example.name");
+ assertThat(props).doesNotContainKey("quarkus.example.runtime-name");
+ }
+}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java
index 28c01e9c43934..cf7904ca9b6a0 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/nativeimage/BasicJavaNativeBuildIT.java
@@ -20,7 +20,7 @@ public class BasicJavaNativeBuildIT extends QuarkusNativeGradleITBase {
public void shouldBuildNativeImage() throws Exception {
final File projectDir = getProjectDir("basic-java-native-module");
- final BuildResult build = runGradleWrapper(projectDir, "clean", "buildNative", "-Dquarkus.package.type=fast-jar");
+ final BuildResult build = runGradleWrapper(projectDir, "clean", "buildNative");
assertThat(build.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
final String buildOutput = build.getOutput();
@@ -48,7 +48,7 @@ public void shouldBuildNativeImage() throws Exception {
public void shouldBuildNativeImageWithCustomName() throws Exception {
final File projectDir = getProjectDir("basic-java-native-module");
- final BuildResult build = runGradleWrapper(projectDir, "clean", "buildNative", "-Dquarkus.package.type=fast-jar",
+ final BuildResult build = runGradleWrapper(projectDir, "clean", "buildNative",
"-Dquarkus.package.output-name=test");
assertThat(build.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
@@ -78,7 +78,7 @@ public void shouldBuildNativeImageWithCustomName() throws Exception {
public void shouldBuildNativeImageWithCustomNameWithoutSuffix() throws Exception {
final File projectDir = getProjectDir("basic-java-native-module");
- final BuildResult build = runGradleWrapper(projectDir, "clean", "buildNative", "-Dquarkus.package.type=fast-jar",
+ final BuildResult build = runGradleWrapper(projectDir, "clean", "buildNative",
"-Dquarkus.package.output-name=test", "-Dquarkus.package.add-runner-suffix=false");
assertThat(build.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);