Skip to content

Commit b114345

Browse files
authored
Merge pull request #9459 from geoand/config-properties-enum-default-value
Fix ignored default enum value for @ConfigProperties
2 parents 42fff6b + 159d8d9 commit b114345

File tree

2 files changed

+47
-40
lines changed

2 files changed

+47
-40
lines changed

extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/configproperties/ClassConfigPropertiesUtil.java

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -270,14 +270,9 @@ private static ResultHandle populateConfigObject(ClassLoader classLoader, ClassI
270270
ResultHandle mpConfig = methodCreator.getMethodParam(0);
271271
if (fieldTypeClassInfo != null) {
272272
if (DotNames.ENUM.equals(fieldTypeClassInfo.superName())) {
273-
// just read the value from MP Config normally
274-
ResultHandle value = methodCreator.invokeInterfaceMethod(
275-
MethodDescriptor.ofMethod(Config.class, "getValue", Object.class, String.class, Class.class),
276-
mpConfig,
277-
methodCreator.load(getFullConfigName(prefixStr, namingStrategy, field)),
278-
methodCreator.loadClass(fieldTypeDotName.toString()));
279-
280-
createWriteValue(methodCreator, configObject, field, setter, useFieldAccess, value);
273+
populateTypicalProperty(methodCreator, configObject, configPropertyBuildItemCandidates,
274+
currentClassInHierarchy, field, useFieldAccess, fieldType, setter, mpConfig,
275+
getFullConfigName(prefixStr, namingStrategy, field));
281276
} else {
282277
if (!fieldTypeClassInfo.hasNoArgsConstructor()) {
283278
throw new IllegalArgumentException(
@@ -328,37 +323,9 @@ private static ResultHandle populateConfigObject(ClassLoader classLoader, ClassI
328323
MethodDescriptor.ofMethod(Optional.class, "empty", Optional.class)));
329324
}
330325
} else {
331-
/*
332-
* We want to support cases where the Config class defines a default value for fields
333-
* by simply specifying the default value in its constructor
334-
* For such cases the strategy we follow is that when a requested property does not exist
335-
* we check the value from the corresponding getter (or read the field value if possible)
336-
* and if the value is not null we don't fail
337-
*/
338-
if (shouldCheckForDefaultValue(currentClassInHierarchy, field)) {
339-
String getterName = JavaBeanUtil.getGetterName(field.name(), fieldTypeDotName.toString());
340-
341-
ReadOptionalResponse readOptionalResponse = createReadOptionalValueAndConvertIfNeeded(
342-
fullConfigName,
343-
fieldType, field.declaringClass().name(), methodCreator, mpConfig);
344-
345-
// call the setter if the optional contained data
346-
createWriteValue(readOptionalResponse.getIsPresentTrue(), configObject, field, setter,
347-
useFieldAccess,
348-
readOptionalResponse.getValue());
349-
} else {
350-
/*
351-
* In this case we want a missing property to cause an exception that we don't handle
352-
* So we call config.getValue making sure to handle collection values
353-
*/
354-
ResultHandle setterValue = createReadMandatoryValueAndConvertIfNeeded(
355-
fullConfigName, fieldType,
356-
field.declaringClass().name(), methodCreator, mpConfig);
357-
createWriteValue(methodCreator, configObject, field, setter, useFieldAccess, setterValue);
358-
359-
}
360-
configPropertyBuildItemCandidates
361-
.add(new ConfigPropertyBuildItemCandidate(field.name(), fullConfigName, fieldType));
326+
populateTypicalProperty(methodCreator, configObject, configPropertyBuildItemCandidates,
327+
currentClassInHierarchy, field, useFieldAccess, fieldType, setter, mpConfig,
328+
fullConfigName);
362329
}
363330
}
364331
}
@@ -393,6 +360,42 @@ private static ResultHandle populateConfigObject(ClassLoader classLoader, ClassI
393360
return configObject;
394361
}
395362

