Search code examples
spring-bootrabbitmqspring-amqpspring-rabbit

I cannot override containerFactory on RabbitListener


I am facing overridden issue and more precisely in the containerFactory in one of my RabbitListener.

Let's say that I have projectA and one of its dependencies (library B) instantiates the following configuration in runtime.

@Configuration
public class AmqpConfiguration {
    @Bean
    public static BeanPostProcessor bpp() {
        return new BeanPostProcessor() {

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof RabbitTemplate) {
                    RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
                    rabbitTemplate.addBeforePublishPostProcessors(new LogRequestBeforePublishPostProcessor());
                } else if (bean instanceof AbstractRabbitListenerContainerFactory) {
                    AbstractRabbitListenerContainerFactory<?> rabbitContainerFactory = (AbstractRabbitListenerContainerFactory<?>)  bean;
                    rabbitContainerFactory.setAfterReceivePostProcessors(new LogRequestAfterReceivePostProcessor());
                }
             
                return bean;
            }

        };

    }
}

As you can understand, the above bean injects custom implementations of MessagePostProcessor in RabbitTamplate and AbstractRabbitListenerContainerFactory instances.

My problem is that I want to extend or override MessagePostProcessor of AbstractRabbitListenerContainerFactory that has been setup in the code below.

rabbitContainerFactory.setAfterReceivePostProcessors(new LogRequestAfterReceivePostProcessor());

To overcome this situation, I tried to create a new instance of SimpleRabbitListenerContainerFactory and pass it to my RabbitListener in projectA but unfortunately I did not make it work. Using debug mode I saw that libraryB's MessagePostProcessor was called.

See my test code below.

@Configuration
public class LoggingContainerConfiguration {

  @Bean(name = "rabbitListenerContainerFactoryNew")
  public SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer,
      ConnectionFactory connectionFactory, MessageConverter objJsonMessageConverter, ObjectMapper objectMapper) {

    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    configurer.configure(factory, connectionFactory);

    factory.setMessageConverter(objJsonMessageConverter);
    factory.setAfterReceivePostProcessors(new LogPaymentEventDTOAfterReceivePostProcessor(objectMapper));
    return factory;
  }
}

@RabbitListener(containerFactory = "rabbitListenerContainerFactoryNew",
                queues = {"test1", "test2"})
public void listener(Pojo pojo) {
   ...
}

Do you have any suggestions how to override MessagePostProcessor of connectionFactory in my RabbitListener ?

Thank you in advance.


Solution

  • Project B's BPP modifies ALL instances; not by bean name.

    Either change it to only modify its own beans, or you can add a SmartInitializingSingleton to re-modify your bean after the BPP has run.