Search code examples
springspring-bootspring-amqpspring-rabbit

Injecting scoped beans in the context of one AMQP message in Spring Boot


When writing web application with Spring Boot you can declare your beans to be part of the session- or request scope.

Is it possible to create a scope for injection of data with messages received by a @RabbitListener?

When receiving a message with a the RabbitListener, I would like to initialize some metadata which I would like to have available for injection in code called during message processing. (e.g. receiving queue for logging, or a pre-configured factory where the configuration depends on parameters known at receiving time of the message).

Passing this data through all called methods feels just ugly.

Ways I could think of, but don't know how to do it:

  • AOP
  • Custom scopes

Help is greatly appreciated!


Solution

  • Probably the simplest approach would be to use a MessagePostProcessor (add to the container/container factory via the afterReceivePostProcessors property).

        /**
         * Set {@link MessagePostProcessor}s that will be applied after message reception, before
         * invoking the {@link MessageListener}. Often used to decompress data.  Processors are invoked in order,
         * depending on {@code PriorityOrder}, {@code Order} and finally unordered.
         * @param afterReceivePostProcessors the post processor.
         * @since 1.4.2
         */
        public void setAfterReceivePostProcessors(MessagePostProcessor... afterReceivePostProcessors) {
            Assert.notNull(afterReceivePostProcessors, "'afterReceivePostProcessors' cannot be null");
            Assert.noNullElements(afterReceivePostProcessors, "'afterReceivePostProcessors' cannot have null elements");
            this.afterReceivePostProcessors = MessagePostProcessorUtils.sort(Arrays.asList(afterReceivePostProcessors));
        }
    

    Use a ThreadLocal to store the metadata; you can then access the metadata in the listener.