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 reading ConfigMapping in constructor injection #19387

Closed
mikethecalamity opened this issue Aug 13, 2021 · 7 comments · Fixed by #19398
Closed

Error reading ConfigMapping in constructor injection #19387

mikethecalamity opened this issue Aug 13, 2021 · 7 comments · Fixed by #19398
Labels
area/config triage/invalid This doesn't seem right
Milestone

Comments

@mikethecalamity
Copy link

Describe the bug

I want to specify a @ConfigMapping on a parameter in the injection constructor, such that it is used then thrown away. This causes an unsatisfied dependency error on build. This may be unsupported behavior, in which case feel free to retag this as an enhancement.

Expected behavior

The ability to read config mappings in an injection constructor.

Actual behavior

        Suppressed: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type my.project.service3.config.Service3Config and qualifiers [@Default]
        - java member: my.project.service3.Service3Handler#<init>()
        - declared on CLASS bean [types=[my.project.service3.Service3Handler, java.lang.Object], qualifiers=[@Default, @Any], target=my.project.service3.Service3Handler]

How to Reproduce?

Reproducer: service3 in https://github.com/mweber03/quarkus-test

  1. ./gradlew service3:quarkusBuild

application.yaml

app:
  data1:
    name: Bob
    num: 100
  data2:
    name: Tim
    num: 30

java

@Dependent
public class Service3Handler {

    private final String value1;
    private final String value2;

    @Inject
    public Service3Handler(@ConfigMapping(prefix = "app.data1") final Service3Config config1,
            @ConfigMapping(prefix = "app.data12") final Service3Config config2) {
        this.value1 = String.format("%s-%s", config1.name(), config1.num());
        this.value2 = String.format("%s-%s", config2.name(), config2.num());
    }

    public String getValue1() {
        return this.value1;
    }

    public String getValue2() {
        return this.value2;
    }
}

Output of uname -a or ver

Ubuntu 20.04

Output of java -version

OpenJDK 11.0.11

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.1.2

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

Gradle 7.1.1

Additional information

No response

@mikethecalamity mikethecalamity added the kind/bug Something isn't working label Aug 13, 2021
@quarkus-bot quarkus-bot bot added the area/arc Issue related to ARC (dependency injection) label Aug 13, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented Aug 13, 2021

/cc @manovotn, @mkouba

@mikethecalamity
Copy link
Author

/cc @radcortez

@radcortez
Copy link
Member

Hum... it should work. Let me have a look.

@radcortez
Copy link
Member

@mweber03 you are missing the @ConfigMapping annotation in your config interface.

I also added a test to Quarkus and it does work as expected.

@radcortez radcortez added triage/invalid This doesn't seem right and removed kind/bug Something isn't working labels Aug 13, 2021
@quarkus-bot quarkus-bot bot added this to the 2.2 - main milestone Aug 17, 2021
@mikethecalamity
Copy link
Author

mikethecalamity commented Aug 25, 2021

@radcortez I disagree that your test actually tests anything.

Your test works because @ConfigMapping(prefix = "config") is on the MyConfigMapping interface, not because its on the injection constructor. If you removed the annotation from the injection constructor, it would still work. So basically putting the annotation in a constructor is pointless because it needs to be on the interface class regardless.

What I was hoping to do is share the interface class between two configs, but I can't do this if the config prefix needs to be on the interface class. This actually used to work with the quarkus arc @ConfigPrefix (if you replace the annotation below).

Example of what I was trying to do:

public interface Service3Config {
    String name();
    int num();
}

public class Service3Handler {

    @Inject
    public Service3Handler(@ConfigMapping(prefix = "app.data1") final Service3Config config1,
            @ConfigMapping(prefix = "app.data2") final Service3Config config2) {
        ...
    }
}

@gsmet

@mkouba
Copy link
Contributor

mkouba commented Aug 27, 2021

So from CDI point of view the @io.smallrye.config.ConfigMapping should have no effect on injection because it's not a qualifier, unless there's some quarkus extension that reads this annotation on injection points and performs some additional transformations...

@mkouba mkouba added area/config and removed area/arc Issue related to ARC (dependency injection) labels Aug 27, 2021
@radcortez
Copy link
Member

The annotation in the constructor is to override the prefix used in the injection point.

@mweber03 yes, the config mapping interface requires the annotation and the injection in the constructor works without it, but you can definitely reuse the same interface with different prefixes by overriding the injection point with the @ConfigMapping annotation and setting the new prefix. I'll add a test for that use case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/config triage/invalid This doesn't seem right
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants