0

The FailedMessageAspect.afterMethod() below gets called successfully during RabbitConsumerMain.main() below. However, it doesn't get called when it's used in the context of listening for a RabbitMQ message - when MessageHandlerImpl.handleMesasge() receives a message from a RabbitMQ queue. Any idea why?

FailedMessageAspect.java

@Aspect
@Component
public class FailedMessageAspect {

    @AfterReturning("execution(* com..MessageHandlerImpl.testAspect(..))")
    private void afterMethod() {
        System.out.println("aspect foo");
    }
}

MessageHandlerImpl.java

@Component
public class MessageHandlerImpl implements MessageHandler {

    @Override
    public void testAspect() {
        System.out.println("handler foo");
    }

    @Override
    public void handleMessage(String message) {
        // handleMessage is called successfully when message is received
        testAspect();
        // FailedMessageAspect.afterMethod() does not get called
    }
}

RabbitConsumerMain.java

@Controller
@SpringBootApplication
public class RabbitConsumerMain implements CommandLineRunner {

    @Autowired
    private MessageHandler messageHandler;

    public static void main(String[] args) throws Exception {
        SpringApplication.run(RabbitConsumerMain.class, args);
    }

    @Override
    public void run(String... args) {
        messageHandler.testAspect();
        //FailedMessageSpect.afterMethod() gets called right here
    }
}

ConsumerConfiguration.java

@Configuration
public class ConsumerConfiguration {
    @Autowired @Lazy
    private MessageHandler messageHandler;

    //other standard AMQP configs

    @Bean
    public MessageListenerContainer messageListenerContainer() {
        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
        container.setConnectionFactory(connectionFactory());
        container.setQueues(workQueue());
        MessageListenerAdapter adapter = new MessageListenerAdapter(messageHandler, new Jackson2JsonMessageConverter());
        container.setMessageListener(adapter);
        return container;
    }
}
Glide
  • 20,235
  • 26
  • 86
  • 135

1 Answers1

3

You don't show all your configuration but, just to be clear, Spring AOP does not advise internal method calls such as handleMessage calling testAspect() within the same class instance.

You need to use AspectJ for that; otherwise, all methods you advise must be public methods invoked via bean definitions, so Spring can invoke the method via a proxy. Internal calls within a bean are never advised.

See the reference manual for a complete explanation.

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