Skip to content

Defining more than one Operator causes NonUniqueBeanException on RateLimitingQueue #924

@etremblay

Description

@etremblay

Expected Behavior

In the same micronaut project, we expect to be able to define many operator controller ( ResourceReconciler with the @Operator bean).

One for each Resources managed by our application.

Actual Behaviour

When the application start we get this exception.

io.micronaut.context.exceptions.NonUniqueBeanException: Multiple possible bean candidates found: [RateLimitingQueue, RateLimitingQueue<object>]
at io.micronaut.context.DefaultBeanContext.findConcreteCandidate(DefaultBeanContext.java:2454)
at io.micronaut.context.DefaultApplicationContext.findConcreteCandidate(DefaultApplicationContext.java:675)
at io.micronaut.context.DefaultBeanContext.lastChanceResolve(DefaultBeanContext.java:3315)
at io.micronaut.context.DefaultBeanContext.pickOneBean(DefaultBeanContext.java:3253)
at io.micronaut.context.DefaultBeanContext.findConcreteCandidateNoCache(DefaultBeanContext.java:3209)
at io.micronaut.context.DefaultBeanContext.findConcreteCandidate(DefaultBeanContext.java:3192)
at io.micronaut.context.DefaultBeanContext.findBeanDefinition(DefaultBeanContext.java:776)
at io.micronaut.context.DefaultBeanContext.findBeanDefinition(DefaultBeanContext.java:785)
at io.micronaut.context.DefaultBeanContext.createBean(DefaultBeanContext.java:1399)
at io.micronaut.context.DefaultBeanContext.createBean(DefaultBeanContext.java:1036)
at io.micronaut.context.BeanContext.createBean(BeanContext.java:92)
at io.micronaut.kubernetes.client.operator.controller.DefaultControllerBuilder.build(DefaultControllerBuilder.java:78)

Note that we already have a fully functionnal operator working for one resource. The error occurs when we try to add a second operator in the same application.

In io.micronaut.kubernetes.client.operator.controller, the bean is created with

final RateLimitingQueue<Request> workQueue = beanContext.createBean(RateLimitingQueue.class);
beanContext.registerSingleton(RateLimitingQueue.class, workQueue, Qualifiers.byName(name));

After the first controller is created, there is two definitions for the bean RateLimitingQueue and RateLimitingQueue<object>. There is something fishy with generic type. Also note that we use it in Kotlin.

I was able to make it work by adding AnyQualifier like this

final RateLimitingQueue<Request> workQueue = beanContext.createBean(RateLimitingQueue.class, AnyQualifier.INSTANCE);

It may not be the good solution but both operators work perfectly well after that.

Steps To Reproduce

Create two class with the @Operator annotation.

@Operator(
    name = "resource1",
    informer = Informer(...)
class Resource1Operator() : ResourceReconciler<Resource1> {}

@Operator(
    name = "resource2",
    informer = Informer(...)
class Resource2Operator() : ResourceReconciler<Resource2> {}

Environment Information

java temurin-21.0.7+6.0.LTS
kotlin 1.9
kapt

Example Application

No response

Version

4.8.2 (micronaut-kubernetes 7.0.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions