Skip to content

Update SmallRye Config to 3.12.0 #46249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
<microprofile-lra.version>2.0</microprofile-lra.version>
<microprofile-openapi.version>4.0.2</microprofile-openapi.version>
<smallrye-common.version>2.10.0</smallrye-common.version>
<smallrye-config.version>3.11.2</smallrye-config.version>
<smallrye-config.version>3.12.0</smallrye-config.version>
<smallrye-health.version>4.2.0</smallrye-health.version>
<smallrye-metrics.version>4.0.0</smallrye-metrics.version>
<smallrye-open-api.version>4.0.8</smallrye-open-api.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public boolean isStaticInitSafe() {
}

public ConfigClass toConfigClass() {
return new ConfigClass(configClass, prefix);
return ConfigClass.configClass(configClass, prefix);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ private static void registerImplicitConverter(

public static Object newInstance(Class<?> configClass) {
if (configClass.isAnnotationPresent(ConfigMapping.class)) {
return ReflectUtil.newInstance(ConfigMappingLoader.getImplementationClass(configClass));
// TODO - radcortez - mapping classes cannot be initialized like this.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand this comment?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is what causes #39431. There is no exception, since the object is created, but all the values are not populated since it didn't call the correct constructor.

I added the TODO there to fix that later... the code has been like this for some time without much incident, but I need to fix it.

return ReflectUtil.newInstance(ConfigMappingLoader.ensureLoaded(configClass).implementation());
} else {
return ReflectUtil.newInstance(configClass);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static io.quarkus.deployment.util.ReflectUtil.reportError;
import static io.quarkus.runtime.annotations.ConfigPhase.BUILD_AND_RUN_TIME_FIXED;
import static io.quarkus.runtime.annotations.ConfigPhase.RUN_TIME;
import static io.smallrye.config.common.utils.StringUtil.skewer;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
Expand Down Expand Up @@ -1231,7 +1232,8 @@ private void generateIsMapped(final String methodName, final ConfigPatternMap<Bo
BranchResult nextEquals = hasNextTrue
.ifTrue(hasNextTrue.invokeStaticMethod(PU_IS_MAPPED, nameIterator, hasNextTrue.load(childName)));
try (BytecodeCreator nextEqualsTrue = nextEquals.trueBranch()) {
String childMethodName = methodName + "$" + childName.replace("[*]", "-collection");
childName = childName.replace("[*]", "-collection");
String childMethodName = methodName + "$" + skewer(childName, '_');
if (child.getMatched() == null) {
generateIsMapped(childMethodName, child);
nextEqualsTrue.invokeVirtualMethod(NI_NEXT, nameIterator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem;
import io.quarkus.paths.PathCollection;
import io.quarkus.runtime.BuildAnalyticsConfig;
import io.quarkus.runtime.BuilderConfig;
import io.quarkus.runtime.CommandLineRuntimeConfig;
import io.quarkus.runtime.DebugRuntimeConfig;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.annotations.StaticInitSafe;
import io.quarkus.runtime.configuration.AbstractConfigBuilder;
Expand All @@ -94,6 +98,8 @@
import io.quarkus.runtime.configuration.RuntimeOverrideConfigSource;
import io.quarkus.runtime.configuration.RuntimeOverrideConfigSourceBuilder;
import io.quarkus.runtime.configuration.StaticInitConfigBuilder;
import io.smallrye.config.ConfigMappingLoader;
import io.smallrye.config.ConfigMappingMetadata;
import io.smallrye.config.ConfigMappings.ConfigClass;
import io.smallrye.config.ConfigSourceFactory;
import io.smallrye.config.ConfigSourceInterceptor;
Expand Down Expand Up @@ -257,15 +263,34 @@ void generateBuilders(
Set<String> secretKeyHandlerFactories = discoverService(SecretKeysHandlerFactory.class, reflectiveClass);
Set<String> configCustomizers = discoverService(SmallRyeConfigBuilderCustomizer.class, reflectiveClass);

// TODO - introduce a way to ignore mappings that are only used for documentation or to prevent warnings
Set<ConfigClass> ignoreMappings = new HashSet<>();
ignoreMappings.add(ConfigClass.configClass(BuildAnalyticsConfig.class, "quarkus.analytics"));
ignoreMappings.add(ConfigClass.configClass(BuilderConfig.class, "quarkus.builder"));
ignoreMappings.add(ConfigClass.configClass(CommandLineRuntimeConfig.class, "quarkus"));
ignoreMappings.add(ConfigClass.configClass(DebugRuntimeConfig.class, "quarkus.debug"));

Set<ConfigClass> allMappings = new HashSet<>();
allMappings.addAll(staticSafeConfigMappings(configMappings));
allMappings.addAll(runtimeConfigMappings(configMappings));
allMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings());
allMappings.addAll(configItem.getReadResult().getRunTimeMappings());
allMappings.removeAll(ignoreMappings);

// Shared components
Map<Object, FieldDescriptor> sharedFields = generateSharedConfig(generatedClass, converters, allMappings);

// For Static Init Config
Set<ConfigClass> staticMappings = new HashSet<>();
staticMappings.addAll(staticSafeConfigMappings(configMappings));
staticMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings());
staticMappings.removeAll(ignoreMappings);
Set<String> staticCustomizers = new HashSet<>(staticSafeServices(configCustomizers));
staticCustomizers.add(StaticInitConfigBuilder.class.getName());

generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_STATIC_NAME,
combinedIndex,
sharedFields,
defaultValues,
converters,
interceptors,
Expand All @@ -275,6 +300,7 @@ void generateBuilders(
staticSafeServices(configSourceFactories),
secretKeyHandlers,
staticSafeServices(secretKeyHandlerFactories),
Set.of(),
staticMappings,
staticCustomizers,
staticInitConfigBuilders.stream().map(StaticInitConfigBuilderBuildItem::getBuilderClassName).collect(toSet()));
Expand All @@ -285,11 +311,13 @@ void generateBuilders(
runTimeMappings.addAll(runtimeConfigMappings(configMappings));
runTimeMappings.addAll(configItem.getReadResult().getBuildTimeRunTimeMappings());
runTimeMappings.addAll(configItem.getReadResult().getRunTimeMappings());
runTimeMappings.removeAll(ignoreMappings);
Set<String> runtimeCustomizers = new HashSet<>(configCustomizers);
runtimeCustomizers.add(RuntimeConfigBuilder.class.getName());

generateConfigBuilder(generatedClass, reflectiveClass, CONFIG_RUNTIME_NAME,
combinedIndex,
sharedFields,
defaultValues,
converters,
interceptors,
Expand All @@ -299,6 +327,7 @@ void generateBuilders(
configSourceFactories,
secretKeyHandlers,
secretKeyHandlerFactories,
staticMappings,
runTimeMappings,
runtimeCustomizers,
runTimeConfigBuilders.stream().map(RunTimeConfigBuilderBuildItem::getBuilderClassName).collect(toSet()));
Expand Down Expand Up @@ -532,12 +561,12 @@ private static String getPathWithoutExtension(Path path) {
private static final MethodDescriptor BUILDER_CUSTOMIZER = MethodDescriptor.ofMethod(SmallRyeConfigBuilderCustomizer.class,
"configBuilder",
void.class, SmallRyeConfigBuilder.class);

private static final MethodDescriptor WITH_DEFAULT = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withDefaultValue",
void.class, SmallRyeConfigBuilder.class, String.class, String.class);
private static final MethodDescriptor WITH_DEFAULTS = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withDefaultValues",
void.class, SmallRyeConfigBuilder.class, Map.class);
private static final MethodDescriptor WITH_CONVERTER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withConverter", void.class, SmallRyeConfigBuilder.class, String.class, int.class, Converter.class);
"withConverter",
void.class, SmallRyeConfigBuilder.class, String.class, int.class, Converter.class);
private static final MethodDescriptor WITH_INTERCEPTOR = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withInterceptor",
void.class, SmallRyeConfigBuilder.class, ConfigSourceInterceptor.class);
Expand All @@ -554,27 +583,86 @@ private static String getPathWithoutExtension(Path path) {
"withSource",
void.class, SmallRyeConfigBuilder.class, ConfigSourceFactory.class);
private static final MethodDescriptor WITH_SECRET_HANDLER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withSecretKeyHandler", void.class, SmallRyeConfigBuilder.class, SecretKeysHandler.class);
"withSecretKeyHandler",
void.class, SmallRyeConfigBuilder.class, SecretKeysHandler.class);
private static final MethodDescriptor WITH_SECRET_HANDLER_FACTORY = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withSecretKeyHandler", void.class, SmallRyeConfigBuilder.class, SecretKeysHandlerFactory.class);
"withSecretKeyHandler",
void.class, SmallRyeConfigBuilder.class, SecretKeysHandlerFactory.class);
private static final MethodDescriptor WITH_MAPPING = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withMapping",
void.class, SmallRyeConfigBuilder.class, String.class, String.class);
void.class, SmallRyeConfigBuilder.class, ConfigClass.class);
private static final MethodDescriptor WITH_MAPPING_INSTANCE = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withMappingInstance",
void.class, SmallRyeConfigBuilder.class, ConfigClass.class);
private static final MethodDescriptor WITH_CUSTOMIZER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withCustomizer",
void.class, SmallRyeConfigBuilder.class, SmallRyeConfigBuilderCustomizer.class);
private static final MethodDescriptor WITH_BUILDER = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"withBuilder",
void.class, SmallRyeConfigBuilder.class, ConfigBuilder.class);
private static final MethodDescriptor CONFIG_CLASS = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"configClass",
ConfigClass.class, String.class, String.class);
private static final MethodDescriptor ENSURE_LOADED = MethodDescriptor.ofMethod(AbstractConfigBuilder.class,
"ensureLoaded",
void.class, String.class);

private static final DotName CONVERTER_NAME = DotName.createSimple(Converter.class.getName());
private static final DotName PRIORITY_NAME = DotName.createSimple(Priority.class.getName());

private static Map<Object, FieldDescriptor> generateSharedConfig(
BuildProducer<GeneratedClassBuildItem> generatedClass,
Set<String> converters,
Set<ConfigClass> mappings) {

Map<Object, FieldDescriptor> fields = new HashMap<>();
try (ClassCreator classCreator = ClassCreator.builder()
.classOutput(new GeneratedClassGizmoAdaptor(generatedClass, true))
.className("io.quarkus.runtime.generated.SharedConfig")
.superClass(AbstractConfigBuilder.class)
.setFinal(true)
.build()) {

MethodCreator clinit = classCreator.getMethodCreator("<clinit>", void.class);
clinit.setModifiers(Opcodes.ACC_STATIC);

int converterIndex = 0;
for (String converter : converters) {
String fieldName = "conv$" + converterIndex++;
FieldDescriptor converterField = classCreator.getFieldCreator(fieldName, Converter.class)
.setModifiers(Opcodes.ACC_STATIC).getFieldDescriptor();
clinit.writeStaticField(converterField, clinit.newInstance(MethodDescriptor.ofConstructor(converter)));
fields.put(converter, converterField);
}

int mappingIndex = 0;
for (ConfigClass mapping : mappings) {
FieldDescriptor mappingField = classCreator.getFieldCreator("mapping$" + mappingIndex++, ConfigClass.class)
.setModifiers(Opcodes.ACC_STATIC).getFieldDescriptor();
clinit.writeStaticField(mappingField, clinit.invokeStaticMethod(CONFIG_CLASS,
clinit.load(mapping.getType().getName()), clinit.load(mapping.getPrefix())));

List<ConfigMappingMetadata> configMappingsMetadata = ConfigMappingLoader
.getConfigMappingsMetadata(mapping.getType());
for (ConfigMappingMetadata configMappingMetadata : configMappingsMetadata) {
clinit.invokeStaticMethod(ENSURE_LOADED, clinit.load(configMappingMetadata.getInterfaceType().getName()));
}

fields.put(mapping, mappingField);
}

clinit.returnVoid();
}

return fields;
}

