Announcement Announcement Module
Collapse
No announcement yet.
How to delegate to method of object in MessageListenerAdapter to listen for messages? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to delegate to method of object in MessageListenerAdapter to listen for messages?

    The documentation and examples are not clear on how to delegate to a method to receive messages using Java and annotations. In the spring-rabbit-stocks example, the RabbitClientConfiguration delegates handling received messages to an object, clientHandler, which is an instance of ClientHandler.

    Code:
    @Configuration
    public class RabbitClientConfiguration extends AbstractStockAppRabbitConfiguration {
    
      @Autowired
      private ClientHandler clientHandler;
      ...
      @Bean 
      public MessageListenerAdapter messageListenerAdapter() {
        return new MessageListenerAdapter(clientHandler, jsonMessageConverter());    
      }
    The XML bean definition is:

    Code:
      <bean id="clientHandler" class="org.springframework.amqp.rabbit.stocks.handler.ClientHandler">
        <property name="stockController" ref="stockController"/>
      </bean>
    The ClientHandler is:

    Code:
    public class ClientHandler {
    
      private StockController stockController;
    
      public StockController getStockController() {
        return stockController;
      }
    
      public void setStockController(StockController stockController) {
        this.stockController = stockController;
      }
    
      public void handleMessage(Quote quote) {
        Stock stock = quote.getStock();
        stockController.displayQuote(quote);
      }
    
    }
    How does the MessageListenerAdapter know to use the handleMessage method?

    In the server messaging configuration for spring-rabbit-stocks, I can see that the listener was configured using XML and that there is a property called "method" which indicates the method that the listener will delegate to:

    Code:
      <listener-container concurrency="5" connection-factory="connectionFactory" message-converter="jsonMessageConverter"
        xmlns="http://www.springframework.org/schema/rabbit">
        <listener ref="serverHandler" method="handleMessage" queue-names="#{stockRequestQueue.name}" />
      </listener-container>
    Using annotated Java, as in the RabbitClientConfiguration example above, how do you identify the method that the listener delegates to?

  • #2
    See the javadocs for MessageListenerAdapter... http://static.springsource.org/sprin...erAdapter.html

    It just happens that the default name for the handler method is handleMessage(); using JavaConfig, simply pass the method name into setDefaultHandlerMethod()...

    http://static.springsource.org/sprin...a.lang.String)

    The method attribute in the namespace is simply passed into this property.

    Comment


    • #3
      Thank you. It works now. Here is the working code using JavaConfig. First, I set up the connection and set the listener to delegate to the handleMessage method of the EventHandler class:

      Code:
      @Configuration
      public class RabbitServerConfiguration {
      
        @Autowired
        private EventHandler eventHandler;
      
        //Connect to RabbitMQ on eventhub-server.
        @Bean
        public ConnectionFactory connectionFactory() {
          CachingConnectionFactory connectionFactory = new CachingConnectionFactory("eventhub-server");
          connectionFactory.setUsername("guest");
          connectionFactory.setPassword("guest");
          return connectionFactory;
        }
        
        //Get an instance of JsonMessageConverter to handle encoding/decoding JSON message data.
        public MessageConverter jsonMessageConverter() {
          return new JsonMessageConverter();
        }
        
        //Set the message listener container to use MessageListenerAdapter.
        @Bean
        public SimpleMessageListenerContainer messageListenerContainer() {
          SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
          container.setConnectionFactory(connectionFactory());
          container.setMessageListener(messageListenerAdapter());
          return container;
        }
        
        //Delegate messages to the handleMessage method of an instance of EventHandler
        //and use the jsonMessageConverter() object to convert the JSON message body.
        @Bean
        public MessageListenerAdapter messageListenerAdapter() {
          MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(eventHandler, jsonMessageConverter());
          listenerAdapter.setDefaultListenerMethod("handleMessage");
          return listenerAdapter;
        }
      }
      And here is the message handler which receives the EventType object that was in the message body in JSON format and automatically deserialized into the EventType object I want to use:

      Code:
      @Configuration
      public class EventHandler {
        protected static Logger logger = Logger.getLogger("EventHandler");
      
        //Get EventType POJO from the message body (which was serialized in JSON format).
        public void handleMessage(EventType event) {
          if (logger.isDebugEnabled()) {
            logger.debug("EventType received");
            logger.debug("  domain: " + event.getHead().getDomain());
            logger.debug("    time: " + event.getHead().getTimeStamp());
          }
        }
      }
      The @Configuration, @Bean, and @Autowired annotations take care of generating the beans. The only XML setup for this was these two lines in the servlet configuration XML:

      Code:
        <context:component-scan base-package="org.events.server.config"/>
      
        <mvc:annotation-driven />

      Comment

      Working...
      X