Search code examples
javaquarkusmicroprofile

Group configuration in quarkus / microprofile


I want to group configuration items in Quarkus and use them as a Map. Something along the lines of the next application.properties:

greeting.names = tom,jane
greeting.tom.message = hello
greeting.tom.name = tom
greeting.jane.message = hi
greeting.jane.name = jane

And have them in the application in a Map, like this:

@ConfigProperties
public class GreetingConfig {

   private String name;
   private String message;

   // getters / setters
}

And use them like this:

private Map<String, GreetingConfig> config;

They are now name indexed, but a List would also be fine (and is what I actually need):

greeting.1.message = hello
greeting.1.name = tom
greeting.2.message = hi
greeting.2.name = jane

Any ideas on how to realize this? I have a programmatic solution, but would prefer a solution by annotation only


Solution

  • I've had a similar problem these days. So I wrote a simple Quarkus extension which helped me with the configuration. You can use the guides from the Quarkus site: Quarkus - Writing Your Own Extension and Quarkus - Building my first extension, but basically these are the steps taken in order to create the configuration:

    1. Have some maven multi module project (not the project where the configuration will be consumed).
    2. Execute a similar command form the project directory:
    mvn io.quarkus:quarkus-maven-plugin:1.4.2.Final:create-extension -N \
        -Dquarkus.artifactIdBase=keycloak-extension \
        -Dquarkus.artifactIdPrefix=otaibe-commons-quarkus- \
        -Dquarkus.nameBase="Keycloak extension"
    

    This will create 'sub multi module' project there with the following modules: runtume and deployment.

    1. Go to the runtime module and add and annotate your config class. It should be something similar to this class
    2. In runtime module create a producer class which should register the configuration class as CDI bean:
    @ApplicationScoped
    public class OtaibeKeycloakQuarkusProducer {
    
        private volatile OtaibeKeycloakConfig otaibeKeycloakConfig;
    
        void initialize(OtaibeKeycloakConfig config) {
            this.otaibeKeycloakConfig = config;
        }
    
        @Singleton
        @Produces
        public OtaibeKeycloakConfig otaibeKeycloakConfig() {
            return otaibeKeycloakConfig;
        }
    
    }
    
    1. Create a Recorder class which should initialize the Producer:
    @Recorder
    public class OtaibeKeycloakRecorder {
    
        public void initOtaQuarkusProducer(BeanContainer container, OtaibeKeycloakConfig configuration) {
            OtaibeKeycloakQuarkusProducer producer = container.instance(OtaibeKeycloakQuarkusProducer.class);
            producer.initialize(configuration);
        }
    
    }
    
    1. In deployment module you have a Processor class. Go there and register your Producer to be injectable as CDI bean and your Recorder to initialize it. Add the similar code:
        @BuildStep
        AdditionalBeanBuildItem beans() {
            return AdditionalBeanBuildItem.builder().addBeanClasses(OtaibeKeycloakQuarkusProducer.class).build();
        }
    
        @BuildStep
        @Record(ExecutionTime.RUNTIME_INIT)
        void otaibeKeycloackConfigBuildItem(BeanContainerBuildItem beanContainer,
                                            OtaibeKeycloakConfig otaibeKeycloakConfig,
                                            OtaibeKeycloakRecorder recorder) {
            recorder.initOtaQuarkusProducer(beanContainer.getValue(), otaibeKeycloakConfig);
        }
    

    You can find my implementation here.

    1. Now, go to your initial project where the configuration will be consumed and add the runtime module as a dependency.

    2. In order to ensure that the configuration is added properly execute the following maven command:

    mvn quarkus:generate-config
    

    Now, you can check the file src/main/resources/application.properties.example and verify whether your properties are added there. The property group should start with quarkus. plus the name of your @ConfigRoot annotation. In my case for example it will start with quarkus.otaibe.keycloak

    That's it!