Skip to content
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

Update MicroProfile Config to 3.1 #39233

Merged
merged 1 commit into from
Apr 24, 2024
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 @@ -39,7 +39,7 @@
<hdrhistogram.version>2.1.12</hdrhistogram.version><!-- keep in sync with micrometer -->
<google-auth.version>0.22.0</google-auth.version>
<graphql-java.version>21.3</graphql-java.version> <!-- keep in sync with smallrye-graphql -->
<microprofile-config-api.version>3.0.3</microprofile-config-api.version>
<microprofile-config-api.version>3.1</microprofile-config-api.version>
<microprofile-health-api.version>4.0.1</microprofile-health-api.version>
<microprofile-metrics-api.version>4.0.1</microprofile-metrics-api.version>
<microprofile-context-propagation.version>1.3</microprofile-context-propagation.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static io.quarkus.arc.processor.Annotations.getParameterAnnotations;
import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;
import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT;
import static io.quarkus.deployment.builditem.ConfigClassBuildItem.Kind.MAPPING;
import static io.quarkus.deployment.builditem.ConfigClassBuildItem.Kind.PROPERTIES;
import static io.quarkus.deployment.configuration.ConfigMappingUtils.CONFIG_MAPPING_NAME;
Expand Down Expand Up @@ -49,8 +50,10 @@
import io.quarkus.arc.processor.Annotations;
import io.quarkus.arc.processor.AnnotationsTransformer;
import io.quarkus.arc.processor.BeanConfigurator;
import io.quarkus.arc.processor.BuiltinScope;
import io.quarkus.arc.processor.DotNames;
import io.quarkus.arc.processor.InjectionPointInfo;
import io.quarkus.arc.processor.ObserverInfo;
import io.quarkus.arc.runtime.ConfigBeanCreator;
import io.quarkus.arc.runtime.ConfigMappingCreator;
import io.quarkus.arc.runtime.ConfigRecorder;
Expand Down Expand Up @@ -135,8 +138,23 @@ void registerCustomConfigBeanTypes(BeanDiscoveryFinishedBuildItem beanDiscovery,
}

