Skip to content

Commit

Permalink
Merge pull request #15053 from radcortez/fix-15033
Browse files Browse the repository at this point in the history
Register implicit Converters for ConfigProperties
  • Loading branch information
geoand committed Feb 15, 2021
2 parents fa941e8 + 428cd3e commit 89ad3ff
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ private String getPropertyName(String name, ClassInfo declaringClass) {
return builder.append(".").append(name).toString();
}

private boolean isHandledByProducers(Type type) {
public static boolean isHandledByProducers(Type type) {
if (type.kind() == Kind.ARRAY) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.createReadMandatoryValueAndConvertIfNeeded;
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.createReadOptionalValueAndConvertIfNeeded;
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.determineSingleGenericType;
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.registerImplicitConverter;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
Expand Down Expand Up @@ -38,6 +39,7 @@
import io.quarkus.deployment.Capability;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.bean.JavaBeanUtil;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem;
import io.quarkus.gizmo.BranchResult;
import io.quarkus.gizmo.BytecodeCreator;
Expand All @@ -63,18 +65,22 @@ final class ClassConfigPropertiesUtil {
private final YamlListObjectHandler yamlListObjectHandler;
private final ClassCreator producerClassCreator;
private final Capabilities capabilities;
private final BuildProducer<ReflectiveClassBuildItem> reflectiveClasses;
private final BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods;
private final BuildProducer<ConfigPropertyBuildItem> configProperties;

ClassConfigPropertiesUtil(IndexView applicationIndex, YamlListObjectHandler yamlListObjectHandler,
ClassCreator producerClassCreator,
Capabilities capabilities, BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
Capabilities capabilities,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses,
BuildProducer<ReflectiveMethodBuildItem> reflectiveMethods,
BuildProducer<ConfigPropertyBuildItem> configProperties) {

this.applicationIndex = applicationIndex;
this.yamlListObjectHandler = yamlListObjectHandler;
this.producerClassCreator = producerClassCreator;
this.capabilities = capabilities;
this.reflectiveClasses = reflectiveClasses;
this.reflectiveMethods = reflectiveMethods;
this.configProperties = configProperties;
}
Expand Down Expand Up @@ -341,6 +347,7 @@ private ResultHandle populateConfigObject(ClassLoader classLoader, ClassInfo con

// config.getOptionalValue
if (genericType.kind() != Type.Kind.PARAMETERIZED_TYPE) {
registerImplicitConverter(genericType, reflectiveClasses);
ResultHandle setterValue = methodCreator.invokeInterfaceMethod(
MethodDescriptor.ofMethod(Config.class, "getOptionalValue", Optional.class, String.class,
Class.class),
Expand Down Expand Up @@ -375,6 +382,7 @@ private ResultHandle populateConfigObject(ClassLoader classLoader, ClassInfo con
getEffectiveConfigName(namingStrategy, field), fullConfigName);
createWriteValue(methodCreator, configObject, field, setter, useFieldAccess, setterValue);
} else {
registerImplicitConverter(fieldType, reflectiveClasses);
populateTypicalProperty(methodCreator, configObject, configPropertyBuildItemCandidates,
currentClassInHierarchy, field, useFieldAccess, fieldType, setter, mpConfig,
fullConfigName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,11 @@ void setup(CombinedIndexBuildItem combinedIndex,
IndexView index = combinedIndex.getIndex();
YamlListObjectHandler yamlListObjectHandler = new YamlListObjectHandler(nonBeansClassOutput, index, reflectiveClasses);
ClassConfigPropertiesUtil classConfigPropertiesUtil = new ClassConfigPropertiesUtil(index,
yamlListObjectHandler, producerClassCreator, capabilities, reflectiveMethods, configProperties);
yamlListObjectHandler, producerClassCreator, capabilities, reflectiveClasses, reflectiveMethods,
configProperties);
InterfaceConfigPropertiesUtil interfaceConfigPropertiesUtil = new InterfaceConfigPropertiesUtil(index,
yamlListObjectHandler, nonBeansClassOutput, producerClassCreator, capabilities, defaultConfigValues,
configProperties);
configProperties, reflectiveClasses);
for (ConfigPropertiesMetadataBuildItem configPropertiesMetadata : configPropertiesMetadataList) {
ClassInfo classInfo = configPropertiesMetadata.getClassInfo();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;

import io.quarkus.arc.deployment.ConfigBuildStep;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.gizmo.BranchResult;
import io.quarkus.gizmo.BytecodeCreator;
import io.quarkus.gizmo.MethodDescriptor;
Expand Down Expand Up @@ -142,6 +145,15 @@ static Type determineSingleGenericType(Type type, DotName declaringClass) {
return type.asParameterizedType().arguments().get(0);
}

static void registerImplicitConverter(Type type, BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
// We need to register for reflection in case an implicit converter is required.
if (!ConfigBuildStep.isHandledByProducers(type)) {
if (type.kind() != Type.Kind.ARRAY) {
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, false, type.name().toString()));
}
}
}

static class ReadOptionalResponse {
private final ResultHandle value; //this is only valid within 'isPresentTrue'
private final BytecodeCreator isPresentTrue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.createReadMandatoryValueAndConvertIfNeeded;
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.createReadOptionalValueAndConvertIfNeeded;
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.determineSingleGenericType;
import static io.quarkus.arc.deployment.configproperties.ConfigPropertiesUtil.registerImplicitConverter;
import static io.quarkus.gizmo.MethodDescriptor.ofMethod;

import java.lang.annotation.Annotation;
Expand Down Expand Up @@ -38,6 +39,7 @@
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.bean.JavaBeanUtil;
import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.gizmo.ClassCreator;
import io.quarkus.gizmo.ClassOutput;
import io.quarkus.gizmo.FieldDescriptor;
Expand All @@ -55,18 +57,21 @@ final class InterfaceConfigPropertiesUtil {
private final Capabilities capabilities;
private final BuildProducer<RunTimeConfigurationDefaultBuildItem> defaultConfigValues;
private final BuildProducer<ConfigPropertyBuildItem> configProperties;
private final BuildProducer<ReflectiveClassBuildItem> reflectiveClasses;

InterfaceConfigPropertiesUtil(IndexView index, YamlListObjectHandler yamlListObjectHandler, ClassOutput classOutput,
ClassCreator classCreator,
Capabilities capabilities, BuildProducer<RunTimeConfigurationDefaultBuildItem> defaultConfigValues,
BuildProducer<ConfigPropertyBuildItem> configProperties) {
BuildProducer<ConfigPropertyBuildItem> configProperties,
BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
this.index = index;
this.yamlListObjectHandler = yamlListObjectHandler;
this.classOutput = classOutput;
this.classCreator = classCreator;
this.capabilities = capabilities;
this.defaultConfigValues = defaultConfigValues;
this.configProperties = configProperties;
this.reflectiveClasses = reflectiveClasses;
}

/**
Expand Down Expand Up @@ -216,6 +221,7 @@ private String generateImplementationForInterfaceConfigPropertiesRec(ClassInfo o
method.declaringClass().name());

if (genericType.kind() != Type.Kind.PARAMETERIZED_TYPE) {
registerImplicitConverter(genericType, reflectiveClasses);
ResultHandle result = methodCreator.invokeInterfaceMethod(
MethodDescriptor.ofMethod(Config.class, "getOptionalValue", Optional.class,
String.class,
Expand Down Expand Up @@ -262,6 +268,7 @@ private String generateImplementationForInterfaceConfigPropertiesRec(ClassInfo o
.produce(new RunTimeConfigurationDefaultBuildItem(fullConfigName, defaultValueStr));
}
// use config.getValue to obtain and return the result taking converting it to collection if needed
registerImplicitConverter(returnType, reflectiveClasses);
ResultHandle value = createReadMandatoryValueAndConvertIfNeeded(
fullConfigName, returnType,
method.declaringClass().name(), methodCreator, config);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package io.quarkus.it.config;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.Optional;

import javax.validation.constraints.Size;
import javax.ws.rs.GET;
Expand All @@ -12,27 +17,46 @@
public class ConfigPropertiesResource {

final GreetingConfiguration greetingConfiguration;
final GreetingConfigurationI greetingConfigurationI;

public ConfigPropertiesResource(GreetingConfiguration greetingConfiguration) {
public ConfigPropertiesResource(GreetingConfiguration greetingConfiguration,
GreetingConfigurationI greetingConfigurationI) {
this.greetingConfiguration = greetingConfiguration;
this.greetingConfigurationI = greetingConfigurationI;
}

@GET
public String greet() {
return greetingConfiguration.message + greetingConfiguration.number + greetingConfiguration.suffix;
}

@GET
@Path("/period")
public String period() {
return greetingConfiguration.period.get().toString();
}

@ConfigProperties(prefix = "configproperties")
public static class GreetingConfiguration {
@Size(min = 2)
public String message;
public String suffix = "!";
public BigDecimal other;
public NumberEnum number;
// Force to use implicit converter to check for reflective registration
public LocalDate date;
public Optional<Period> period;
}

public enum NumberEnum {
ONE,
TWO;
}

@ConfigProperties(prefix = "configproperties")
public interface GreetingConfigurationI {
LocalDateTime dateTime();

Optional<Instant> instant();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ microprofile.cidr-address=10.0.0.20/24
configproperties.message=Hello
configproperties.other=1
configproperties.number=ONE
configproperties.date=2020-10-10
configproperties.date-time=2020-10-10T10:10
configproperties.period=P1D
configproperties.instant=2010-10-10T10:10:10Z

quarkus.swagger-ui.always-include=true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ public void testConfigPropertiesProperlyInjected() {
.when().get("/configuration-properties")
.then().body(is("HelloONE!"));
}

@Test
public void testImplicitConverters() {
RestAssured
.when().get("/configuration-properties/period")
.then().body(is("P1D"));
}
}

0 comments on commit 89ad3ff

Please sign in to comment.