'How to browse messages from a queue using Apache Camel?

I need to browse messages from an active mq using Camel route without consuming the messages.

The messages in the JMS queue are to be read(only browsed and not consumed) and moved to a database while ensuring that the original queue remains intact.

public class CamelStarter {

    private static CamelContext camelContext;

    public static void main(String[] args) throws Exception {
        camelContext = new DefaultCamelContext();
        ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(ActiveMQConnectionFactory.DEFAULT_BROKER_URL);

        camelContext.addComponent("jms",  JmsComponent.jmsComponent(connectionFactory));

        camelContext.addRoutes(new RouteBuilder() {

            @Override
            public void configure() throws Exception {
                from("jms:queue:testQueue").to("browse:orderReceived") .to("jms:queue:testQueue1");
            }

        }
                );

        camelContext.start();

        Thread.sleep(1000);

        inspectReceivedOrders();

        camelContext.stop();

    }

    public static void inspectReceivedOrders() {

        BrowsableEndpoint browse = camelContext.getEndpoint("browse:orderReceived", BrowsableEndpoint.class);
        List<Exchange> exchanges = browse.getExchanges();
        System.out.println("Browsing queue: "+ browse.getEndpointUri() + " size: " + exchanges.size());
        for (Exchange exchange : exchanges) {
            String payload = exchange.getIn().getBody(String.class);
            String msgId = exchange.getIn().getHeader("JMSMessageID", String.class);
            System.out.println(msgId + "=" +payload);
        }


Solution 1:[1]

As far as I know, not possible in Camel to read (without consuming !) JMS messages...
The only workaround I found (in a JEE app) was to define a startup EJB with a timer, holding a QueueBrowser, and delegating the msg processing to a Camel route:


    @Singleton
    @Startup
    public class MyQueueBrowser  {
    
        private TimerService timerService;
        
        @Resource(mappedName="java:/jms/queue/com.company.myqueue")
        private Queue sourceQueue;
        
        @Inject
        @JMSConnectionFactory("java:/ConnectionFactory")
        private JMSContext jmsContext;  
        
        @Inject
        @Uri("direct:readMessage")
        private ProducerTemplate camelEndpoint;
        
    
        @PostConstruct
        private void init() {       
            TimerConfig timerConfig = new TimerConfig(null, false);
            ScheduleExpression se = new ScheduleExpression().hour("*").minute("*/"+frequencyInMin);
            timerService.createCalendarTimer(se, timerConfig);
        }
        
        
        @Timeout
        public void scheduledExecution(Timer timer) throws Exception {      
            QueueBrowser browser = null;
            try {                       
                browser = jmsContext.createBrowser(sourceQueue);                                           
                Enumeration<Message> msgs = browser.getEnumeration();
                while ( msgs.hasMoreElements() ) { 
                    Message jmsMsg = msgs.nextElement(); 
                    // + here: read body and/or properties of jmsMsg                                            
                    camelEndpoint.sendBodyAndHeader(body, myHeaderName, myHeaderValue);
                }                                                                               
            } catch (JMSRuntimeException jmsException) {
                ...
            } finally {        
                browser.close();
            }
        }
    
        
    }

Solution 2:[2]

Apache camel browse component is exactly designed for that. Check here for the documentation.

Can't say more since you have not provided any other information.

Let's asssume you have a route like this

from("activemq:somequeue).to("bean:someBean")  

or

from("activemq:somequeue).process(exchange -> {})  

All you got to do it put a browse endpoint in between like this

from("activemq:somequeue).to("browse:someHandler").to("bean:someBean")   

Then write a class like this

    @Component
    public class BrowseQueue {
    
      @Autowired
      CamelContext camelContext;
    
      public void inspect() {
        BrowsableEndpoint browse = camelContext.getEndpoint("browse:someHandler", BrowsableEndpoint.class);
        List<Exchange> exchanges = browse.getExchanges();
    
        
        for (Exchange exchange : exchanges) {
          ...... 
        }
      }
    
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JoSSte
Solution 2 JoSSte