apache / camel-quarkus

Apache Camel Quarkus
https://camel.apache.org
Apache License 2.0
255 stars 189 forks source link

Bean defined with @Identifier not resolved when multiple beans with same identifier exist #4725

Closed turing85 closed 11 months ago

turing85 commented 1 year ago

Description

We added support to automatically register beans annotated with @Identifier in #4374 (commit https://github.com/apache/camel-quarkus/commit/6f4228848ef68eff290ef735d8552dcc23cf7266#diff-79ee191174431bde21e06eae2287b5a2e61d6a7b39a3e6d5915d5b2c2455f532) Bean registration fails, however, when multiple beans with different types have the same @Identifier("<name>").


Example

Bean defining class:

public class BeanProducer {
    @Produces
    @Typed({ ConnectionFactory.class })
    @ApplicationScoped
    @Identifier("externally-defined")
    ActiveMQConnectionFactory externallyDefinedConnectionFactory(
            @ConfigProperty(name = "artemis.externally-defined.url") String externallyDefinedUrl) {
        return new ActiveMQConnectionFactory(externallyDefinedUrl);
    }

    @Produces
    @ApplicationScoped
    @Typed({ ArtemisJmsConsumerManager.class })
    @Identifier("externally-defined")
    ArtemisJmsConsumerManager externalConsumerManager(
            @Identifier("externally-defined") ConnectionFactory connectionFactory) {
        return new ArtemisJmsConsumerManager(connectionFactory, "out");
    }
    // other beans with differend @Identifiers
}

Usage in route:

public class TransferRoute extends RouteConfigurationBuilder {

    @Override
    public void configuration() {
        from(jms("queue:in").connectionFactory("named"))
                .to(jms("queue:out").connectionFactory("externally-defined"));
    }
}

results in:

...
Caused by: jakarta.enterprise.inject.AmbiguousResolutionException: [PRODUCER_METHOD bean [class=io.quarkus.it.artemis.camel.jms.withnamedandexternal.BeanProducer, id=993a3bbccfc0b1c95e14b9f04ff12402c4215353], PRODUCER_METHOD bean [class=io.quarkus.it.artemis.camel.jms.withnamedandexternal.BeanProducer, id=8ebca384354a86c6da0c74eaf28ad6affbcf0ee1]]
    at io.quarkus.arc.impl.ArcContainerImpl.resolve(ArcContainerImpl.java:592)
    at io.quarkus.arc.impl.BeanManagerImpl.resolve(BeanManagerImpl.java:114)
    at org.apache.camel.quarkus.core.RuntimeBeanRepository.getReferenceByName(RuntimeBeanRepository.java:80)
    at org.apache.camel.quarkus.core.RuntimeBeanRepository.lambda$lookupByNameAndType$2(RuntimeBeanRepository.java:119)
    at java.base/java.util.Optional.flatMap(Optional.java:289)
    at org.apache.camel.quarkus.core.RuntimeBeanRepository.lookupByNameAndType(RuntimeBeanRepository.java:119)
    at org.apache.camel.quarkus.core.RuntimeBeanRepository.lookupByName(RuntimeBeanRepository.java:113)
    at org.apache.camel.support.DefaultRegistry.lookupByName(DefaultRegistry.java:220)
    at org.apache.camel.support.CamelContextHelper.lookup(CamelContextHelper.java:190)
    at org.apache.camel.support.CamelContextHelper.mandatoryLookupAndConvert(CamelContextHelper.java:246)
    at org.apache.camel.support.EndpointHelper.resolveReferenceParameter(EndpointHelper.java:351)
    at org.apache.camel.support.EndpointHelper.resolveReferenceParameter(EndpointHelper.java:298)
    at org.apache.camel.support.DefaultComponent.resolveAndRemoveReferenceParameter(DefaultComponent.java:629)
    at org.apache.camel.support.DefaultComponent.resolveAndRemoveReferenceParameter(DefaultComponent.java:592)
    at org.apache.camel.component.jms.JmsComponent.createEndpoint(JmsComponent.java:1139)
    at org.apache.camel.support.DefaultComponent.createEndpoint(DefaultComponent.java:170)
    at org.apache.camel.impl.engine.AbstractCamelContext.doGetEndpoint(AbstractCamelContext.java:876)
    ... 77 more

Expected behaviour

Bean is properly resolved through its type


Actual behavour

Application fails to start up with above exception


Analysis and possible solution

The problem is cased in RuntimeBeanRepository, because the bean is looked up without its type, thus two beans are found and the above exception is thrown.

One possible solution would be to first try to get the bean with its type, and only if this fails get the bean without type and call the converter. Risk: it might be possible that some code relies on some converter call, even if conversion is not strictly necessary.

@jamesnetherton already did some experimentation here.


FTR: corresponding Zulip conversation.

turing85 commented 1 year ago

I raised https://issues.apache.org/jira/browse/CAMEL-19234 to tackle the issue in camel's core. I think it is possible to implement it in such a way that backwards-compatibility ca be ensured.

turing85 commented 1 year ago

Issue has been fixed in camel and is scheduled for release in 4.0.0-M3. So it should automatically be "fixed" as soon as we produce a release on camel version >= 4.0.0-M3.

Question is: how should we track that this issue has been resolve, i.ie when it is accessible to users?

jamesnetherton commented 1 year ago

how should we track that this issue has been resolved

I'll try to add a test case to verify it.

when it is accessible to users

It depends whether we do another milestone release (M2) for Camel Quarkus 3.x. Otherwise it'll be available when we release 3.0.0.

turing85 commented 1 year ago

@jamesnetherton we already have some tests that (implicitly) test the behaviour here. We are currently in the process of migrating the tests to quarkus-3.x (see this branch). We also plan to provide the entire camel-jms test suite to camel-quarkus (see https://github.com/quarkiverse/quarkus-artemis/issues/158).