smallrye / smallrye-reactive-messaging

SmallRye Reactive Messaging
http://www.smallrye.io/smallrye-reactive-messaging/
Apache License 2.0
235 stars 176 forks source link

Usage without Quarkus or auto bean discovery #2115

Open craig-day opened 1 year ago

craig-day commented 1 year ago

I'm hoping to use this implementation of MP Reactive Messaging outside of Quarkus. I'm primarily trying to spin up some Kafka consumers in a Vert.x app. Initially it seemed straightforward by just adding the ReactiveMessagingExtension to my Weld container, however that opened a rabbit hole of other managed beans to add. I've been working through all the errors and adding the beans as Weld complains about being unable to find them. I ended up with something like this:

    weld.addExtension(new ReactiveMessagingExtension());

    // TODO: why do we need to set all this up for SmallRye?
    weld
        .addBeanClass(MediatorManager.class)
        .addBeanClass(HealthCenter.class)
        .addBeanClass(InternalChannelRegistry.class)
        .addBeanClass(WorkerPoolRegistry.class)
        .addBeanClass(MediatorFactory.class)
        .addBeanClass(Wiring.class)
        .addBeanClass(ExecutionHolder.class);

    weld.addPackage(true, KafkaConnector.class);

I've gotten through all the CDI errors, and now I'm getting stuck with the mediator complaining about channels without upstreams configured.

Wondering if I'm missing something critical or if there is an implicit dependency on Quarkus.

cescoffier commented 1 year ago

You can use smallrye reactive messaging without Quarkus. Most of our tests are just using Weld (SE). For the Kafka connector, you would need something like this:

https://github.com/smallrye/smallrye-reactive-messaging/blob/main/smallrye-reactive-messaging-kafka/src/test/java/io/smallrye/reactive/messaging/kafka/base/WeldTestBase.java#L67

However, if your application is using Vert.x and CDI, I recommend you to use Quarkus, as it will package both nicely and optimize a lot of things for you.

craig-day commented 1 year ago

Thanks for this! Would you be open to adding a CDI class that does this directly in here? This got me a lot further, and I also found that I need to produced a mutiny vertx instance delegating to my regular vertx instance.

Yes, I know Quarkus does this for me and we're working on getting our apps there, but there are lots of other things that aren't quarkus compatible for me right now so it's not a simple switch. Having a CDI support class that I could add that wires all the rest up would be super helpful.

cescoffier commented 1 year ago

What do you mean with a CDI support class? (Sorry, not a cdi expert).

If we can do anything to make it easier, it's more than welcome!

\CC @mkouba the living CDI reference.

craig-day commented 1 year ago

I'm thinking something that does everything the initWeld() method you linked does. Something that can register the rest of the beans for you rather than relying on auto-discovery (like quarkus does) or a consumer manually adding them. A CDI extension could work, probably using BeforeBeanDiscovery, or even a class that has a bunch of @Produces methods that could be added a single time by the client, rather than referencing all the classes.

mkouba commented 1 year ago

I'm thinking something that does everything the initWeld() method you linked does. Something that can register the rest of the beans for you rather than relying on auto-discovery (like quarkus does) or a consumer manually adding them.

AFAIK the Weld SE can also perform discovery if you omit the Weld#disableDiscovery() method. In fact, it's the default behavior.

CC @manovotn

craig-day commented 1 year ago

Yes Weld can perform auto discovery, but for many reasons, startup performance being a large one, that often gets disabled. I think it's always nice to provide explicit behavior as an option rather than relying on an automatic assumption or classpath based loading. In any case, I can keep doing this in my app, I was just wondering if folks here would be interested in adding an optional module here to easy non-quarkus usage.

mkouba commented 1 year ago

Hm, so you're proposing some kind of semi-automatic discovery ;-).

A CDI extension could work, probably using BeforeBeanDiscovery, ...

This could work but I'm not sure it's worth a new module.

or even a class that has a bunch of @Produces methods that could be added a single time by the client, rather than referencing all the classes.

This would not work because the produced beans would not be injected by the container (i.e. the producer method controls the instantiation of the bean class).

Also this issue should be probably renamed because AFAIK smallrye-reactive-messaging can be easily used (i.e. without explicit configuration) in WildFly and other environments.

manovotn commented 1 year ago

Sorry, I was on PTO last week, hence my late answer.

In order not to interfere with Quarkus behavior (or any CDI Lite framework for that matter) and avoid discovery, leveraging portable extensions is probably the easiest way. Using BeforeBeanDiscovery you can register the beans very similarly.

craig-day commented 1 year ago

That's exactly what I was thinking. I'll work on a draft PR with what I was thinking to see if you all think it's reasonable to add here.

manovotn commented 1 year ago

That's exactly what I was thinking. I'll work on a draft PR with what I was thinking to see if you all think it's reasonable to add here.

I think it makes sense 👍 So unless @cescoffier objects, go ahead.

cescoffier commented 1 year ago

No problem for me! Definitely welcome!

craig-day commented 1 year ago

I started implementing what I was thinking in this draft: https://github.com/smallrye/smallrye-reactive-messaging/pull/2125

I wasn't sure if I put things in the right place, would love any thoughts.

michalcukierman commented 7 months ago

For the framework using (extending) SmallRye Reactive Messaging we've used: https://github.com/weld/weld-testing/tree/master/junit5