6

Is there a way to intercept messages once template.convertAndSend is called, before the message is delivered to RabbitMQ.

Also any way to intercept the message before reaching the handler?

I can handle the message using PostProcessor for publisher, but prefer to use interceptor.

public class TestPostProcessor implements MessagePostProcessor {

    @Autowired
    Tracer defaultTracer;

    @Override
    public Message postProcessMessage(Message message) throws AmqpException {
        //.....
        //.... 
        return message;
    }
}

Any suggestions?

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
basu76
  • 441
  • 10
  • 19
  • `>I can handle the message using PostProcessor for publisher, but prefer to use interceptor.` Can you explain what you mean by that? The MPP __is__ a form of interceptor. The listener container also supports MPPs after receiving and before delivery to the listener: `setAfterReceivePostProcessors()`. – Gary Russell Oct 21 '16 at 19:32
  • To use it I had to do rabbitTemplate.convertAndSend(routingKey,"Message",postProcessor); - was wondering if there is a way to inject this, without us having to provide it here. Also how would we do it on SimpleMessageListenerContainer ? – basu76 Oct 21 '16 at 19:43
  • Yes; see my answer. – Gary Russell Oct 21 '16 at 19:48

2 Answers2

6

MessagePostProcessor is a form of interceptor.

There are two ways to invoke one - use one of the overloaded convertAndSend() methods that take an MPP as an argument, or add one or more to the RabbitTemplate using setBeforePublishPostProcessors().

You can also intercept received messages using the setAfterReceivePostProcessors() which is invoked before the received message is returned from a receive() method.

The listener container also supports MPPs after receiving and before delivery to the listener via its setAfterReceivePostProcessors() method.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
1

If you want to keep using spring boot properties (from org.springframework.boot.autoconfigure.amqp.RabbitProperties) in your application.properties file, you can provide your own RabbitListenerContainerFactory :

  @Bean
  public CustomRabbitListenerContainerFactory rabbitListenerContainerFactory(
      SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory, MyContextMessageProcessor messageProcessor) {
    CustomRabbitListenerContainerFactory factory = new CustomRabbitListenerContainerFactory(messageProcessor);
    configurer.configure(factory, connectionFactory);
    return factory;
  }

CustomRabbitListenerContainerFactory.java :

public class CustomRabbitListenerContainerFactory
  extends org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory {

  private MessagePostProcessor[] messagePostProcessor;

  public CustomRabbitListenerContainerFactory(MessagePostProcessor... messagePostProcessor) {
    super();
    this.messagePostProcessor = messagePostProcessor;
  }

  @Override
  protected void initializeContainer(SimpleMessageListenerContainer instance, RabbitListenerEndpoint endpoint) {
    super.initializeContainer(instance, endpoint);
    instance.addAfterReceivePostProcessors(messagePostProcessor);
  }
}
  • Even simpler solution: just autowire the framework created SimpleRabbitListenerContainerFactory (pay attention for the Direct part of the story) and call the method: setAfterReceivePostProcessors – Ursache Jan 12 '21 at 10:05