@BuildStep
void validateConfigInjectionPoints(ValidationPhaseBuildItem validationPhase,
BuildProducer<ConfigPropertyBuildItem> configProperties) {
void configPropertyInjectionPoints(
ValidationPhaseBuildItem validationPhase,
BuildProducer<ConfigPropertyBuildItem> configProperties,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {

// @Observes @Initialized(ApplicationScoped.class) requires validation at static init
Set<MethodInfo> observerMethods = new HashSet<>();
for (ObserverInfo observer : validationPhase.getBeanProcessor().getBeanDeployment().getObservers()) {
if (observer.isSynthetic()) {
continue;
}
AnnotationInstance instance = Annotations.getParameterAnnotation(observer.getObserverMethod(),
DotNames.INITIALIZED);
if (instance != null && instance.value().asClass().name().equals(BuiltinScope.APPLICATION.getName())) {
observerMethods.add(observer.getObserverMethod());
}
}

for (InjectionPointInfo injectionPoint : validationPhase.getContext().getInjectionPoints()) {
if (injectionPoint.hasDefaultedQualifier()) {
Expand Down Expand Up @@ -185,47 +203,43 @@ void validateConfigInjectionPoints(ValidationPhaseBuildItem validationPhase,
propertyDefaultValue = defaultValue.asString();
}

configProperties.produce(new ConfigPropertyBuildItem(propertyName, injectedType, propertyDefaultValue));
if (injectionPoint.getTarget().kind().equals(METHOD)
&& observerMethods.contains(injectionPoint.getTarget().asMethod())) {
configProperties
.produce(ConfigPropertyBuildItem.staticInit(propertyName, injectedType, propertyDefaultValue));
}

configProperties.produce(ConfigPropertyBuildItem.runtimeInit(propertyName, injectedType, propertyDefaultValue));
}
}
}

@BuildStep
@Record(RUNTIME_INIT)
void validateConfigValues(ConfigRecorder recorder, List<ConfigPropertyBuildItem> configProperties,
BeanContainerBuildItem beanContainer, BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
// IMPL NOTE: we do depend on BeanContainerBuildItem to make sure that the BeanDeploymentValidator finished its processing

// the non-primitive types need to be registered for reflection since Class.forName is used at runtime to load the class
for (ConfigPropertyBuildItem item : configProperties) {
Type requiredType = item.getPropertyType();
String propertyType = requiredType.name().toString();
if (requiredType.kind() != Kind.PRIMITIVE) {
reflectiveClass.produce(ReflectiveClassBuildItem.builder(propertyType).build());
}
}
@Record(STATIC_INIT)
void validateStaticInitConfigProperty(
ConfigRecorder recorder,
List<ConfigPropertyBuildItem> configProperties,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {

Set<ConfigValidationMetadata> propertiesToValidate = new HashSet<>();
for (ConfigPropertyBuildItem configProperty : configProperties) {
String rawTypeName = configProperty.getPropertyType().name().toString();
List<String> actualTypeArgumentNames = Collections.emptyList();
if (configProperty.getPropertyType().kind() == Kind.PARAMETERIZED_TYPE) {
List<Type> argumentTypes = configProperty.getPropertyType().asParameterizedType().arguments();
actualTypeArgumentNames = new ArrayList<>(argumentTypes.size());
for (Type argumentType : argumentTypes) {
actualTypeArgumentNames.add(argumentType.name().toString());
if (argumentType.kind() != Kind.PRIMITIVE) {
reflectiveClass.produce(ReflectiveClassBuildItem.builder(argumentType.name().toString())
.build());
}
}
recorder.validateConfigProperties(
configProperties.stream()
.filter(ConfigPropertyBuildItem::isStaticInit)
.map(p -> configPropertyToConfigValidation(p, reflectiveClass))
.collect(toSet()));
}

}
propertiesToValidate.add(new ConfigValidationMetadata(configProperty.getPropertyName(),
rawTypeName, actualTypeArgumentNames, configProperty.getDefaultValue()));
}
@BuildStep
@Record(RUNTIME_INIT)
void validateRuntimeConfigProperty(
ConfigRecorder recorder,
List<ConfigPropertyBuildItem> configProperties,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {

recorder.validateConfigProperties(propertiesToValidate);
recorder.validateConfigProperties(
configProperties.stream()
.filter(ConfigPropertyBuildItem::isRuntimeInit)
.map(p -> configPropertyToConfigValidation(p, reflectiveClass))
.collect(toSet()));
}

@BuildStep
Expand Down Expand Up @@ -524,6 +538,30 @@ public static boolean isHandledByProducers(Type type) {
MP_CONFIG_VALUE_NAME.equals(type.name());
}

private static ConfigValidationMetadata configPropertyToConfigValidation(ConfigPropertyBuildItem configProperty,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass) {
String typeName = configProperty.getPropertyType().name().toString();
List<String> typeArgumentNames = Collections.emptyList();

if (configProperty.getPropertyType().kind() != Kind.PRIMITIVE) {
reflectiveClass.produce(ReflectiveClassBuildItem.builder(typeName).build());
}

if (configProperty.getPropertyType().kind() == Kind.PARAMETERIZED_TYPE) {
List<Type> argumentTypes = configProperty.getPropertyType().asParameterizedType().arguments();
typeArgumentNames = new ArrayList<>(argumentTypes.size());
for (Type argumentType : argumentTypes) {
typeArgumentNames.add(argumentType.name().toString());
if (argumentType.kind() != Kind.PRIMITIVE) {
reflectiveClass.produce(ReflectiveClassBuildItem.builder(argumentType.name().toString()).build());
}
}
}

return new ConfigValidationMetadata(configProperty.getPropertyName(), typeName, typeArgumentNames,
configProperty.getDefaultValue());
}

private static Map<Type, ConfigClassBuildItem> configClassesToTypesMap(List<ConfigClassBuildItem> configClasses,
ConfigClassBuildItem.Kind kind) {
Map<Type, ConfigClassBuildItem> configClassesTypes = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.jboss.jandex.Type;

import io.quarkus.builder.item.MultiBuildItem;
import io.quarkus.runtime.ExecutionMode;

/**
* Represents a mandatory config property that needs to be validated at runtime.
Expand All @@ -11,11 +12,18 @@ public final class ConfigPropertyBuildItem extends MultiBuildItem {
private final String propertyName;
private final Type propertyType;
private final String defaultValue;
private final ExecutionMode executionMode;

private ConfigPropertyBuildItem(
final String propertyName,
final Type propertyType,
final String defaultValue,
final ExecutionMode executionMode) {

public ConfigPropertyBuildItem(final String propertyName, final Type propertyType, final String defaultValue) {
this.propertyName = propertyName;
this.propertyType = propertyType;
this.defaultValue = defaultValue;
this.executionMode = executionMode;
}

public String getPropertyName() {
Expand All @@ -29,4 +37,30 @@ public Type getPropertyType() {
public String getDefaultValue() {
return defaultValue;
}

public ExecutionMode getExecutionMode() {
return executionMode;
}

public boolean isStaticInit() {
return executionMode.equals(ExecutionMode.STATIC_INIT);
}

public boolean isRuntimeInit() {
return executionMode.equals(ExecutionMode.RUNTIME_INIT);
}

public static ConfigPropertyBuildItem staticInit(
final String propertyName,
final Type propertyType,
final String defaultValue) {
return new ConfigPropertyBuildItem(propertyName, propertyType, defaultValue, ExecutionMode.STATIC_INIT);
}

public static ConfigPropertyBuildItem runtimeInit(
final String propertyName,
final Type propertyType,
final String defaultValue) {
return new ConfigPropertyBuildItem(propertyName, propertyType, defaultValue, ExecutionMode.RUNTIME_INIT);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,8 @@ private ResultHandle populateConfigObject(ClassLoader classLoader, ClassInfo con
}

for (ConfigPropertyBuildItemCandidate candidate : configPropertyBuildItemCandidates) {
configProperties
.produce(new ConfigPropertyBuildItem(candidate.getConfigPropertyName(), candidate.getConfigPropertyType(),
null));
configProperties.produce(ConfigPropertyBuildItem.runtimeInit(candidate.getConfigPropertyName(),
candidate.getConfigPropertyType(), null));
}

return configObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ private String generateImplementationForInterfaceConfigPropertiesRec(ClassInfo o
method.declaringClass().name(), methodCreator, config);
methodCreator.returnValue(value);
if (defaultValueStr == null || ConfigProperty.UNCONFIGURED_VALUE.equals(defaultValueStr)) {
configProperties
.produce(new ConfigPropertyBuildItem(fullConfigName, returnType, defaultValueStr));
configProperties.produce(
ConfigPropertyBuildItem.runtimeInit(fullConfigName, returnType, defaultValueStr));
}
}
}
Expand Down
6 changes: 1 addition & 5 deletions tcks/microprofile-config/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<name>Quarkus - TCK - MicroProfile Config</name>

<properties>
<microprofile-config-tck.version>3.0.3</microprofile-config-tck.version>
<microprofile-config-tck.version>3.1</microprofile-config-tck.version>
</properties>

<build>
Expand Down Expand Up @@ -43,10 +43,6 @@
<systemPropertyVariables>
<!-- Disable quarkus optimization -->
<quarkus.arc.remove-unused-beans>false</quarkus.arc.remove-unused-beans>
<!-- 1. There is a bug in TCK: -->
<!-- https://github.com/eclipse/microprofile-config/issues/543 -->
<!-- 2. After transformation we get a ClassCastException which is very likely caused by a class loading problem in our Arquillian adapter -->
<quarkus.arc.transform-unproxyable-classes>false</quarkus.arc.transform-unproxyable-classes>
</systemPropertyVariables>
<!-- This workaround allows us to run a single test using
the "test" system property -->
Expand Down
Loading