Annotated Endpoint Method Signature

So far, we have been injecting a simple String in our endpoint, but it can actually have a very flexible method signature. The following example rewrites it to inject the Order with a custom header:

@Component
public class MyService {

    @RabbitListener(queues = "myQueue")
    public void processOrder(Order order, @Header("order_type") String orderType) {
        ...
    }
}

The following list shows the arguments that are available to be matched with parameters in listener endpoints:

  • The raw org.springframework.amqp.core.Message.

  • The MessageProperties from the raw Message.

  • The com.rabbitmq.client.Channel on which the message was received.

  • The org.springframework.messaging.Message converted from the incoming AMQP message.

  • @Header-annotated method arguments to extract a specific header value, including standard AMQP headers.

  • @Headers-annotated argument that must also be assignable to java.util.Map for getting access to all headers.

  • The converted payload

A non-annotated element that is not one of the supported types (that is, Message, MessageProperties, Message<?> and Channel) is matched with the payload. You can make that explicit by annotating the parameter with @Payload. You can also turn on validation by adding an extra @Valid.

The ability to inject Spring’s message abstraction is particularly useful to benefit from all the information stored in the transport-specific message without relying on the transport-specific API. The following example shows how to do so:

@RabbitListener(queues = "myQueue")
public void processOrder(Message<Order> order) { ...
}

Handling of method arguments is provided by DefaultMessageHandlerMethodFactory, which you can further customize to support additional method arguments. The conversion and validation support can be customized there as well.

For instance, if we want to make sure our Order is valid before processing it, we can annotate the payload with @Valid and configure the necessary validator, as follows:

@Configuration
@EnableRabbit
public class AppConfig implements RabbitListenerConfigurer {

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
    }

    @Bean
    public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setValidator(myValidator());
        return factory;
    }
}