'How to listen to events without consuming them

I'm working on a simulator in Java that is using ActiveMQ for communication between the various parts, which will live on different machines. I have things mostly up and running, but the client has asked that one of the services log all events coming through. The catch is that, as far as I understand it, in Queue mode (the default setup in the code I'm working in), once read, the event is consumed. Is there a way to "peek" the event without consuming it? I've considered reading it, and then relogging it, but it feels like that would require an additional level of checking to be sure the logging service doesn't then just grab it again.



Solution 1:[1]

Ultimately, I wound up going with a Topic setup with publishers and listed subscribers due to the simplicity of defining which services would receive which topics, and the current setup having messages consumed almost as fast as they can be produced. All I had to do was to have the logging module subscribe to all defined messages, as well as any other modules that would receive them.

Solution 2:[2]

If you're using Java and since you're using a queue then you can use a JMS QueueBrowser. It will allow you to inspect the messages on the queue without actually consuming them.

You might also consider using a mirrored queue as it was designed with this type of use-case in mind.

Solution 3:[3]

Consider that in your design you may have more than one subscriber to the flow of events-- the application consuming messages, and the logging service that needs to trace information. Allowing the logging service to receive their own copy of messages, and they can store or discard as needed

Check out the Virtual Topic pattern-- send message to a topic and read from a queue. With this design, you can add additional subscribers at any time and provide the logging service their own copy of messages.

Edit:

Additionally, you can configure a composite destination to send a copy of messages to a second queue.

<destinationInterceptors>
  <virtualDestinationInterceptor> 
    <virtualDestinations> 
      <compositeQueue name="APP.DATA.IN" forwardOnly="false"> 
        <forwardTo>
          <queue physicalName="APP.DATA.IN.LOGGING.SERVICE" />
        </forwardTo>
     </compositeQueue>
   </virtualDestinations>
 </virtualDestinationInterceptor>

This would need to be manually added for each queue you want a second copy. With the Virtual Topic approach, you do not need to add a configuration for each.

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 Sean Duggan
Solution 2 Justin Bertram
Solution 3