private static void generateConfigBuilder(
BuildProducer<GeneratedClassBuildItem> generatedClass,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
String className,
CombinedIndexBuildItem combinedIndex,
Map<Object, FieldDescriptor> sharedFields,
Map<String, String> defaultValues,
Set<String> converters,
Set<String> interceptors,
Expand All @@ -584,6 +672,7 @@ private static void generateConfigBuilder(
Set<String> configSourceFactories,
Set<String> secretKeyHandlers,
Set<String> secretKeyHandlerFactories,
Set<ConfigClass> mappingsInstances,
Set<ConfigClass> mappings,
Set<String> configCustomizers,
Set<String> configBuilders) {
Expand All @@ -597,23 +686,33 @@ private static void generateConfigBuilder(
.setFinal(true)
.build()) {

MethodCreator clinit = classCreator.getMethodCreator("<clinit>", void.class);
clinit.setModifiers(Opcodes.ACC_STATIC);

MethodCreator method = classCreator.getMethodCreator(BUILDER_CUSTOMIZER);
ResultHandle configBuilder = method.getMethodParam(0);

FieldDescriptor defaultsField = classCreator.getFieldCreator("defaults", Map.class).setModifiers(Opcodes.ACC_STATIC)
.getFieldDescriptor();
clinit.writeStaticField(defaultsField, clinit.newInstance(MethodDescriptor.ofConstructor(HashMap.class, int.class),
clinit.load((int) ((float) defaultValues.size() / 0.75f + 1.0f))));
MethodDescriptor put = MethodDescriptor.ofMethod(HashMap.class, "put", Object.class, Object.class, Object.class);
for (Map.Entry<String, String> entry : defaultValues.entrySet()) {
method.invokeStaticMethod(WITH_DEFAULT, configBuilder, method.load(entry.getKey()),
method.load(entry.getValue()));
clinit.invokeVirtualMethod(put, clinit.readStaticField(defaultsField), clinit.load(entry.getKey()),
clinit.load(entry.getValue()));
}
method.invokeStaticMethod(WITH_DEFAULTS, configBuilder, method.readStaticField(defaultsField));

for (String converter : converters) {
ClassInfo converterClass = combinedIndex.getComputingIndex().getClassByName(converter);
Type type = getConverterType(converterClass, combinedIndex);
AnnotationInstance priorityAnnotation = converterClass.annotation(PRIORITY_NAME);
int priority = priorityAnnotation != null ? priorityAnnotation.value().asInt() : 100;

method.invokeStaticMethod(WITH_CONVERTER, configBuilder,
method.load(type.name().toString()),
method.load(priority),
method.newInstance(MethodDescriptor.ofConstructor(converter)));
method.readStaticField(sharedFields.get(converter)));
}

for (String interceptor : interceptors) {
Expand Down Expand Up @@ -651,11 +750,17 @@ private static void generateConfigBuilder(
method.newInstance(MethodDescriptor.ofConstructor(secretKeyHandlerFactory)));
}

for (ConfigClass mappingInstance : mappingsInstances) {
method.invokeStaticMethod(WITH_MAPPING_INSTANCE, configBuilder,
method.readStaticField(sharedFields.get(mappingInstance)));
}

mappings.removeAll(mappingsInstances);
for (ConfigClass mapping : mappings) {
method.invokeStaticMethod(WITH_MAPPING, configBuilder, method.load(mapping.getKlass().getName()),
method.load(mapping.getPrefix()));
method.invokeStaticMethod(WITH_MAPPING, configBuilder, method.readStaticField(sharedFields.get(mapping)));
}

clinit.returnVoid();
method.returnVoid();
}

Expand Down
Loading
Loading