Search code examples
javarabbitmqspring-amqpspring-rabbit

spring-rabbit in another web framework: using RabbitListenerEndpointRegistry


A decision has been made to use Spring's spring-rabbit in the Dropwizard web-framework. We don't have access to Spring's bean processors and annotations.

We already have a setup in place where we simply initialize DirectMessageListenerContainers in a consolidated place in the application.

I want to manage these containers better, for example: to be able to shut them down, we need reference to them.

I can always save a Map<x, DirectMessageListenerContainer>, or Set, but I think the cleaner way is to use a static RabbitListenerEndpointRegistry`:

endpointRegistry.registerListenerContainer(endpoint, directRabbitListenerContainerFactory);

However, I've noticed some behaviors that I can't find the documentation for.

Some configurations that we need for the DMLC aren't available on the on the Endpoint instance needed for the registartion, for example: #setAfterReceivePostProcessors and #setErrorHandler are only available on the DMLC instance. Understandable.

To mitigate this, I'm using endpoint#setupListenerContainer(container) which correctly picks these properties from the DMLC instance. However, there are some settings that are "shared" between the endpoint and the DMLC, and in those instances it seems that setting them on them endpoint will override the DMLC configs, or fail in case they're only configured on the DMLC instance but not on the endpoint. For example:

container.setQueueNames("containerQueue");
endpoint.setQueueNames("enpodintQueue")

Will initialize a DMLC listening to the endpointQueue, not containerQueue.

Both container and endpoint have a #setMessageListener() method, however regardless of what is set on the container, if one is not set on the endpoint, an exception is thrown when try to register the container.

Similarly, setPrefetchCount on the container is completely ignored, and we have to define concurrency on the endpoint.

My question is, where are those overrides/ignores defined/documented, if any? The documentation for #setupListenerContainer says:

Setup the specified message listener container with the model defined by this endpoint.

This endpoint must provide the requested missing option(s) of the specified container to make it usable. Usually, this is about setting the queues and the messageListener to use but an implementation may override any default setting that was already set.

Params: listenerContainer – the listener container to configure

Except for trial and error, how can I know which properties (like errorHandler) should I set on the container, and which should be set on the endpoint (like concurrency, messagListener, and queueNames)?


Solution

  • This really was not designed to be used outside of Spring inversion of control container and without @RabbitListener annotation.

    So, you need to create DirectRabbitListenerContainerFactory instance and set all of its required properties. Then you create a SimpleRabbitListenerEndpoint instance with all of its required options. And then that endpointRegistry.registerListenerContainer() should work.

    Bottom line: the endpoint options have a precedence over those from the factory. The factory is common for many instances and you indeed can override all similar via endpoint. In regular case: whatever we have on the @RabbitListener wins.