diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 71d5baec96ea3..53c0c1581d886 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -47,7 +47,7 @@
2.0
4.0.2
2.9.0
- 3.10.2
+ 3.11.1
4.1.1
4.0.0
4.0.6
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java
index 5c8ef29854607..774ee4784759f 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/BuildTimeConfigurationReader.java
@@ -1212,7 +1212,7 @@ private static void getDefaults(
.withName(propertyName.toString())
.withValue(defaultValue)
.withRawValue(defaultValue)
- .withConfigSourceName("DefaultValuesConfigSource")
+ .withConfigSourceName(DefaultValuesConfigSource.NAME)
.withConfigSourceOrdinal(Integer.MIN_VALUE)
.build());
}
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java
index 32f567f0c38d7..cc32fafb9e737 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/ConfigMappingUtils.java
@@ -122,9 +122,7 @@ private static void processConfigClass(
.reason(ConfigMappingUtils.class.getName())
.build());
reflectiveMethods.produce(new ReflectiveMethodBuildItem(ConfigMappingUtils.class.getName(),
- mappingMetadata.getClassName(), "getDefaults", new String[0]));
- reflectiveMethods.produce(new ReflectiveMethodBuildItem(ConfigMappingUtils.class.getName(),
- mappingMetadata.getClassName(), "getNames", new String[0]));
+ mappingMetadata.getClassName(), "getProperties", new String[0]));
configComponentInterfaces.add(mappingMetadata.getInterfaceType());
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
index 2fcfed8eea5f6..15b092b40d967 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
@@ -6,7 +6,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.Collection;
+import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -64,8 +64,6 @@
import io.quarkus.runtime.configuration.NameIterator;
import io.quarkus.runtime.configuration.PropertiesUtil;
import io.quarkus.runtime.configuration.QuarkusConfigFactory;
-import io.smallrye.config.ConfigMappingInterface;
-import io.smallrye.config.ConfigMappings;
import io.smallrye.config.ConfigMappings.ConfigClass;
import io.smallrye.config.Converters;
import io.smallrye.config.PropertyName;
@@ -89,7 +87,6 @@ public final class RunTimeConfigurationGenerator {
void.class);
public static final MethodDescriptor C_READ_CONFIG = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "readConfig", void.class);
- static final FieldDescriptor C_MAPPED_PROPERTIES = FieldDescriptor.of(CONFIG_CLASS_NAME, "mappedProperties", Set.class);
static final FieldDescriptor C_UNKNOWN = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknown", Set.class);
static final FieldDescriptor C_UNKNOWN_RUNTIME = FieldDescriptor.of(CONFIG_CLASS_NAME, "unknownRuntime", Set.class);
@@ -149,6 +146,7 @@ public final class RunTimeConfigurationGenerator {
boolean.class, String.class);
static final MethodDescriptor NI_NEXT = MethodDescriptor.ofMethod(NameIterator.class, "next", void.class);
static final MethodDescriptor NI_PREVIOUS = MethodDescriptor.ofMethod(NameIterator.class, "previous", void.class);
+ static final MethodDescriptor NI_GO_TO_START = MethodDescriptor.ofMethod(NameIterator.class, "goToStart", void.class);
static final MethodDescriptor OBJ_TO_STRING = MethodDescriptor.ofMethod(Object.class, "toString", String.class);
@@ -186,18 +184,16 @@ public final class RunTimeConfigurationGenerator {
static final MethodDescriptor SRCB_BUILD = MethodDescriptor.ofMethod(SmallRyeConfigBuilder.class, "build",
SmallRyeConfig.class);
+ static final MethodDescriptor PU_IS_MAPPED = MethodDescriptor.ofMethod(PropertiesUtil.class, "isMapped", boolean.class,
+ NameIterator.class, String.class);
static final MethodDescriptor PU_IS_PROPERTY_QUARKUS_COMPOUND_NAME = MethodDescriptor.ofMethod(PropertiesUtil.class,
"isPropertyQuarkusCompoundName", boolean.class, NameIterator.class);
static final MethodDescriptor PU_IS_PROPERTY_IN_ROOTS = MethodDescriptor.ofMethod(PropertiesUtil.class, "isPropertyInRoots",
boolean.class, String.class, Set.class);
+
static final MethodDescriptor HS_NEW = MethodDescriptor.ofConstructor(HashSet.class);
static final MethodDescriptor HS_NEW_SIZED = MethodDescriptor.ofConstructor(HashSet.class, int.class);
static final MethodDescriptor HS_ADD = MethodDescriptor.ofMethod(HashSet.class, "add", boolean.class, Object.class);
- static final MethodDescriptor HS_ADD_ALL = MethodDescriptor.ofMethod(HashSet.class, "addAll", boolean.class,
- Collection.class);
- static final MethodDescriptor HS_CONTAINS = MethodDescriptor.ofMethod(HashSet.class, "contains", boolean.class,
- Object.class);
- static final MethodDescriptor PN_NEW = MethodDescriptor.ofConstructor(PropertyName.class, String.class);
// todo: more space-efficient sorted map impl
static final MethodDescriptor TM_NEW = MethodDescriptor.ofConstructor(TreeMap.class);
@@ -274,17 +270,13 @@ public static final class GenerateOperation implements AutoCloseable {
clinit = cc.getMethodCreator(MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "", void.class));
clinit.setModifiers(Opcodes.ACC_STATIC);
- cc.getFieldCreator(C_MAPPED_PROPERTIES).setModifiers(Opcodes.ACC_STATIC);
- clinit.writeStaticField(C_MAPPED_PROPERTIES, clinit.newInstance(HS_NEW_SIZED,
- clinit.load((int) ((float) buildTimeConfigResult.getAllMappingsNames().size() / 0.75f + 1.0f))));
-
cc.getFieldCreator(C_UNKNOWN).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_UNKNOWN, clinit.newInstance(HS_NEW));
cc.getFieldCreator(C_UNKNOWN_RUNTIME).setModifiers(Opcodes.ACC_STATIC);
clinit.writeStaticField(C_UNKNOWN_RUNTIME, clinit.newInstance(HS_NEW));
- generateMappedProperties();
+ generateIsMapped();
clinitNameBuilder = clinit.newInstance(SB_NEW);
@@ -530,14 +522,18 @@ private void configSweepLoop(MethodDescriptor parserBody, MethodCreator method,
.trueBranch()) {
ResultHandle key = hasNext.checkCast(hasNext.invokeInterfaceMethod(ITR_NEXT, iterator), String.class);
- // !mappedProperties.contains(new PropertyName(key)) continue sweepLoop;
- hasNext.ifNonZero(
- hasNext.invokeVirtualMethod(HS_CONTAINS, hasNext.readStaticField(C_MAPPED_PROPERTIES),
- hasNext.newInstance(PN_NEW, key)))
- .trueBranch().continueScope(sweepLoop);
-
// NameIterator keyIter = new NameIterator(key);
ResultHandle keyIter = hasNext.newInstance(NI_NEW_STRING, key);
+ // if (!isMappedProperty(keyIter))
+ ResultHandle isMappedName = hasNext.invokeStaticMethod(
+ MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "isMapped", boolean.class, NameIterator.class),
+ keyIter);
+ try (BytecodeCreator isMappedPropertyTrue = hasNext.ifTrue(isMappedName).trueBranch()) {
+ isMappedPropertyTrue.continueScope(sweepLoop);
+ }
+
+ // keyIter.goToStart() - reset the NameIterator so it can be used by the ConfigRoot code
+ hasNext.invokeVirtualMethod(NI_GO_TO_START, keyIter);
// if (PropertiesUtil.isPropertyQuarkusCompoundName(keyIter))
BranchResult quarkusCompoundName = hasNext
@@ -1186,33 +1182,74 @@ private FieldDescriptor getOrCreateConverterInstance(Field field, ConverterType
return fd;
}
- private void generateMappedProperties() {
- MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, "addMappedProperties", void.class);
- MethodCreator mc = cc.getMethodCreator(method);
- mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
- for (ConfigClass mapping : buildTimeConfigResult.getAllMappings()) {
- mc.invokeStaticMethod(generateMappedProperties(mapping, buildTimeConfigResult.getAllMappingsNames()));
+ private void generateIsMapped() {
+ Map names = buildTimeConfigResult.getAllMappingsNames();
+ ConfigPatternMap patterns = new ConfigPatternMap<>();
+ for (Map.Entry entry : names.entrySet()) {
+ NameIterator name = new NameIterator(entry.getValue());
+ ConfigPatternMap current = patterns;
+ while (name.hasNext()) {
+ String segment = name.getNextSegment();
+ ConfigPatternMap child = current.getChild(segment);
+ if (child == null) {
+ child = new ConfigPatternMap<>();
+ current.addChild(segment, child);
+ }
+ current = child;
+ name.next();
+ }
+ current.setMatched(true);
}
- mc.returnVoid();
- mc.close();
- clinit.invokeStaticMethod(method);
+
+ generateIsMapped("isMapped", patterns);
}
- private MethodDescriptor generateMappedProperties(final ConfigClass mapping,
- final Map propertyNames) {
- MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME,
- "addMappedProperties$" + mapping.getKlass().getName().replace('.', '$'), void.class);
+ private void generateIsMapped(final String methodName, final ConfigPatternMap names) {
+ MethodDescriptor method = MethodDescriptor.ofMethod(CONFIG_CLASS_NAME, methodName, boolean.class,
+ NameIterator.class);
MethodCreator mc = cc.getMethodCreator(method);
mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
- Map properties = ConfigMappings.getProperties(mapping);
- ResultHandle set = mc.readStaticField(C_MAPPED_PROPERTIES);
- for (String propertyName : properties.keySet()) {
- String name = propertyNames.get(new PropertyName(propertyName));
- mc.invokeVirtualMethod(HS_ADD, set, mc.newInstance(PN_NEW, mc.load(name)));
+
+ ResultHandle nameIterator = mc.getMethodParam(0);
+ BranchResult hasNext = mc.ifTrue(mc.invokeVirtualMethod(NI_HAS_NEXT, nameIterator));
+
+ try (BytecodeCreator hasNextTrue = hasNext.trueBranch()) {
+ ArrayDeque childNames = new ArrayDeque<>();
+ // * matching has to come last
+ for (String childName : names.childNames()) {
+ if (childName.startsWith("*")) {
+ childNames.addLast(childName);
+ } else {
+ childNames.addFirst(childName);
+ }
+ }
+
+ for (String childName : childNames) {
+ ConfigPatternMap child = names.getChild(childName);
+ BranchResult nextEquals = hasNextTrue
+ .ifTrue(hasNextTrue.invokeStaticMethod(PU_IS_MAPPED, nameIterator, hasNextTrue.load(childName)));
+ try (BytecodeCreator nextEqualsTrue = nextEquals.trueBranch()) {
+ String childMethodName = methodName + "$" + childName.replace("[*]", "-collection");
+ if (child.getMatched() == null) {
+ generateIsMapped(childMethodName, child);
+ nextEqualsTrue.invokeVirtualMethod(NI_NEXT, nameIterator);
+ nextEqualsTrue
+ .returnValue(nextEqualsTrue.invokeStaticMethod(MethodDescriptor.ofMethod(CONFIG_CLASS_NAME,
+ childMethodName, boolean.class, NameIterator.class), nameIterator));
+ } else {
+ nextEqualsTrue.returnBoolean(true);
+ }
+ }
+ }
+ hasNextTrue.returnBoolean(false);
}
- mc.returnVoid();
+
+ try (BytecodeCreator hasNextFalse = hasNext.falseBranch()) {
+ hasNextFalse.returnBoolean(false);
+ }
+
+ mc.returnBoolean(false);
mc.close();
- return method;
}
private void reportUnknown(BytecodeCreator bc, ResultHandle unknownProperty) {
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
index 24ab9fad7b140..a8d4b305e2fc4 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/ConfigGenerationBuildStep.java
@@ -227,7 +227,7 @@ void generateBuilders(
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
List profiles = config.getProfiles();
for (Map.Entry entry : configItem.getReadResult().getRunTimeValues().entrySet()) {
- if ("DefaultValuesConfigSource".equals(entry.getValue().getConfigSourceName())) {
+ if (DefaultValuesConfigSource.NAME.equals(entry.getValue().getConfigSourceName())) {
continue;
}
// Runtime values may contain active profiled names that override sames names in defaults
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/DeprecatedRuntimePropertiesRecorder.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/DeprecatedRuntimePropertiesRecorder.java
index 994e2fbd5c0dc..e26aada4e53a9 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/DeprecatedRuntimePropertiesRecorder.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/DeprecatedRuntimePropertiesRecorder.java
@@ -7,6 +7,7 @@
import org.jboss.logging.Logger;
import io.quarkus.runtime.annotations.Recorder;
+import io.smallrye.config.DefaultValuesConfigSource;
import io.smallrye.config.SmallRyeConfig;
@Recorder
@@ -20,7 +21,7 @@ public void reportDeprecatedProperties(Set deprecatedRuntimeProperties)
if (deprecatedRuntimeProperties.contains(property)) {
String configSourceName = ((SmallRyeConfig) config).getConfigValue(property).getConfigSourceName();
// this condition can be removed when support of the @ConfigRoot annotation on classes is removed
- if ("DefaultValuesConfigSource".equals(configSourceName)) {
+ if (DefaultValuesConfigSource.NAME.equals(configSourceName)) {
continue;
}
log.warnf("The '%s' config property is deprecated and should not be used anymore", property);
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java
index 7c51a8707538e..74055336f70e8 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/PropertiesUtil.java
@@ -2,11 +2,19 @@
import java.util.Set;
+import io.smallrye.config.PropertyName;
+
public class PropertiesUtil {
private PropertiesUtil() {
throw new IllegalStateException("Utility class");
}
+ public static boolean isMapped(final NameIterator name, final String mapped) {
+ int offset = name.getPosition() == -1 ? 0 : name.getPosition() + 1;
+ int len = name.getNextEnd() == 0 ? name.getName().length() : name.getNextEnd() - offset;
+ return PropertyName.equals(name.getName(), offset, len, mapped, 0, mapped.length());
+ }
+
public static boolean isPropertyInRoots(final String property, final Set roots) {
for (String root : roots) {
if (isPropertyInRoot(property, root)) {
diff --git a/devtools/gradle/gradle/libs.versions.toml b/devtools/gradle/gradle/libs.versions.toml
index 45c9107126256..69f2aa9ec9b2c 100644
--- a/devtools/gradle/gradle/libs.versions.toml
+++ b/devtools/gradle/gradle/libs.versions.toml
@@ -3,7 +3,7 @@ plugin-publish = "1.3.0"
# updating Kotlin here makes QuarkusPluginTest > shouldNotFailOnProjectDependenciesWithoutMain(Path) fail
kotlin = "2.0.21"
-smallrye-config = "3.10.2"
+smallrye-config = "3.11.1"
junit5 = "5.10.5"
assertj = "3.27.2"
diff --git a/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/config/ConfigMappingInvalidTest.java b/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/config/ConfigMappingInvalidTest.java
index 696b7a2dc61f9..cedf4a2bc434c 100644
--- a/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/config/ConfigMappingInvalidTest.java
+++ b/extensions/hibernate-validator/deployment/src/test/java/io/quarkus/hibernate/validator/test/config/ConfigMappingInvalidTest.java
@@ -1,56 +1,76 @@
package io.quarkus.hibernate.validator.test.config;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.time.Duration;
+import java.time.Period;
import java.util.List;
-
-import jakarta.inject.Inject;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
+import java.util.function.Consumer;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import jakarta.validation.Payload;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import io.quarkus.arc.Unremovable;
+import io.quarkus.runtime.configuration.DurationConverter;
import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.ConfigValidationException;
-import io.smallrye.config.SmallRyeConfig;
+import io.smallrye.config.WithConverter;
+import io.smallrye.config.WithDefault;
+import io.smallrye.config.WithName;
+import io.smallrye.config.WithParentName;
public class ConfigMappingInvalidTest {
@RegisterExtension
- static final QuarkusUnitTest UNIT_TEST = new QuarkusUnitTest().setArchiveProducer(
+ static final QuarkusUnitTest TEST = new QuarkusUnitTest().setArchiveProducer(
() -> ShrinkWrap.create(JavaArchive.class)
- .addAsResource(new StringAsset("validator.server.host=localhost\n" +
- "validator.server.services=redis,postgresql\n" +
- "validator.hierarchy.number=1\n" +
- "validator.repeatable.name=a"), "application.properties"));
-
- @Inject
- SmallRyeConfig config;
+ .addAsResource("application-mappings-validation.properties", "application.properties"))
+ .assertException(new Consumer() {
+ @Override
+ public void accept(final Throwable throwable) {
+ // can't use instanceOf because of different ClassLoaders
+ assertEquals(ConfigValidationException.class.getName(), throwable.getClass().getName());
+ String message = throwable.getMessage();
+ assertTrue(message.contains("validator.server.host must be less than or equal to 3"));
+ assertTrue(message.contains("validator.hierarchy.number must be greater than or equal to 10"));
+ assertTrue(message.contains("validator.repeatable.name size must be between 2"));
+
+ assertTrue(message.contains("cloud.port must be greater than or equal to 8000"));
+ assertTrue(message.contains("cloud.log.days must be less than or equal to 15"));
+ assertTrue(message.contains("cloud.cors.origins[1].port must be greater than or equal to 8000"));
+ assertTrue(message.contains("cloud.info.name size must be between 0 and 3"));
+ assertTrue(message.contains("cloud.info.code must be less than or equal to 3"));
+ assertTrue(message.contains("cloud.info.alias[0] size must be between 0 and 3"));
+ assertTrue(message.contains("cloud.info.admins.root[1].username size must be between 0 and 4"));
+ assertTrue(message.contains("cloud.info.firewall.accepted[1] size must be between 8 and 15"));
+ assertTrue(message.contains("cloud.proxy.timeout must be less than or equal to 10"));
+ assertTrue(message.contains("cloud server is not prod"));
+ }
+ });
@Test
void invalid() {
- assertThrows(ConfigValidationException.class, () -> config.getConfigMapping(Server.class),
- "validator.server.host must be less than or equal to 3");
- }
-
- @Test
- @Disabled("Requires https://github.com/smallrye/smallrye-config/pull/923")
- void invalidHierarchy() {
- assertThrows(ConfigValidationException.class, () -> config.getConfigMapping(Child.class),
- "validator.hierarchy.number must be greater than or equal to 10");
- }
-
- @Test
- void repeatable() {
- assertThrows(ConfigValidationException.class, () -> config.getConfigMapping(Repeatable.class));
+ fail();
}
@Unremovable
@@ -80,4 +100,138 @@ public interface Repeatable {
@Size(min = 2)
String name();
}
+
+ @Unremovable
+ @ConfigMapping(prefix = "cloud")
+ @Prod
+ public interface Cloud {
+ String host();
+
+ @Min(8000)
+ int port();
+
+ @WithConverter(DurationConverter.class)
+ Duration timeout();
+
+ @WithName("io-threads")
+ int threads();
+
+ @WithParentName
+ Map form();
+
+ Optional ssl();
+
+ Optional proxy();
+
+ Optional cors();
+
+ Log log();
+
+ Info info();
+
+ interface Form {
+ String loginPage();
+
+ String errorPage();
+
+ String landingPage();
+
+ Optional cookie();
+
+ @WithDefault("1")
+ List positions();
+ }
+
+ interface Ssl {
+ int port();
+
+ String certificate();
+
+ @WithDefault("TLSv1.3,TLSv1.2")
+ List protocols();
+ }
+
+ interface Proxy {
+ boolean enable();
+
+ @Max(10)
+ int timeout();
+ }
+
+ interface Log {
+ @WithDefault("false")
+ boolean enabled();
+
+ @WithDefault(".log")
+ String suffix();
+
+ @WithDefault("true")
+ boolean rotate();
+
+ @WithDefault("COMMON")
+ Pattern pattern();
+
+ Period period();
+
+ @Max(15)
+ int days();
+
+ enum Pattern {
+ COMMON,
+ SHORT,
+ COMBINED,
+ LONG;
+ }
+ }
+
+ interface Cors {
+ List origins();
+
+ List<@Size(min = 2) String> methods();
+
+ interface Origin {
+ @Size(min = 5)
+ String host();
+
+ @Min(8000)
+ int port();
+ }
+ }
+
+ interface Info {
+ Optional<@Size(max = 3) String> name();
+
+ @Max(3)
+ OptionalInt code();
+
+ Optional> alias();
+
+ Map> admins();
+
+ Map> firewall();
+
+ interface Admin {
+ @Size(max = 4)
+ String username();
+ }
+ }
+ }
+
+ @Target({ ElementType.TYPE_USE, ElementType.FIELD })
+ @Retention(RetentionPolicy.RUNTIME)
+ @Constraint(validatedBy = Prod.Validator.class)
+ public @interface Prod {
+ String message() default "server is not prod";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+
+ class Validator implements ConstraintValidator {
+ @Override
+ public boolean isValid(final Cloud value, final ConstraintValidatorContext context) {
+ return value.host().equals("prod");
+ }
+ }
+ }
}
diff --git a/extensions/hibernate-validator/deployment/src/test/resources/application-mappings-validation.properties b/extensions/hibernate-validator/deployment/src/test/resources/application-mappings-validation.properties
new file mode 100644
index 0000000000000..a94e71916cc37
--- /dev/null
+++ b/extensions/hibernate-validator/deployment/src/test/resources/application-mappings-validation.properties
@@ -0,0 +1,34 @@
+validator.server.host=localhost
+validator.server.services=redis,postgresql
+validator.hierarchy.number=1
+validator.repeatable.name=a
+
+cloud.host=localhost
+cloud.port=5000
+cloud.io-threads=200
+cloud.timeout=60s
+cloud.form.error-page=error.html
+cloud.form.landing-page=index.html
+cloud.form.login-page=login.html
+cloud.info.admins.root[0].username=root
+cloud.info.admins.root[1].username=super
+cloud.info.alias=James
+cloud.info.alias[0]=James
+cloud.info.code=007
+cloud.info.firewall.accepted=127.0.0.1,8.8.8
+cloud.info.firewall.accepted[0]=127.0.0.1
+cloud.info.firewall.accepted[1]=8.8.8
+cloud.info.name=Bond
+cloud.log.days=20
+cloud.log.period=P1D
+cloud.proxy.enable=true
+cloud.proxy.timeout=20
+cloud.ssl.certificate=certificate
+cloud.ssl.port=8443
+cloud.cors.methods=GET,POST
+cloud.cors.methods[0]=GET
+cloud.cors.methods[1]=POST
+cloud.cors.origins[0].host=some-server
+cloud.cors.origins[0].port=9000
+cloud.cors.origins[1].host=localhost
+cloud.cors.origins[1].port=1
diff --git a/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/config/runtime/KubernetesConfigSourceFactory.java b/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/config/runtime/KubernetesConfigSourceFactory.java
index f3a98ccec4ea5..39821839ce840 100644
--- a/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/config/runtime/KubernetesConfigSourceFactory.java
+++ b/extensions/kubernetes-config/runtime/src/main/java/io/quarkus/kubernetes/config/runtime/KubernetesConfigSourceFactory.java
@@ -16,6 +16,7 @@
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.Converters;
+import io.smallrye.config.DefaultValuesConfigSource;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigBuilder;
@@ -84,7 +85,7 @@ Iterable getConfigSources(final KubernetesConfigSourceConfig confi
private boolean isExplicitlyDisabled(ConfigSourceContext context) {
ConfigValue configValue = context.getValue("quarkus.kubernetes-config.enabled");
- if ("DefaultValuesConfigSource".equals(configValue.getConfigSourceName())) {
+ if (DefaultValuesConfigSource.NAME.equals(configValue.getConfigSourceName())) {
return false;
}
if (configValue.getValue() != null) {
diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/DependenciesProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/DependenciesProcessor.java
index 43d11dc5fe48c..eb38bd492003e 100644
--- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/DependenciesProcessor.java
+++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/DependenciesProcessor.java
@@ -25,6 +25,7 @@
import io.quarkus.maven.dependency.ArtifactCoords;
import io.quarkus.maven.dependency.ArtifactKey;
import io.quarkus.maven.dependency.ResolvedDependency;
+import io.smallrye.config.DefaultValuesConfigSource;
public class DependenciesProcessor {
@@ -84,7 +85,8 @@ void createBuildTimeActions(BuildProducer buildTimeAct
private boolean isEnabled() {
var value = ConfigProvider.getConfig().getConfigValue("quarkus.bootstrap.incubating-model-resolver");
// if it's not false and if it's false it doesn't come from the default value
- return value == null || !"false".equals(value.getValue()) || "DefaultValuesConfigSource".equals(value.getSourceName());
+ return value == null || !"false".equals(value.getValue())
+ || DefaultValuesConfigSource.NAME.equals(value.getSourceName());
}
private void buildTree(ApplicationModel model, Root root, Optional> allGavs, Optional toTarget) {
diff --git a/integration-tests/hibernate-validator-resteasy-reactive/src/test/java/io/quarkus/it/hibernate/validator/ConfigMappingStartupValidatorTest.java b/integration-tests/hibernate-validator-resteasy-reactive/src/test/java/io/quarkus/it/hibernate/validator/ConfigMappingStartupValidatorTest.java
deleted file mode 100644
index 16652a5a9c213..0000000000000
--- a/integration-tests/hibernate-validator-resteasy-reactive/src/test/java/io/quarkus/it/hibernate/validator/ConfigMappingStartupValidatorTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package io.quarkus.it.hibernate.validator;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import jakarta.inject.Inject;
-import jakarta.validation.constraints.Pattern;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-import io.quarkus.hibernate.validator.runtime.HibernateBeanValidationConfigValidator;
-import io.quarkus.runtime.configuration.QuarkusConfigFactory;
-import io.quarkus.test.junit.QuarkusTest;
-import io.quarkus.test.junit.QuarkusTestProfile;
-import io.quarkus.test.junit.TestProfile;
-import io.smallrye.config.ConfigMapping;
-import io.smallrye.config.ConfigMappingLoader;
-import io.smallrye.config.ConfigMappingMetadata;
-import io.smallrye.config.ConfigValidationException;
-import io.smallrye.config.ConfigValidationException.Problem;
-import io.smallrye.config.ConfigValidator;
-import io.smallrye.config.SmallRyeConfig;
-import io.smallrye.config.SmallRyeConfigBuilder;
-import io.smallrye.config.WithDefault;
-
-@QuarkusTest
-@TestProfile(ConfigMappingStartupValidatorTest.Profile.class)
-public class ConfigMappingStartupValidatorTest {
-
- @ConfigMapping(prefix = "config")
- public interface ConfigWithValidation {
- String CONFIG_WITH_VALIDATION_VALUE_MUST_BE_D_3 = "ConfigWithValidation.value() must be \"-\\d{3}\"";
-
- @WithDefault("invalid-value")
- @Pattern(regexp = "-\\d{3}", message = CONFIG_WITH_VALIDATION_VALUE_MUST_BE_D_3)
- String value();
- }
-
- public static class Profile implements QuarkusTestProfile {
- @Override
- public boolean disableGlobalTestResources() {
- return false;
- }
- }
-
- private static SmallRyeConfig smallryeConfig;
- private static Map, Exception> suppressedConfigValidatorExceptions;
-
- @Inject
- ConfigWithValidation config;
-
- @BeforeAll
- public static void doBefore() {
- Set constraints = Set.of(Pattern.class.getName());
- Set> classesToBeValidated = new HashSet<>();
- for (ConfigMappingMetadata configMappingMetadata : ConfigMappingLoader
- .getConfigMappingsMetadata(ConfigWithValidation.class)) {
- try {
- classesToBeValidated.add(Class.forName(configMappingMetadata.getClassName()));
- } catch (ClassNotFoundException e) {
- // Ignore
- }
- }
-
- SmallRyeConfigBuilder builder = new SmallRyeConfigBuilder();
- builder.withMapping(ConfigWithValidation.class).setAddDefaultSources(true)
- .withValidator(new ConfigValidator() {
- final ConfigValidator base = new HibernateBeanValidationConfigValidator(constraints, classesToBeValidated);
-
- @Override
- public void validateMapping(Class> mappingClass, String prefix, Object mappingObject)
- throws ConfigValidationException {
- try {
- base.validateMapping(mappingClass, prefix, mappingObject);
- } catch (Exception e) {
- suppressedConfigValidatorExceptions.put(mappingClass, e);
- }
- }
- });
- QuarkusConfigFactory.setConfig(smallryeConfig = builder.build());
- suppressedConfigValidatorExceptions = new HashMap<>();
- }
-
- @AfterAll
- public static void doAfter() {
- QuarkusConfigFactory.setConfig(null);
- smallryeConfig = null;
- suppressedConfigValidatorExceptions = null;
- }
-
- @Test
- public void test() {
- assertEquals("invalid-value", config.value());
- ConfigValidationException ex = assertThrows(ConfigValidationException.class, () -> {
- throw suppressedConfigValidatorExceptions.get(ConfigWithValidation.class);
- });
- assertEquals(1, ex.getProblemCount());
- final Problem problem = ex.getProblem(0);
- assertEquals("config.value " + ConfigWithValidation.CONFIG_WITH_VALIDATION_VALUE_MUST_BE_D_3, problem.getMessage());
- }
-}
diff --git a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/Cloud.java b/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/Cloud.java
deleted file mode 100644
index 74fd78e03b5e5..0000000000000
--- a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/Cloud.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package io.quarkus.it.smallrye.config;
-
-import java.time.Duration;
-import java.time.Period;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.OptionalInt;
-
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.Size;
-
-import io.quarkus.arc.Unremovable;
-import io.quarkus.runtime.configuration.DurationConverter;
-import io.smallrye.config.ConfigMapping;
-import io.smallrye.config.WithConverter;
-import io.smallrye.config.WithDefault;
-import io.smallrye.config.WithName;
-import io.smallrye.config.WithParentName;
-
-@Unremovable
-@ConfigMapping(prefix = "cloud")
-@Prod
-public interface Cloud {
- String host();
-
- @Min(8000)
- int port();
-
- @WithConverter(DurationConverter.class)
- Duration timeout();
-
- @WithName("io-threads")
- int threads();
-
- @WithParentName
- Map form();
-
- Optional ssl();
-
- Optional proxy();
-
- Optional cors();
-
- Log log();
-
- Info info();
-
- interface Form {
- String loginPage();
-
- String errorPage();
-
- String landingPage();
-
- Optional cookie();
-
- @WithDefault("1")
- List positions();
- }
-
- interface Ssl {
- int port();
-
- String certificate();
-
- @WithDefault("TLSv1.3,TLSv1.2")
- List protocols();
- }
-
- interface Proxy {
- boolean enable();
-
- @Max(10)
- int timeout();
- }
-
- interface Log {
- @WithDefault("false")
- boolean enabled();
-
- @WithDefault(".log")
- String suffix();
-
- @WithDefault("true")
- boolean rotate();
-
- @WithDefault("COMMON")
- Pattern pattern();
-
- Period period();
-
- @Max(15)
- int days();
-
- enum Pattern {
- COMMON,
- SHORT,
- COMBINED,
- LONG;
- }
- }
-
- interface Cors {
- List origins();
-
- List<@Size(min = 2) String> methods();
-
- interface Origin {
- @Size(min = 5)
- String host();
-
- @Min(8000)
- int port();
- }
- }
-
- interface Info {
- Optional<@Size(max = 3) String> name();
-
- @Max(3)
- OptionalInt code();
-
- Optional> alias();
-
- Map> admins();
-
- Map> firewall();
-
- interface Admin {
- @Size(max = 4)
- String username();
- }
- }
-}
diff --git a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/Prod.java b/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/Prod.java
deleted file mode 100644
index 0387cabd46b58..0000000000000
--- a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/Prod.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package io.quarkus.it.smallrye.config;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import jakarta.validation.Constraint;
-import jakarta.validation.ConstraintValidator;
-import jakarta.validation.ConstraintValidatorContext;
-import jakarta.validation.Payload;
-
-@Target({ ElementType.TYPE_USE, ElementType.FIELD })
-@Retention(RetentionPolicy.RUNTIME)
-@Constraint(validatedBy = Prod.Validator.class)
-public @interface Prod {
- String message() default "server is not prod";
-
- Class>[] groups() default {};
-
- Class extends Payload>[] payload() default {};
-
- class Validator implements ConstraintValidator {
- @Override
- public boolean isValid(final Cloud value, final ConstraintValidatorContext context) {
- return value.host().equals("prod");
- }
- }
-}
diff --git a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ServerResource.java b/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ServerResource.java
index 69205f27a8553..ca507f61583c2 100644
--- a/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ServerResource.java
+++ b/integration-tests/smallrye-config/src/main/java/io/quarkus/it/smallrye/config/ServerResource.java
@@ -4,24 +4,15 @@
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
-import jakarta.json.Json;
-import jakarta.json.JsonArrayBuilder;
-import jakarta.json.JsonObjectBuilder;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
-import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.inject.ConfigProperties;
import org.eclipse.microprofile.config.inject.ConfigProperty;
-import io.smallrye.config.ConfigValidationException;
-import io.smallrye.config.SmallRyeConfig;
-
@Path("/server")
public class ServerResource {
- @Inject
- Config config;
@Inject
Server server;
@Inject
@@ -45,26 +36,6 @@ public Response getServerProperties() {
return Response.ok(serverProperties).build();
}
- @GET
- @Path("/validator/cloud")
- public Response validator() {
- try {
- config.unwrap(SmallRyeConfig.class).getConfigMapping(Cloud.class, "cloud");
- } catch (ConfigValidationException e) {
- JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
- for (int i = 0; i < e.getProblemCount(); i++) {
- jsonArrayBuilder.add(e.getProblem(i).getMessage());
- }
- JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
- jsonObjectBuilder.add("errors", jsonArrayBuilder);
- return Response.ok().entity(jsonObjectBuilder.build().toString()).build();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return Response.serverError().build();
- }
-
@GET
@Path("/info")
public String info() {
diff --git a/integration-tests/smallrye-config/src/main/resources/application.yaml b/integration-tests/smallrye-config/src/main/resources/application.yaml
index 7da81f0bee2be..81e3e4e758693 100644
--- a/integration-tests/smallrye-config/src/main/resources/application.yaml
+++ b/integration-tests/smallrye-config/src/main/resources/application.yaml
@@ -34,55 +34,6 @@ http:
period: P1D
days: 10
-cloud:
- host: localhost
- port: 5000
- timeout: 60s
- io-threads: 200
-
- form:
- login-page: login.html
- error-page: error.html
- landing-page: index.html
-
- ssl:
- port: 8443
- certificate: certificate
-
- cors:
- origins:
- - host: some-server
- port: 9000
- - host: localhost
- port: 1
- methods:
- - GET
- - POST
-
- proxy:
- enable: true
- timeout: 20
-
- log:
- period: P1D
- days: 20
-
- info:
- name: Bond
- code: 007
- alias:
- - James
- admins:
- root:
- -
- username: root
- -
- username: super
- firewall:
- accepted:
- - 127.0.0.1
- - 8.8.8
-
profile:
main:
yaml: main
diff --git a/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/ServerResourceTest.java b/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/ServerResourceTest.java
index 400df4f21f128..0951ad1e8f5f8 100644
--- a/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/ServerResourceTest.java
+++ b/integration-tests/smallrye-config/src/test/java/io/quarkus/it/smallrye/config/ServerResourceTest.java
@@ -1,19 +1,13 @@
package io.quarkus.it.smallrye.config;
import static io.restassured.RestAssured.given;
-import static jakarta.ws.rs.core.HttpHeaders.ACCEPT;
-import static jakarta.ws.rs.core.HttpHeaders.CONTENT_TYPE;
-import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import static jakarta.ws.rs.core.Response.Status.OK;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasItem;
-import static org.hamcrest.Matchers.hasSize;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.http.Header;
@QuarkusTest
class ServerResourceTest {
@@ -75,25 +69,4 @@ void info() {
.header("X-VERSION", "1.2.3.4")
.body(containsString("My application info"));
}
-
- @Test
- void invalid() {
- given()
- .header(new Header(CONTENT_TYPE, APPLICATION_JSON))
- .header(new Header(ACCEPT, APPLICATION_JSON))
- .get("/server/validator/{prefix}", "cloud")
- .then()
- .statusCode(OK.getStatusCode())
- .body("errors", hasSize(10))
- .body("errors", hasItem("cloud.port must be greater than or equal to 8000"))
- .body("errors", hasItem("cloud.log.days must be less than or equal to 15"))
- .body("errors", hasItem("cloud.cors.origins[1].port must be greater than or equal to 8000"))
- .body("errors", hasItem("cloud.info.name size must be between 0 and 3"))
- .body("errors", hasItem("cloud.info.code must be less than or equal to 3"))
- .body("errors", hasItem("cloud.info.alias[0] size must be between 0 and 3"))
- .body("errors", hasItem("cloud.info.admins.root[1].username size must be between 0 and 4"))
- .body("errors", hasItem("cloud.info.firewall.accepted[1] size must be between 8 and 15"))
- .body("errors", hasItem("cloud.proxy.timeout must be less than or equal to 10"))
- .body("errors", hasItem("cloud server is not prod"));
- }
}