Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with ConfigMapping using Maps and Nested Groups #20728

Closed
rudiger3d opened this issue Oct 13, 2021 · 5 comments · Fixed by smallrye/smallrye-config#649 or #20870
Closed

Error with ConfigMapping using Maps and Nested Groups #20728

rudiger3d opened this issue Oct 13, 2021 · 5 comments · Fixed by smallrye/smallrye-config#649 or #20870
Assignees
Labels
area/config kind/bug Something isn't working
Milestone

Comments

@rudiger3d
Copy link

Describe the bug

I'm seeing errors when mapping configuration to objects using a combination of nested groups (https://quarkus.io/guides/config-mappings#nested-groups) and maps (https://quarkus.io/guides/config-mappings#maps) that I think is a bug.

Having:

package org.acme.config;

import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithParentName;

import java.util.Map;

@ConfigMapping(prefix = "clients", namingStrategy = ConfigMapping.NamingStrategy.VERBATIM)
public interface BugsConfiguration {

    @WithParentName
    Map<String, ClientConfiguration> clients();

    interface ClientConfiguration {
        MediumProperties medium();
        CreatedByProperties app();
    }

    interface MediumProperties {
        boolean web();
        boolean app();
    }

    interface CreatedByProperties {
        String createdByApplication();
    }
}

and application.properties

clients.SOS_DAH.medium.app=true
clients.SOS_DAH.medium.web=true

clients.SOS_DAH.app.createdByApplication=Roadrunner

The app fails to start because

2021-10-13 09:35:53,054 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application (with profile dev): io.smallrye.config.ConfigValidationException: Configuration validation failed:
	clients.SOS_DAH.medium.app does not map to any root
	at io.smallrye.config.ConfigMappingProvider.mapConfiguration(ConfigMappingProvider.java:855)
	at io.smallrye.config.ConfigMappingProvider.mapConfiguration(ConfigMappingProvider.java:811)
	at io.smallrye.config.SmallRyeConfigBuilder.build(SmallRyeConfigBuilder.java:403)
	at io.quarkus.runtime.generated.Config.readConfig(Config.zig:1379)
	at io.quarkus.deployment.steps.RuntimeConfigSetup.deploy(RuntimeConfigSetup.zig:42)
	at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:436)
	at io.quarkus.runtime.Application.start(Application.java:101)
	at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:101)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:66)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:42)
	at io.quarkus.runtime.Quarkus.run(Quarkus.java:119)
	at io.quarkus.runner.GeneratedMain.main(GeneratedMain.zig:29)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:103)
	at java.base/java.lang.Thread.run(Thread.java:833)

However if I don't use a Map in my ConfigMapping class, e.g.

package org.acme.config;

import io.smallrye.config.ConfigMapping;

@ConfigMapping(prefix = "clients.SOS_DAH", namingStrategy = ConfigMapping.NamingStrategy.VERBATIM)
public interface WorkingConfiguration {

    MediumProperties medium();
    CreatedByProperties app();

    interface MediumProperties {
        boolean web();
        boolean app();
    }

    interface CreatedByProperties {
        String createdByApplication();
    }
}

I don't get any errors.

Expected behavior

I expect that I am able to use Maps in my ConfigMapping class and that names at different levels of the config hierarchy does not "shadows" each other.

Actual behavior

It appears that when using Maps and Nested groups in a ConfigMapping class that names in different nested groups and at different levels of the config "shadows" each other.

How to Reproduce?

  1. git clone https://github.com/quarkusio/quarkus-quickstarts/tree/main/config-quickstart
  2. cd config-quickstart
  3. Add BugsConfiguration.java and the properties from the "Describe the error" section to application.properties
  4. Start the application

Output of uname -a or ver

Darwin everythingsruined 20.6.0 Darwin Kernel Version 20.6.0: Wed Jun 23 00:26:31 PDT 2021; root:xnu-7195.141.2~5/RELEASE_X86_64 x86_64

Output of java -version

openjdk version "17" 2021-09-14 OpenJDK Runtime Environment Temurin-17+35 (build 17+35) OpenJDK 64-Bit Server VM Temurin-17+35 (build 17+35, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

No response

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

No response

@rudiger3d rudiger3d added the kind/bug Something isn't working label Oct 13, 2021
@radcortez radcortez self-assigned this Oct 13, 2021
@radcortez
Copy link
Member

Yes, this is a bug. It seems that internally, in a specific edge case we are considering that we already processed the boolean app() because it has the same method name as CreatedByProperties app(). I guess we never noticed because it requires this specific mapping to manifest itself.

@rudiger3d for now, to work around the problem, can you use different names for these methods? In the meanwhile, I'll work on a fix.

@rudiger3d
Copy link
Author

@radcortez yes I can get started - the most important is that it actually is supposed to work.

I am looking into migrating a Spring Boot application that uses this particularly combination, so going forward it would make things a lot easier if I don't have to make too many work arounds :)

Thanks for the quick reply!

@radcortez
Copy link
Member

I already have a fix. It should be available soon. Alternatively, because this is done in SR Config, you should be able to update the dependency manually (until it is available in Quarkus).

@rudiger3d
Copy link
Author

Great!

Will the fix also take into account the below example where the name enabled is present at same leaf level of two different roots?

I.e.

package org.acme.config;

import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import io.smallrye.config.WithParentName;

import java.util.Map;

@ConfigMapping(prefix = "clients", namingStrategy = ConfigMapping.NamingStrategy.VERBATIM)
public interface BugsConfiguration {

    @WithParentName
    Map<String, ClientConfiguration> clients();

    interface ClientConfiguration {
        MediumProperties medium();
        CreatedByProperties app();
        EnabledProperties callback();
        EnabledProperties task();
    }

    interface MediumProperties {
        boolean web();
        boolean app();
    }

    interface CreatedByProperties {
        String createdByApplication();
    }

    interface EnabledProperties {
        boolean enabled();
    }
}

and application.properties

clients.SOS_DAH.medium.app=true
clients.SOS_DAH.medium.web=true

clients.SOS_DAH.app.createdByApplication=Roadrunner

clients.SOS_DAH.callback.enabled=true
clients.SOS_DAH.task.enabled=false

@radcortez
Copy link
Member

Yes, I've used your example to fix and test it. Check here: https://github.com/smallrye/smallrye-config/pull/649/files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/config kind/bug Something isn't working
Projects
None yet
3 participants