Quarkus ConfigMapping: how to map properties with keys with and without next level at the same time, like "fields" and "fields.excludes"

Viewed 36

Converting my app to use Quarkus @ConfigMapping is not easy, especially when the properties names may be used by other apps and you are not free to change them.

I have two keys like fields(set of string) and fields.excludes(another set of string). I want to know what I can do to map both of them. I tried:

Set<String> fields();

@WithName("fields")
FieldsExcludes fieldsToExclude();

interface FieldsExcludes {
    Set<String> excludes();
}
...

No compilation error, but runtime error:

Caused by: java.util.NoSuchElementException: SRCFG00014: The config property app.operator.0000001.endpoint.0.fields.exclude is required but it could not be found in any config source
    at io.smallrye.config.SmallRyeConfig.getIndexedValues(SmallRyeConfig.java:114)
    at io.smallrye.config.SmallRyeConfig.getValues(SmallRyeConfig.java:106)
    ...

Of course, I think Quarkus cannot tell if "fields" is a field of set, or a field of type FieldsExcludes. But this kind of configs are valid in YAML.

    fields: [a,b,c,d]
    fields.exclude: [e]

(if I break line at 2nd line after fields it's not valid; but if I put it like this it's valid, at least for Intellij IDEA)


See here: https://quarkus.io/guides/config-yaml#configuration-key-conflicts, in the doc it's stated that it's valid; I can use a ~ as a null key. So fields as a list and fields.exclude as another object should be supported.

1 Answers

OK at last it seems already supported; the error is due to it's not defined as "Optional<>" so Quarkus can find it in one place but cannot in another. (YAML contains 2 ConfigDetail, one of them does not have excludes, and it has no default value)

The final code is like this:

    interface ConfigDetail {
        Set<String> fields();

        @WithName("fields")
        Optional<FieldsToExclude> fieldsToExclude();
    }
...
    interface FieldsToExclude {
        Set<String> exclude();
    }
          fields:
            ~: [a,b,c,d]
            exclude: [e]
          ...
          fields:
            ~: [a,b,c,d,e]
          ...
Related