4

For my Quarkus application I'm looking for a way to define a configuration map from within a custom ConfigProperties class. I tried the following:

import io.quarkus.arc.config.ConfigProperties;
import io.quarkus.runtime.annotations.ConfigItem;

@ConfigProperties(prefix = "my-properties")
public class MyPropertiesConfiguration { 

    @ConfigItem
    public Map<String, FooConfiguration> foo;

    // ...
}
import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;

@ConfigGroup
public class FooConfiguration {

  @ConfigItem
  public String myProperty;
}

Given those two classes and the following application.properties file...

my-properties.foo.anystring.my-property=bar

on startup the application fails with error message: javax.enterprise.inject.spi.DeploymentException: No config value of type [java.util.Map] exists for: my-properties.foo

As far as I understand https://quarkus.io/guides/writing-extensions#configuration-maps the sample should work. What am I doing wrong? Could it happen that this functionality is just limited to Quarkus extensions only?

mika
  • 2,495
  • 22
  • 30

2 Answers2

1

As written in this Quarkus github issue, this is currently not supported.

My dirty workaround was to use the ConfigProvider directly. Use with care.

  public static Map<String, String> getMapFromConfig(String prefix) {
    final Config config = ConfigProvider.getConfig();
    final Iterable<String> propertyNames = config.getPropertyNames();
    return StreamSupport.stream(propertyNames.spliterator(), false)
        .filter(name -> name.startsWith(prefix) && !name.equalsIgnoreCase(prefix))
        .collect(
            Collectors.toMap(
                propertyName -> cleanupPropertyName(propertyName.substring(prefix.length() + 1)),
                propertyName -> config.getOptionalValue(propertyName, String.class).orElse("")));
  }

  /** Remove start and end double quotes */
  public static String cleanupPropertyName(String name) {
    if (name.startsWith("\"") && name.endsWith("\"")) {
      return name.substring(1, name.length() - 1);
    }
    return name;
  }

My config looks like this:

property-templates:
  "my.key": value 1
  "my.second.key": value 2
gaetanc
  • 116
  • 5
-2

Declare the configuration like this

import io.quarkus.arc.config.ConfigProperties;

@ConfigProperties(prefix = "myapp")
public class AppSpecificConfig {

    public String property;

}

The application.properties file will contain

myapp.property=foo

And then you can @Inject an instance of this class anywhere within your application.

For more details, see https://quarkus.io/guides/config#using-configproperties

Jan Martiška
  • 1,151
  • 5
  • 7
  • Hi @Jan Martiška, thx for your reply. The definition and injection of simple properties is clear. I'm looking for a way to setup a named configuration using a java.util.Map. In the sample I provided in my question I try to tell quarkus to put a new `FooConfiguration` item with `myProperty = bar` onto the map `foo` using string `anystring` as key. – mika May 19 '20 at 14:50
  • 1
    Ah, then I think no, that facility is currently only for extensions. There is an alternative, if you really want to inject maps, you can create a `org.eclipse.microprofile.config.spi.Converter`, but that one will only be able to map one configuration property into a `Map` object, meaning the property will have to contain all keys and values in a particular parseable format. – Jan Martiška May 20 '20 at 09:54
  • @JanMartiška do you have an example how to create and register such converter for Map? – stinger Dec 16 '20 at 10:45
  • @stinger Try following the guide at https://quarkus.io/guides/config#custom-configuration-converters except that you will use a `Map` instead of `MicroProfileCustomValue` – Jan Martiška Dec 17 '20 at 11:30