Merge pull request #40225 from radcortez/sr-config-3.8.0

Update SmallRye Config to 3.8.1
This commit is contained in:
Guillaume Smet 2024-04-27 15:19:11 +02:00 committed by GitHub
commit 9a768bbec0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 389 additions and 187 deletions

View File

@ -51,7 +51,7 @@
<microprofile-lra.version>2.0</microprofile-lra.version>
<microprofile-openapi.version>3.1.1</microprofile-openapi.version>
<smallrye-common.version>2.3.0</smallrye-common.version>
<smallrye-config.version>3.7.1</smallrye-config.version>
<smallrye-config.version>3.8.1</smallrye-config.version>
<smallrye-health.version>4.1.0</smallrye-health.version>
<smallrye-metrics.version>4.0.0</smallrye-metrics.version>
<smallrye-open-api.version>3.10.0</smallrye-open-api.version>

View File

@ -50,6 +50,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-development-mode-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-validator-spi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-class-change-agent</artifactId>

View File

@ -10,6 +10,10 @@ import io.quarkus.builder.item.MultiBuildItem;
public final class ConfigClassBuildItem extends MultiBuildItem {
private final Class<?> configClass;
/**
* All the config interfaces registered for this config mapping (including the nested ones)
*/
private final Set<Class<?>> configComponentInterfaces;
private final Set<Type> types;
private final Set<String> generatedClasses;
private final String prefix;
@ -19,12 +23,14 @@ public final class ConfigClassBuildItem extends MultiBuildItem {
public ConfigClassBuildItem(
final Class<?> configClass,
final Set<Class<?>> configComponentInterfaces,
final Set<Type> types,
final Set<String> generatedClasses,
final String prefix,
final Kind kind) {
this.configClass = configClass;
this.configComponentInterfaces = configComponentInterfaces;
this.types = types;
this.generatedClasses = generatedClasses;
this.prefix = prefix;
@ -36,6 +42,10 @@ public final class ConfigClassBuildItem extends MultiBuildItem {
return configClass;
}
public Set<Class<?>> getConfigComponentInterfaces() {
return configComponentInterfaces;
}
public Set<Type> getTypes() {
return types;
}

View File

@ -524,12 +524,6 @@ public final class BuildTimeConfigurationReader {
buildTimeRunTimeValues.putAll(getDefaults(config, buildTimeRunTimePatternMap));
runTimeDefaultValues.putAll(getDefaults(runtimeConfig, runTimePatternMap));
// Register defaults for Mappings
// Runtime defaults are added in ConfigGenerationBuildStep.generateBuilders to include user mappings
for (ConfigClassWithPrefix buildTimeRunTimeMapping : buildTimeRunTimeMappings) {
buildTimeRunTimeValues.putAll(ConfigMappings.getDefaults(buildTimeRunTimeMapping));
}
Set<String> registeredRoots = allRoots.stream().map(RootDefinition::getName).collect(toSet());
registeredRoots.add("quarkus");
Set<String> allProperties = getAllProperties(registeredRoots);
@ -1118,7 +1112,7 @@ public final class BuildTimeConfigurationReader {
}
});
String[] profiles = config.getProfiles().toArray(String[]::new);
List<String> profiles = config.getProfiles();
for (String property : builder.build().getPropertyNames()) {
properties.add(ProfileConfigSourceInterceptor.activeName(property, profiles));
}

View File

@ -25,7 +25,9 @@ import io.quarkus.deployment.builditem.ConfigClassBuildItem;
import io.quarkus.deployment.builditem.ConfigClassBuildItem.Kind;
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.quarkus.deployment.util.ReflectUtil;
import io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.ConfigMappingInterface;
import io.smallrye.config.ConfigMappingInterface.LeafProperty;
@ -46,7 +48,9 @@ public class ConfigMappingUtils {
CombinedIndexBuildItem combinedIndex,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigClassBuildItem> configClasses,
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses,
DotName configAnnotation) {
for (AnnotationInstance instance : combinedIndex.getIndex().getAnnotations(configAnnotation)) {
@ -61,7 +65,7 @@ public class ConfigMappingUtils {
String prefix = Optional.ofNullable(annotationPrefix).map(AnnotationValue::asString).orElse("");
Kind configClassKind = getConfigClassType(instance);
processConfigClass(configClassWithPrefix(configClass, prefix), configClassKind, true, combinedIndex,
generatedClasses, reflectiveClasses, configClasses);
generatedClasses, reflectiveClasses, reflectiveMethods, configClasses, additionalConstrainedClasses);
}
}
@ -69,8 +73,11 @@ public class ConfigMappingUtils {
CombinedIndexBuildItem combinedIndex,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ConfigClassBuildItem> configClasses) {
processConfigClasses(combinedIndex, generatedClasses, reflectiveClasses, configClasses, CONFIG_MAPPING_NAME);
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigClassBuildItem> configClasses,
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
processConfigClasses(combinedIndex, generatedClasses, reflectiveClasses, reflectiveMethods, configClasses,
additionalConstrainedClasses, CONFIG_MAPPING_NAME);
}
public static void processExtensionConfigMapping(
@ -78,10 +85,12 @@ public class ConfigMappingUtils {
CombinedIndexBuildItem combinedIndex,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ConfigClassBuildItem> configClasses) {
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigClassBuildItem> configClasses,
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
processConfigClass(configClass, Kind.MAPPING, false, combinedIndex, generatedClasses, reflectiveClasses,
configClasses);
reflectiveMethods, configClasses, additionalConstrainedClasses);
}
private static void processConfigClass(
@ -91,30 +100,37 @@ public class ConfigMappingUtils {
CombinedIndexBuildItem combinedIndex,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ConfigClassBuildItem> configClasses) {
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigClassBuildItem> configClasses,
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
Class<?> configClass = configClassWithPrefix.getKlass();
String prefix = configClassWithPrefix.getPrefix();
List<ConfigMappingMetadata> configMappingsMetadata = ConfigMappingLoader.getConfigMappingsMetadata(configClass);
Set<String> generatedClassesNames = new HashSet<>();
// all the config interfaces including nested ones
Set<Class<?>> configComponentInterfaces = new HashSet<>();
configMappingsMetadata.forEach(mappingMetadata -> {
generatedClassesNames.add(mappingMetadata.getClassName());
// This is the generated implementation of the mapping by SmallRye Config.
byte[] classBytes = mappingMetadata.getClassBytes();
generatedClasses.produce(new GeneratedClassBuildItem(isApplicationClass, mappingMetadata.getClassName(),
mappingMetadata.getClassBytes()));
// Register the interface and implementation methods for reflection. This is required for Bean Validation.
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(mappingMetadata.getInterfaceType()).methods().build());
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(mappingMetadata.getClassName()).methods().build());
// Register also the interface hierarchy
for (Class<?> parent : getHierarchy(mappingMetadata.getInterfaceType())) {
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(parent).methods().build());
}
classBytes));
additionalConstrainedClasses.produce(AdditionalConstrainedClassBuildItem.of(mappingMetadata.getClassName(),
classBytes));
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(mappingMetadata.getClassName()).constructors().build());
reflectiveMethods
.produce(new ReflectiveMethodBuildItem(mappingMetadata.getClassName(), "getDefaults", new String[0]));
reflectiveMethods.produce(new ReflectiveMethodBuildItem(mappingMetadata.getClassName(), "getNames", new String[0]));
configComponentInterfaces.add(mappingMetadata.getInterfaceType());
processProperties(mappingMetadata.getInterfaceType(), reflectiveClasses);
});
configClasses.produce(new ConfigClassBuildItem(configClass, collectTypes(combinedIndex, configClass),
configClasses.produce(new ConfigClassBuildItem(configClass, configComponentInterfaces,
collectTypes(combinedIndex, configClass),
generatedClassesNames, prefix, configClassKind));
}
@ -125,7 +141,6 @@ public class ConfigMappingUtils {
ConfigMappingInterface mapping = ConfigMappingLoader.getConfigMapping(configClass);
for (Property property : mapping.getProperties()) {
Class<?> returnType = property.getMethod().getReturnType();
reflectiveClasses.produce(ReflectiveClassBuildItem.builder(returnType).methods().build());
if (property.hasConvertWith()) {
Class<? extends Converter<?>> convertWith;

View File

@ -1197,24 +1197,24 @@ public final class RunTimeConfigurationGenerator {
Object.class);
private void generateUnknownFilter() {
Set<String> mappedProperties = new HashSet<>();
Set<String> names = new HashSet<>();
for (ConfigClassWithPrefix buildTimeMapping : buildTimeConfigResult.getBuildTimeMappings()) {
mappedProperties.addAll(ConfigMappings.getKeys(buildTimeMapping));
names.addAll(ConfigMappings.getProperties(buildTimeMapping).keySet());
}
for (ConfigClassWithPrefix staticConfigMapping : buildTimeConfigResult.getBuildTimeRunTimeMappings()) {
mappedProperties.addAll(ConfigMappings.getKeys(staticConfigMapping));
names.addAll(ConfigMappings.getProperties(staticConfigMapping).keySet());
}
for (ConfigClassWithPrefix runtimeConfigMapping : buildTimeConfigResult.getRunTimeMappings()) {
mappedProperties.addAll(ConfigMappings.getKeys(runtimeConfigMapping));
names.addAll(ConfigMappings.getProperties(runtimeConfigMapping).keySet());
}
// Add a method that generates a KeyMap that can check if a property is mapped by a @ConfigMapping
MethodCreator mc = cc.getMethodCreator(C_MAPPED_PROPERTIES);
mc.setModifiers(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC);
ResultHandle keyMap = mc.newInstance(KM_NEW);
for (String mappedProperty : mappedProperties) {
ResultHandle mappedPropertyKeyMap = mc.invokeVirtualMethod(KM_FIND_OR_ADD, keyMap, mc.load(mappedProperty));
mc.invokeVirtualMethod(KM_PUT_ROOT_VALUE, mappedPropertyKeyMap, mc.load(true));
for (String name : names) {
mc.invokeVirtualMethod(KM_PUT_ROOT_VALUE, mc.invokeVirtualMethod(KM_FIND_OR_ADD, keyMap, mc.load(name)),
mc.load(true));
}
mc.returnValue(keyMap);

View File

@ -123,8 +123,7 @@ public class ConfigDescriptionBuildStep {
private void processMappings(List<ConfigClassWithPrefix> mappings, List<ConfigDescriptionBuildItem> descriptionBuildItems,
Properties javaDocProperties, ConfigPhase configPhase) {
for (ConfigClassWithPrefix mapping : mappings) {
Map<String, Property> properties = ConfigMappings.getProperties(mapping).get(mapping.getKlass())
.get(mapping.getPrefix());
Map<String, Property> properties = ConfigMappings.getProperties(mapping);
for (Map.Entry<String, Property> entry : properties.entrySet()) {
String propertyName = entry.getKey();
Property property = entry.getValue();

View File

@ -59,6 +59,7 @@ import io.quarkus.deployment.builditem.ShutdownContextBuildItem;
import io.quarkus.deployment.builditem.StaticInitConfigBuilderBuildItem;
import io.quarkus.deployment.builditem.SuppressNonRuntimeConfigChangedWarningBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.quarkus.deployment.configuration.BuildTimeConfigurationReader;
import io.quarkus.deployment.configuration.RunTimeConfigurationGenerator;
import io.quarkus.deployment.configuration.tracker.ConfigTrackingConfig;
@ -73,6 +74,7 @@ import io.quarkus.gizmo.FieldDescriptor;
import io.quarkus.gizmo.MethodCreator;
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem;
import io.quarkus.paths.PathCollection;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.annotations.StaticInitSafe;
@ -86,7 +88,6 @@ import io.quarkus.runtime.configuration.RuntimeConfigBuilder;
import io.quarkus.runtime.configuration.RuntimeOverrideConfigSource;
import io.quarkus.runtime.configuration.RuntimeOverrideConfigSourceBuilder;
import io.quarkus.runtime.configuration.StaticInitConfigBuilder;
import io.smallrye.config.ConfigMappings;
import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix;
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigSourceInterceptor;
@ -176,19 +177,23 @@ public class ConfigGenerationBuildStep {
CombinedIndexBuildItem combinedIndex,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ConfigClassBuildItem> configClasses) {
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigClassBuildItem> configClasses,
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
processConfigMapping(combinedIndex, generatedClasses, reflectiveClasses, configClasses);
processConfigMapping(combinedIndex, generatedClasses, reflectiveClasses, reflectiveMethods, configClasses,
additionalConstrainedClasses);
List<ConfigClassWithPrefix> buildTimeRunTimeMappings = configItem.getReadResult().getBuildTimeRunTimeMappings();
for (ConfigClassWithPrefix buildTimeRunTimeMapping : buildTimeRunTimeMappings) {
processExtensionConfigMapping(buildTimeRunTimeMapping, combinedIndex, generatedClasses, reflectiveClasses,
configClasses);
reflectiveMethods, configClasses, additionalConstrainedClasses);
}
List<ConfigClassWithPrefix> runTimeMappings = configItem.getReadResult().getRunTimeMappings();
for (ConfigClassWithPrefix runTimeMapping : runTimeMappings) {
processExtensionConfigMapping(runTimeMapping, combinedIndex, generatedClasses, reflectiveClasses, configClasses);
processExtensionConfigMapping(runTimeMapping, combinedIndex, generatedClasses, reflectiveClasses, reflectiveMethods,
configClasses, additionalConstrainedClasses);
}
}
@ -203,14 +208,6 @@ public class ConfigGenerationBuildStep {
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) throws Exception {
Map<String, String> defaultValues = new HashMap<>();
// Default values from extensions @ConfigMapping
for (ConfigClassWithPrefix runTimeMapping : configItem.getReadResult().getRunTimeMappings()) {
defaultValues.putAll(ConfigMappings.getDefaults(runTimeMapping));
}
// Default values from user @ConfigMapping
for (ConfigMappingBuildItem configMapping : configMappings) {
defaultValues.putAll(ConfigMappings.getDefaults(configMapping.toConfigClassWithPrefix()));
}
// Default values from @ConfigRoot
defaultValues.putAll(configItem.getReadResult().getRunTimeDefaultValues());
// Default values from build item RunTimeConfigurationDefaultBuildItem override
@ -218,7 +215,7 @@ public class ConfigGenerationBuildStep {
defaultValues.put(e.getKey(), e.getValue());
}
// Recorded values from build time from any other source (higher ordinal then defaults, so override)
String[] profiles = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class).getProfiles().toArray(String[]::new);
List<String> profiles = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class).getProfiles();
for (Map.Entry<String, String> entry : configItem.getReadResult().getRunTimeValues().entrySet()) {
// Runtime values may contain active profiled names that override sames names in defaults
// We need to keep the original name definition in case a different profile is used to run the app
@ -244,8 +241,6 @@ public class ConfigGenerationBuildStep {
staticMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings());
Set<String> staticCustomizers = new HashSet<>(staticSafeServices(configCustomizers));
staticCustomizers.add(StaticInitConfigBuilder.class.getName());
String staticMappingsInfoClassName = "io.quarkus.runtime.generated.StaticInitMappingsInfo";
generateMappingsInfo(generatedClass, reflectiveClass, staticMappingsInfoClassName, staticMappings);
generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_STATIC_NAME,
defaultValues,
@ -257,7 +252,6 @@ public class ConfigGenerationBuildStep {
staticSafeServices(configSourceFactories),
secretKeyHandlers,
staticSafeServices(secretKeyHandlerFactories),
staticMappingsInfoClassName,
staticMappings,
staticCustomizers,
staticInitConfigBuilders.stream().map(StaticInitConfigBuilderBuildItem::getBuilderClassName).collect(toSet()));
@ -270,8 +264,6 @@ public class ConfigGenerationBuildStep {
runTimeMappings.addAll(configItem.getReadResult().getRunTimeMappings());
Set<String> runtimeCustomizers = new HashSet<>(configCustomizers);
runtimeCustomizers.add(RuntimeConfigBuilder.class.getName());
String runtimeMappingsInfoClassName = "io.quarkus.runtime.generated.RunTimeMappingsInfo";
generateMappingsInfo(generatedClass, reflectiveClass, runtimeMappingsInfoClassName, runTimeMappings);
generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_RUNTIME_NAME,
defaultValues,
@ -283,7 +275,6 @@ public class ConfigGenerationBuildStep {
configSourceFactories,
secretKeyHandlers,
secretKeyHandlerFactories,
runtimeMappingsInfoClassName,
runTimeMappings,
runtimeCustomizers,
runTimeConfigBuilders.stream().map(RunTimeConfigBuilderBuildItem::getBuilderClassName).collect(toSet()));
@ -518,66 +509,6 @@ public class ConfigGenerationBuildStep {
return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
}
private static final MethodDescriptor MAP_PUT = MethodDescriptor.ofMethod(HashMap.class,
"put", Object.class, Object.class, Object.class);
private static final MethodDescriptor SET_ADD = MethodDescriptor.ofMethod(HashSet.class,
"add", boolean.class, Object.class);
private static void generateMappingsInfo(
BuildProducer<GeneratedClassBuildItem> generatedClass,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
String className,
Set<ConfigClassWithPrefix> mappings) {
try (ClassCreator classCreator = ClassCreator.builder()
.classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true))
.className(className)
.setFinal(true)
.build()) {
for (ConfigMappings.ConfigClassWithPrefix mapping : mappings) {
generateMappingNames(classCreator, mapping);
}
MethodCreator keys = classCreator.getMethodCreator("keys", Set.class);
keys.setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle set = keys.checkCast(keys.newInstance(MethodDescriptor.ofConstructor(HashSet.class)), Set.class);
for (ConfigMappings.ConfigClassWithPrefix mapping : mappings) {
for (String key : ConfigMappings.getKeys(mapping)) {
keys.invokeVirtualMethod(SET_ADD, set, keys.load(key));
}
}
keys.returnValue(set);
}
reflectiveClass.produce(ReflectiveClassBuildItem.builder(className).build());
}
private static void generateMappingNames(ClassCreator classCreator, ConfigMappings.ConfigClassWithPrefix mapping) {
MethodCreator method = classCreator.getMethodCreator(
mapping.getKlass().getName().replaceAll("\\.", "_") + "_" + mapping.getPrefix().hashCode(), Map.class);
method.setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
Map<String, Map<String, Set<String>>> properties = ConfigMappings.getNames(mapping);
ResultHandle map = method.checkCast(
method.newInstance(MethodDescriptor.ofConstructor(HashMap.class, int.class), method.load(properties.size())),
Map.class);
for (Map.Entry<String, Map<String, Set<String>>> entry : properties.entrySet()) {
ResultHandle groups = method.checkCast(method.newInstance(MethodDescriptor.ofConstructor(HashMap.class, int.class),
method.load(entry.getValue().size())), Map.class);
for (Map.Entry<String, Set<String>> group : entry.getValue().entrySet()) {
ResultHandle names = method
.checkCast(method.newInstance(MethodDescriptor.ofConstructor(HashSet.class, int.class),
method.load(group.getValue().size())), Set.class);
for (String name : group.getValue()) {
method.invokeVirtualMethod(SET_ADD, names, method.load(name));
}
method.invokeVirtualMethod(MAP_PUT, groups, method.load(group.getKey()), names);
}
method.invokeVirtualMethod(MAP_PUT, map, method.load(entry.getKey()), groups);
}
method.returnValue(map);
}
private static final MethodDescriptor BUILDER_CUSTOMIZER = MethodDescriptor.ofMethod(SmallRyeConfigBuilderCustomizer.class,
"configBuilder",
void.class, SmallRyeConfigBuilder.class);
@ -635,7 +566,6 @@ public class ConfigGenerationBuildStep {
Set<String> configSourceFactories,
Set<String> secretKeyHandlers,
Set<String> secretKeyHandlerFactories,
String mappingsInfoClassName,
Set<ConfigClassWithPrefix> mappings,
Set<String> configCustomizers,
Set<String> configBuilders) {
@ -700,13 +630,7 @@ public class ConfigGenerationBuildStep {
for (ConfigClassWithPrefix mapping : mappings) {
method.invokeStaticMethod(WITH_MAPPING, configBuilder, method.load(mapping.getKlass().getName()),
method.load(mapping.getPrefix()));
ResultHandle names = method.invokeStaticMethod(MethodDescriptor.ofMethod(mappingsInfoClassName,
mapping.getKlass().getName().replaceAll("\\.", "_") + "_" + mapping.getPrefix().hashCode(), Map.class));
method.invokeVirtualMethod(WITH_NAMES, configBuilder, names);
}
ResultHandle keys = method
.invokeStaticMethod(MethodDescriptor.ofMethod(mappingsInfoClassName, "keys", Set.class));
method.invokeVirtualMethod(WITH_KEYS, configBuilder, keys);
method.returnVoid();
}

View File

@ -13,8 +13,6 @@ public class RuntimeConfigBuilder implements SmallRyeConfigBuilderCustomizer {
@Override
public void configBuilder(final SmallRyeConfigBuilder builder) {
new QuarkusConfigBuilderCustomizer().configBuilder(builder);
builder.withMappingDefaults(false);
builder.withDefaultValue("quarkus.uuid", UUID.randomUUID().toString());
builder.forClassLoader(Thread.currentThread().getContextClassLoader())

View File

@ -11,7 +11,6 @@ public class StaticInitConfigBuilder implements SmallRyeConfigBuilderCustomizer
@Override
public void configBuilder(final SmallRyeConfigBuilder builder) {
new QuarkusConfigBuilderCustomizer().configBuilder(builder);
builder.withMappingDefaults(false);
builder.forClassLoader(Thread.currentThread().getContextClassLoader())
.addDefaultInterceptors()

View File

@ -8,6 +8,7 @@ import java.util.List;
import java.util.concurrent.Callable;
import io.smallrye.config.ConfigValue;
import io.smallrye.config.Converters;
import picocli.CommandLine;
@CommandLine.Command(name = "set")
@ -46,6 +47,12 @@ public class SetConfig extends BaseConfigCommand implements Callable<Integer> {
if (encryptionKey.getValue() != null) {
args.add("--key=" + encryptionKey.getValue());
}
ConfigValue encryptionDecode = findKey(lines,
"smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key-decode");
if (encryptionDecode.getValue() == null
|| !Converters.getImplicitConverter(Boolean.class).convert(encryptionDecode.getValue())) {
args.add("--format=plain");
}
int execute = new CommandLine(encrypt).execute(args.toArray(new String[] {}));
if (execute < 0) {

View File

@ -81,7 +81,6 @@ class SetConfigTest {
assertTrue(result.getStdout().contains("Adding foo.bar"));
SmallRyeConfig config = config();
assertEquals("aes-gcm-nopadding", config.getConfigValue("foo.bar").getExtendedExpressionHandler());
assertEquals("1234", config.getConfigValue("foo.bar").getValue());
String encryption = config.getRawValue("smallrye.config.secret-handler.aes-gcm-nopadding.encryption-key");
@ -93,13 +92,9 @@ class SetConfigTest {
config = config();
assertEquals("aes-gcm-nopadding", config.getConfigValue("foo.bar").getExtendedExpressionHandler());
assertEquals("1234", config.getConfigValue("foo.bar").getValue());
assertTrue(config.isPropertyPresent("foo.baz"));
// TODO - radcortez - Requires update in SmallRye Config
//assertEquals("aes-gcm-nopadding", config.getConfigValue("foo.baz").getExtendedExpressionHandler());
//assertEquals("5678", config.getConfigValue("foo.baz").getValue());
assertEquals("5678", config.getConfigValue("foo.baz").getValue());
}
@Test
@ -118,14 +113,12 @@ class SetConfigTest {
assertEquals(0, result.getExitCode());
SmallRyeConfig config = config();
assertEquals("aes-gcm-nopadding", config.getConfigValue("foo.bar").getExtendedExpressionHandler());
assertEquals("1234", config.getConfigValue("foo.bar").getValue());
}
private SmallRyeConfig config() throws Exception {
final PropertiesConfigSource propertiesConfigSource = new PropertiesConfigSource(
PropertiesConfigSource propertiesConfigSource = new PropertiesConfigSource(
tempDir.resolve("src/main/resources/application.properties").toUri().toURL());
System.out.println(propertiesConfigSource.getProperties());
return new SmallRyeConfigBuilder()
.addDefaultInterceptors()
.addDiscoveredSecretKeysHandlers()

View File

@ -68,9 +68,11 @@ import io.quarkus.deployment.builditem.ConfigPropertiesBuildItem;
import io.quarkus.deployment.builditem.ConfigurationBuildItem;
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.quarkus.deployment.configuration.definition.RootDefinition;
import io.quarkus.deployment.recording.RecorderContext;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem;
import io.quarkus.runtime.annotations.ConfigPhase;
import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix;
import io.smallrye.config.inject.ConfigProducer;
@ -287,9 +289,12 @@ public class ConfigBuildStep {
CombinedIndexBuildItem combinedIndex,
BuildProducer<GeneratedClassBuildItem> generatedClasses,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ConfigClassBuildItem> configClasses) {
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigClassBuildItem> configClasses,
BuildProducer<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses) {
processConfigClasses(combinedIndex, generatedClasses, reflectiveClasses, configClasses, MP_CONFIG_PROPERTIES_NAME);
processConfigClasses(combinedIndex, generatedClasses, reflectiveClasses, reflectiveMethods, configClasses,
additionalConstrainedClasses, MP_CONFIG_PROPERTIES_NAME);
}
@BuildStep
@ -489,6 +494,7 @@ public class ConfigBuildStep {
List<ConfigMappingBuildItem> configMappings,
List<ConfigPropertiesBuildItem> configProperties) throws Exception {
// TODO - Register ConfigProperties during build time
context.registerNonDefaultConstructor(
ConfigClassWithPrefix.class.getDeclaredConstructor(Class.class, String.class),
configClassWithPrefix -> Stream.of(configClassWithPrefix.getKlass(), configClassWithPrefix.getPrefix())

View File

@ -2,6 +2,8 @@ package io.quarkus.hibernate.validator.deployment;
import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.annotation.Repeatable;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@ -43,8 +45,10 @@ import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.CompositeIndex;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.logging.Logger;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@ -60,6 +64,7 @@ import io.quarkus.arc.processor.BeanInfo;
import io.quarkus.arc.processor.BuiltinScope;
import io.quarkus.arc.processor.DotNames;
import io.quarkus.bootstrap.classloading.QuarkusClassLoader;
import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.Capability;
import io.quarkus.deployment.Feature;
@ -103,6 +108,7 @@ import io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyConfigSupport;
import io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyReactiveViolationExceptionMapper;
import io.quarkus.hibernate.validator.runtime.jaxrs.ResteasyViolationExceptionMapper;
import io.quarkus.hibernate.validator.runtime.jaxrs.ViolationReport;
import io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem;
import io.quarkus.hibernate.validator.spi.BeanValidationAnnotationsBuildItem;
import io.quarkus.jaxrs.spi.deployment.AdditionalJaxRsResourceMethodAnnotationsBuildItem;
import io.quarkus.resteasy.common.spi.ResteasyConfigBuildItem;
@ -111,14 +117,14 @@ import io.quarkus.resteasy.common.spi.ResteasyJaxrsProviderBuildItem;
import io.quarkus.resteasy.reactive.spi.ExceptionMapperBuildItem;
import io.quarkus.runtime.LocalesBuildTimeConfig;
import io.quarkus.runtime.configuration.ConfigBuilder;
import io.smallrye.config.ConfigMappingLoader;
import io.smallrye.config.ConfigMappingMetadata;
import io.smallrye.config.ConfigValidator;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.config.validator.BeanValidationConfigValidator;
class HibernateValidatorProcessor {
private static final Logger LOG = Logger.getLogger(HibernateValidatorProcessor.class);
private static final String META_INF_VALIDATION_XML = "META-INF/validation.xml";
private static final DotName CONSTRAINT_VALIDATOR_FACTORY = DotName
@ -168,9 +174,19 @@ class HibernateValidatorProcessor {
void beanValidationAnnotations(
BeanArchiveIndexBuildItem beanArchiveIndexBuildItem,
CombinedIndexBuildItem combinedIndexBuildItem,
Optional<AdditionalConstrainedClassesIndexBuildItem> additionalConstrainedClassesIndexBuildItem,
BuildProducer<BeanValidationAnnotationsBuildItem> beanValidationAnnotations) {
IndexView indexView = CompositeIndex.create(beanArchiveIndexBuildItem.getIndex(), combinedIndexBuildItem.getIndex());
IndexView indexView;
if (additionalConstrainedClassesIndexBuildItem.isPresent()) {
// we use both indexes to support both generated beans and jars that contain no CDI beans but only Validation annotations
// we also add the additional constrained classes
indexView = CompositeIndex.create(beanArchiveIndexBuildItem.getIndex(), combinedIndexBuildItem.getIndex(),
additionalConstrainedClassesIndexBuildItem.get().getIndex());
} else {
indexView = CompositeIndex.create(beanArchiveIndexBuildItem.getIndex(), combinedIndexBuildItem.getIndex());
}
Set<DotName> constraints = new HashSet<>();
Set<String> builtinConstraints = ConstraintHelper.getBuiltinConstraints();
@ -217,19 +233,24 @@ class HibernateValidatorProcessor {
Set<DotName> configMappings = new HashSet<>();
Set<DotName> configClassesToValidate = new HashSet<>();
Map<DotName, Map<DotName, ConfigClassBuildItem>> embeddingMap = new HashMap<>();
for (ConfigClassBuildItem configClass : configClasses) {
for (String generatedConfigClass : configClass.getGeneratedClasses()) {
DotName simple = DotName.createSimple(generatedConfigClass);
configClassesToValidate.add(simple);
}
for (ConfigMappingMetadata mappingsMetadata : ConfigMappingLoader
.getConfigMappingsMetadata(configClass.getConfigClass())) {
configMappings.add(DotName.createSimple(mappingsMetadata.getInterfaceType()));
}
configClass.getConfigComponentInterfaces().stream().map(DotName::createSimple)
.forEach(cm -> {
configMappings.add(cm);
embeddingMap.computeIfAbsent(cm, c -> new HashMap<>())
.putIfAbsent(configClass.getName(), configClass);
});
}
Set<DotName> constrainedConfigMappings = new HashSet<>();
Set<String> configMappingsConstraints = new HashSet<>();
for (DotName consideredAnnotation : beanValidationAnnotations.getAllAnnotations()) {
Collection<AnnotationInstance> annotationInstances = combinedIndex.getIndex().getAnnotations(consideredAnnotation);
@ -246,6 +267,7 @@ class HibernateValidatorProcessor {
ClassInfo declaringClass = methodInfo.declaringClass();
if (configMappings.contains(declaringClass.name())) {
configMappingsConstraints.add(builtinConstraintCandidate);
constrainedConfigMappings.add(declaringClass.name());
}
} else if (annotation.target().kind() == AnnotationTarget.Kind.TYPE) {
AnnotationTarget target = annotation.target().asType().enclosingTarget();
@ -254,12 +276,14 @@ class HibernateValidatorProcessor {
ClassInfo declaringClass = methodInfo.declaringClass();
if (configMappings.contains(declaringClass.name())) {
configMappingsConstraints.add(builtinConstraintCandidate);
constrainedConfigMappings.add(declaringClass.name());
}
}
} else if (annotation.target().kind() == AnnotationTarget.Kind.CLASS) {
ClassInfo classInfo = annotation.target().asClass();
if (configMappings.contains(classInfo.name())) {
configMappingsConstraints.add(builtinConstraintCandidate);
constrainedConfigMappings.add(classInfo.name());
}
}
}
@ -269,6 +293,26 @@ class HibernateValidatorProcessor {
return;
}
// if in the tree of a ConfigMapping, there is one constraint, we register the whole tree
// we might be able to do some more advanced surgery with Jandex evolution but for now
// that's the best we can do
Set<DotName> configComponentsInterfacesToRegisterForReflection = new HashSet<>();
for (DotName constrainedConfigMapping : constrainedConfigMappings) {
if (!embeddingMap.containsKey(constrainedConfigMapping)) {
// should never happen but let's be safe
continue;
}
embeddingMap.get(constrainedConfigMapping).values().stream()
.map(c -> c.getConfigComponentInterfaces())
.flatMap(Collection::stream)
.map(DotName::createSimple)
.forEach(configComponentsInterfacesToRegisterForReflection::add);
}
reflectiveClass.produce(ReflectiveClassBuildItem.builder(
configComponentsInterfacesToRegisterForReflection.stream().map(DotName::toString).toArray(String[]::new))
.methods().build());
String builderClassName = HibernateBeanValidationConfigValidator.class.getName() + "Builder";
try (ClassCreator classCreator = ClassCreator.builder()
.classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true))
@ -406,6 +450,7 @@ class HibernateValidatorProcessor {
BuildProducer<AnnotationsTransformerBuildItem> annotationsTransformers,
BeanArchiveIndexBuildItem beanArchiveIndexBuildItem,
CombinedIndexBuildItem combinedIndexBuildItem,
Optional<AdditionalConstrainedClassesIndexBuildItem> additionalConstrainedClassesIndexBuildItem,
BuildProducer<FeatureBuildItem> feature,
BuildProducer<BeanContainerListenerBuildItem> beanContainerListener,
BuildProducer<UnremovableBeanBuildItem> unremovableBeans,
@ -418,8 +463,16 @@ class HibernateValidatorProcessor {
feature.produce(new FeatureBuildItem(Feature.HIBERNATE_VALIDATOR));
// we use both indexes to support both generated beans and jars that contain no CDI beans but only Validation annotations
IndexView indexView = CompositeIndex.create(beanArchiveIndexBuildItem.getIndex(), combinedIndexBuildItem.getIndex());
IndexView indexView;
if (additionalConstrainedClassesIndexBuildItem.isPresent()) {
// we use both indexes to support both generated beans and jars that contain no CDI beans but only Validation annotations
// we also add the additional constrained classes
indexView = CompositeIndex.create(beanArchiveIndexBuildItem.getIndex(), combinedIndexBuildItem.getIndex(),
additionalConstrainedClassesIndexBuildItem.get().getIndex());
} else {
indexView = CompositeIndex.create(beanArchiveIndexBuildItem.getIndex(), combinedIndexBuildItem.getIndex());
}
Set<DotName> classNamesToBeValidated = new HashSet<>();
Map<DotName, Set<SimpleMethodSignatureKey>> methodsWithInheritedValidation = new HashMap<>();
@ -537,6 +590,30 @@ class HibernateValidatorProcessor {
hibernateValidatorBuildTimeConfig)));
}
@BuildStep
void indexAdditionalConstrainedClasses(List<AdditionalConstrainedClassBuildItem> additionalConstrainedClasses,
BuildProducer<AdditionalConstrainedClassesIndexBuildItem> additionalConstrainedClassesIndex) {
if (additionalConstrainedClasses.isEmpty()) {
return;
}
// Create an index with additional constrained classes
Indexer indexer = new Indexer();
for (AdditionalConstrainedClassBuildItem additionalConstrainedClass : additionalConstrainedClasses) {
try {
if (additionalConstrainedClass.isGenerated()) {
indexer.index(new ByteArrayInputStream(additionalConstrainedClass.getBytes()));
} else {
indexer.indexClass(additionalConstrainedClass.getClazz());
}
} catch (IOException e) {
LOG.warnf(e, "Unable to index constrained class %s", additionalConstrainedClass.getName());
}
}
additionalConstrainedClassesIndex.produce(new AdditionalConstrainedClassesIndexBuildItem(indexer.complete()));
}
@BuildStep
void optionalResourceBundles(BuildProducer<NativeImageResourceBundleBuildItem> resourceBundles) {
String[] potentialHibernateValidatorResourceBundles = {
@ -728,4 +805,16 @@ class HibernateValidatorProcessor {
return Thread.currentThread().getContextClassLoader().getResource(META_INF_VALIDATION_XML) != null;
}
private static final class AdditionalConstrainedClassesIndexBuildItem extends SimpleBuildItem {
private final IndexView index;
private AdditionalConstrainedClassesIndexBuildItem(IndexView index) {
this.index = index;
}
public IndexView getIndex() {
return index;
}
}
}

View File

@ -16,7 +16,11 @@
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
<artifactId>quarkus-builder</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>jandex</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,48 @@
package io.quarkus.hibernate.validator.spi;
import io.quarkus.builder.item.MultiBuildItem;
public final class AdditionalConstrainedClassBuildItem extends MultiBuildItem {
private static final byte[] EMPTY = new byte[0];
private final Class<?> clazz;
private final String name;
private final byte[] bytes;
private AdditionalConstrainedClassBuildItem(Class<?> clazz) {
this.clazz = clazz;
this.name = clazz.getName();
this.bytes = EMPTY;
}
private AdditionalConstrainedClassBuildItem(String name, byte[] bytes) {
this.clazz = null;
this.name = name;
this.bytes = bytes;
}
public static AdditionalConstrainedClassBuildItem of(Class<?> clazz) {
return new AdditionalConstrainedClassBuildItem(clazz);
}
public static AdditionalConstrainedClassBuildItem of(String name, byte[] bytes) {
return new AdditionalConstrainedClassBuildItem(name, bytes);
}
public Class<?> getClazz() {
return clazz;
}
public String getName() {
return name;
}
public byte[] getBytes() {
return bytes;
}
public boolean isGenerated() {
return clazz == null;
}
}

View File

@ -61,6 +61,7 @@ public class EagerSecurityFilter implements ContainerRequestFilter {
var interceptorStorageHandle = Arc.container().instance(EagerSecurityInterceptorStorage.class);
this.interceptorStorage = interceptorStorageHandle.isAvailable() ? interceptorStorageHandle.get() : null;
Event<Object> event = Arc.container().beanManager().getEvent();
// TODO - quarkus.security.events.enabled was marked as runtime, but providers are initialized during static init
this.eventHelper = new SecurityEventHelper<>(event.select(AuthorizationSuccessEvent.class),
event.select(AuthorizationFailureEvent.class), AUTHORIZATION_SUCCESS, AUTHORIZATION_FAILURE,
Arc.container().beanManager(),

View File

@ -9,7 +9,7 @@ import io.smallrye.config.WithDefault;
* Quarkus Security configuration.
*/
@ConfigMapping(prefix = "quarkus.security")
@ConfigRoot(phase = ConfigPhase.RUN_TIME)
@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public interface SecurityConfig {
/**

View File

@ -9,7 +9,7 @@ analysis_results.fields.reachable=30176
analysis_results.fields.reachable.tolerance=3
analysis_results.types.reflection=6585
analysis_results.types.reflection.tolerance=3
analysis_results.methods.reflection=4786
analysis_results.methods.reflection=4556
analysis_results.methods.reflection.tolerance=3
analysis_results.fields.reflection=147
analysis_results.fields.reflection.tolerance=3

View File

@ -9,7 +9,7 @@ analysis_results.fields.reachable=30098
analysis_results.fields.reachable.tolerance=3
analysis_results.types.reflection=6705
analysis_results.types.reflection.tolerance=3
analysis_results.methods.reflection=4893
analysis_results.methods.reflection=4551
analysis_results.methods.reflection.tolerance=3
analysis_results.fields.reflection=170
analysis_results.fields.reflection.tolerance=3

View File

@ -9,7 +9,7 @@ analysis_results.fields.reachable=27443
analysis_results.fields.reachable.tolerance=3
analysis_results.types.reflection=6128
analysis_results.types.reflection.tolerance=3
analysis_results.methods.reflection=4608
analysis_results.methods.reflection=4374
analysis_results.methods.reflection.tolerance=3
analysis_results.fields.reflection=176
analysis_results.fields.reflection.tolerance=3

View File

@ -9,7 +9,7 @@ analysis_results.fields.reachable=27389
analysis_results.fields.reachable.tolerance=3
analysis_results.types.reflection=6232
analysis_results.types.reflection.tolerance=3
analysis_results.methods.reflection=4708
analysis_results.methods.reflection=4367
analysis_results.methods.reflection.tolerance=3
analysis_results.fields.reflection=201
analysis_results.fields.reflection.tolerance=3

View File

@ -4,6 +4,9 @@ import java.util.Optional;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.quarkus.runtime.annotations.RegisterForReflection;
@RegisterForReflection
public interface Alias extends Named {
@JsonProperty
Optional<String> alias();

View File

@ -1,13 +1,136 @@
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
Server server();
Map<String, Form> form();
Optional<Ssl> ssl();
Optional<Proxy> proxy();
Optional<Cors> cors();
Log log();
Info info();
interface Form {
String loginPage();
String errorPage();
String landingPage();
Optional<String> cookie();
@WithDefault("1")
List<Integer> positions();
}
interface Ssl {
int port();
String certificate();
@WithDefault("TLSv1.3,TLSv1.2")
List<String> 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<Origin> 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<List<@Size(max = 3) String>> alias();
Map<String, List<Admin>> admins();
Map<String, List<@Size(min = 8, max = 15) String>> firewall();
interface Admin {
@Size(max = 4)
String username();
}
}
}

View File

@ -4,6 +4,9 @@ import java.util.Optional;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.quarkus.runtime.annotations.RegisterForReflection;
@RegisterForReflection
public interface Named {
@JsonProperty
Optional<String> name();

View File

@ -23,7 +23,7 @@ public @interface Prod {
class Validator implements ConstraintValidator<Prod, Cloud> {
@Override
public boolean isValid(final Cloud value, final ConstraintValidatorContext context) {
return value.server().equals("prod");
return value.host().equals("prod");
}
}
}

View File

@ -8,10 +8,6 @@ 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 org.eclipse.microprofile.config.spi.Converter;
import com.fasterxml.jackson.annotation.JsonProperty;
@ -25,12 +21,12 @@ import io.smallrye.config.WithName;
import io.smallrye.config.WithParentName;
@ConfigMapping(prefix = "http.server")
@RegisterForReflection
public interface Server extends Alias {
@JsonProperty
String host();
@JsonProperty
@Min(8000)
int port();
@JsonProperty
@ -63,6 +59,7 @@ public interface Server extends Alias {
@JsonProperty
Info info();
@RegisterForReflection
interface Form {
@JsonProperty
String loginPage();
@ -81,15 +78,16 @@ public interface Server extends Alias {
List<Integer> positions();
}
@RegisterForReflection
interface Proxy {
@JsonProperty
boolean enable();
@JsonProperty
@Max(10)
int timeout();
}
@RegisterForReflection
interface Log {
@JsonProperty
@WithDefault("false")
@ -111,7 +109,6 @@ public interface Server extends Alias {
Period period();
@JsonProperty
@Max(15)
int days();
@RegisterForReflection
@ -123,44 +120,44 @@ public interface Server extends Alias {
}
}
@RegisterForReflection
interface Cors {
@JsonProperty
List<Origin> origins();
@JsonProperty
List<@Size(min = 2) String> methods();
List<String> methods();
@RegisterForReflection
interface Origin {
@JsonProperty
@Size(min = 5)
String host();
@JsonProperty
@Min(8000)
int port();
}
}
@RegisterForReflection
interface Info {
@JsonProperty
Optional<@Size(max = 3) String> name();
Optional<String> name();
@JsonProperty
@Max(3)
OptionalInt code();
@JsonProperty
Optional<List<@Size(max = 3) String>> alias();
Optional<List<String>> alias();
@JsonProperty
Map<String, List<Admin>> admins();
@JsonProperty
Map<String, List<@Size(min = 8, max = 15) String>> firewall();
Map<String, List<String>> firewall();
@RegisterForReflection
interface Admin {
@JsonProperty
@Size(max = 4)
String username();
}
}

View File

@ -1,6 +1,5 @@
package io.quarkus.it.smallrye.config;
import java.lang.reflect.Method;
import java.util.List;
import jakarta.enterprise.inject.Instance;
@ -40,13 +39,6 @@ public class ServerResource {
return Response.ok(server).build();
}
@GET
@Path("/host")
public Response getServerHost() throws Exception {
Method method = server.getClass().getDeclaredMethod("host");
return Response.ok(method.invoke(server)).build();
}
@GET
@Path("/properties")
public Response getServerProperties() {

View File

@ -4,9 +4,10 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.smallrye.config.WithDefault;
// TODO - Add hierarchy here but requires https://github.com/smallrye/smallrye-config/pull/590
@RegisterForReflection
public interface Ssl {
@JsonProperty
int port();

View File

@ -36,7 +36,7 @@ http:
cloud:
host: localhost
port: 8080
port: 5000
timeout: 60s
io-threads: 200

View File

@ -22,6 +22,6 @@ public class AppConfigTest {
containsString("name=app"),
containsString("count=10"),
containsString("alias=alias"),
endsWith("}}"));
endsWith("}"));
}
}

View File

@ -47,15 +47,6 @@ class ServerResourceTest {
.body("log.period", equalTo("P1D"));
}
@Test
void serverHost() {
given()
.get("/server/host")
.then()
.statusCode(OK.getStatusCode())
.body(equalTo("localhost"));
}
@Test
void properties() {
given()
@ -93,7 +84,8 @@ class ServerResourceTest {
.get("/server/validator/{prefix}", "cloud")
.then()
.statusCode(OK.getStatusCode())
.body("errors", hasSize(9))
.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"))