363+
// creates the bytecode needed to populate anything other than a nested config object or an optional
364+
private static void populateTypicalProperty(MethodCreator methodCreator, ResultHandle configObject,
365+
List<ConfigPropertyBuildItemCandidate> configPropertyBuildItemCandidates, ClassInfo currentClassInHierarchy,
366+
FieldInfo field, boolean useFieldAccess, Type fieldType, MethodInfo setter,
367+
ResultHandle mpConfig, String fullConfigName) {
368+
/*
369+
* We want to support cases where the Config class defines a default value for fields
370+
* by simply specifying the default value in its constructor
371+
* For such cases the strategy we follow is that when a requested property does not exist
372+
* we check the value from the corresponding getter (or read the field value if possible)
373+
* and if the value is not null we don't fail
374+
*/
375+
if (shouldCheckForDefaultValue(currentClassInHierarchy, field)) {
376+
ReadOptionalResponse readOptionalResponse = createReadOptionalValueAndConvertIfNeeded(
377+
fullConfigName,
378+
fieldType, field.declaringClass().name(), methodCreator, mpConfig);
379+
380+
// call the setter if the optional contained data
381+
createWriteValue(readOptionalResponse.getIsPresentTrue(), configObject, field, setter,
382+
useFieldAccess,
383+
readOptionalResponse.getValue());
384+
} else {
385+
/*
386+
* In this case we want a missing property to cause an exception that we don't handle
387+
* So we call config.getValue making sure to handle collection values
388+
*/
389+
ResultHandle setterValue = createReadMandatoryValueAndConvertIfNeeded(
390+
fullConfigName, fieldType,
391+
field.declaringClass().name(), methodCreator, mpConfig);
392+
createWriteValue(methodCreator, configObject, field, setter, useFieldAccess, setterValue);
393+
394+
}
395+
configPropertyBuildItemCandidates
396+
.add(new ConfigPropertyBuildItemCandidate(field.name(), fullConfigName, fieldType));
397+
}
398+
396399
private static String getFullConfigName(String prefixStr, ConfigProperties.NamingStrategy namingStrategy, FieldInfo field) {
397400
return prefixStr + "." + namingStrategy.getName(field.name());
398401
}

extensions/arc/deployment/src/test/java/io/quarkus/arc/test/configproperties/ClassWithoutGettersConfigPropertiesTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public class ClassWithoutGettersConfigPropertiesTest {
2424
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
2525
.addClasses(DummyBean.class, DummyProperties.class)
2626
.addAsResource(new StringAsset(
27-
"dummy.name=quarkus\ndummy.my-enum=OPTIONAL\ndummy.numbers=1,2,3,4\ndummy.unused=whatever"),
27+
"dummy.name=quarkus\ndummy.my-enum=OPTIONAL\ndummy.other-enum=Enum_Two\ndummy.numbers=1,2,3,4\ndummy.unused=whatever"),
2828
"application.properties"));
2929

3030
@Inject
@@ -36,6 +36,8 @@ public void testConfiguredValues() {
3636
assertEquals("quarkus", dummyProperties.name);
3737
assertEquals(Arrays.asList(1, 2, 3, 4), dummyProperties.numbers);
3838
assertEquals(MyEnum.OPTIONAL, dummyProperties.myEnum);
39+
assertEquals(MyEnum.ENUM_ONE, dummyProperties.unsetEnum);
40+
assertEquals(MyEnum.Enum_Two, dummyProperties.otherEnum);
3941
}
4042

4143
@Singleton
@@ -50,6 +52,8 @@ public static class DummyProperties {
5052
public String name;
5153
public List<Integer> numbers;
5254
public MyEnum myEnum;
55+
public MyEnum otherEnum = MyEnum.ENUM_ONE;
56+
public MyEnum unsetEnum = MyEnum.ENUM_ONE;
5357

5458
public void setName(String name) {
5559
this.name = name;

0 commit comments

Comments
 (0)