camel-quarkus icon indicating copy to clipboard operation
camel-quarkus copied to clipboard

If jandex is present in an extension, the RouteBuilder beans created by a runtime extension appear to be duplicated

Open jskillin-idt opened this issue 3 years ago • 8 comments

In my setup, I have an extension with the jandex plugin applied to it so that the JARs contain a jandex.idx file. The build steps appear to run correctly, and record correctly. However, at runtime, when a Quarkus app attempts to get beans of type RouteBuilder, the RouteBuilder beans belonging to that extension get duplicated, and the duplicate instance has not had its constructor run. This duplicate bean later causes a runtime exception.

This could be user error; perhaps you don't want jandex indexes created for Quarkus extensions intended for Camel? Or perhaps this is indeed a bug in the way that Quarkus and Camel interact.

To reproduce, roughly speaking:

  1. Create an extension and apply the jandex plugin to the runtime and deployment projects.
  2. Create an application with a test that attempts to use Camel's registry to retrieve the RouteBuilder beans.

I am using Quarkus 2.9.2.Final, Camel 3.16.0, and camel-quarkus 2.9.0.

A reproduction git repo will be linked once the issue is posted.

jskillin-idt avatar Jun 08 '22 22:06 jskillin-idt

Example reproduction: https://github.com/jskillin-idt/apache-camel-quarkus-issues-3844

The branch "without-camel" tested that the same style of injection works without Camel in the middle.

jskillin-idt avatar Jun 08 '22 22:06 jskillin-idt

I should probably mention that simply running "./gradlew build" is enough to reproduce the issue using the example reproduction.

jskillin-idt avatar Jun 08 '22 22:06 jskillin-idt

Here is what should be seen from the test output (and then Gradle links a fuller test report complete with the standard output that has the full stack trace):

ExampleTest > test() FAILED
    java.lang.RuntimeException at QuarkusTestExtension.java:632
        Caused by: java.lang.RuntimeException at null:-1
            Caused by: java.lang.RuntimeException at CamelBootstrapRecorder.java:47
                Caused by: java.lang.RuntimeException at CamelMainRuntime.java:65
                    Caused by: java.lang.NullPointerException at ExampleRouteBuilder.java:17

jskillin-idt avatar Jun 08 '22 22:06 jskillin-idt

If you don't want Camel Quarkus to automatically discover and bootstrap RouteBuilder implementations, then you can add some configuration to application.properties:

quarkus.camel.routes-discovery.enabled=false

It's not entirely clear what you're trying to accomplish with your extension. Camel Quarkus can take care of bootstrapping RouteBuilder and the CamelContext for you. So you don't strictly need to produce your own synthetic beans for them and write your own recorders etc.

jamesnetherton avatar Jun 09 '22 06:06 jamesnetherton

Hey James,

I think the downfall of the minimal reproduction I created is it doesn't do a good job demonstrating the intent behind the design. What RouteBuilders are available is not known at the time of writing this code. The app will live in a different location and there will be many of them. The idea is that the extensions will build RouteBuilders in response to customized rules.

If we disable this bootstrapping that Camel does, is there additional work to do to replace that functionality? I can do more investigation on this as I'm somewhat new to this ecosystem.

jskillin-idt avatar Jun 09 '22 16:06 jskillin-idt

is there additional work to do to replace that functionality

Yes, you become responsible for ensuring those routes are added to the CamelContext.

The project provides some BuildItems for various things that could be useful for you.

https://github.com/apache/camel-quarkus/tree/main/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/spi

jamesnetherton avatar Jun 13 '22 06:06 jamesnetherton

Is it unexpected for a user of camel-quarkus to produce synthetic RouteBuilder beans for Camel to discover later? If so, does that mean that producing RouteBuilder's is invalid while "quarkus.camel.routes-discovery.enabled" is set to true?

jskillin-idt avatar Jun 13 '22 16:06 jskillin-idt

Is it unexpected for a user of camel-quarkus to produce synthetic RouteBuilder beans for Camel to discover later

It's not a scenario that has ever been considered TBH.

Does that mean that producing RouteBuilder's is invalid while "quarkus.camel.routes-discovery.enabled" is set to true

Kind of. There are 2 competing forces at play here. The framework is automatically discovering & instantiating the RouteBuilder classes that are in your extension. Also since you also produce synthetic beans for them, they are discoverable via the Camel registry and hence they get added to the CamelContext. In a 'normal' app, folks would not have a RouteBuilder that they instantiate via a CDI producer method since it does not make much sense to do so.

The alternative to disabling routes discovery entirely would be to suppress Camel Quarkus from trying to instantiate your RouteBuilder classes by producing RoutesBuilderClassExcludeBuildItem. For example:

@BuildStep
RoutesBuilderClassExcludeBuildItem excludedRoutesDiscovery() {
    return RoutesBuilderClassExcludeBuildItem.ofClass(ExampleRouteBuilder.class);
}

We could maybe investigate making things a bit simpler so that additional code / config is not needed in the future.

jamesnetherton avatar Jun 14 '22 07:06 jamesnetherton