Details
Description
I use Apache NMS ActiveMQ together with Spring NMS and map messages. I use two persistent queues. Dequeuing without accessing the message and then queuing the same message again results in a removal of the complete body of the map message. The use case is that we move a map message to an error queue if an exception occurs while dequeuing. I've got a unit test which shows that behaviour (unit test fails but should not) with one persistent queue (queue=>dequeue=>queue=>dequeue):
UNIT TEST (withouth Spring NMS)
[Test] public void QueueDequeQueueDequeueTestWithoutSpringNms() { // This test should FAIL if the bug is fixed within the Apache NMS ActiveMQ framework var connecturi = new Uri("failover:(tcp://IP:PORT)?initialReconnectDelay=100"); IConnectionFactory factory = new ConnectionFactory(connecturi); using (IConnection connection = factory.CreateConnection()) using (ISession session = connection.CreateSession()) { IDestination destination = SessionUtil.GetDestination(session, "queue://FOO.BAR"); using (IMessageConsumer consumer = session.CreateConsumer(destination)) using (IMessageProducer producer = session.CreateProducer(destination)) { connection.Start(); producer.DeliveryMode = MsgDeliveryMode.Persistent; producer.RequestTimeout = TimeSpan.FromSeconds(5); consumer.Listener += DequeueFirstTime; var request = session.CreateMapMessage(); request.Body.SetString("Unit-Test-Key", "Unit-Test-Value"); // Queue Assert.IsNotNull(request, "request is null"); Assert.IsTrue(request.Body.Contains("Unit-Test-Key"), "Unit-Test-Key does not exist"); producer.Send(request); } } } private static void DequeueFirstTime(IMessage receivedMsg) { // Dequeue var currentMessage = receivedMsg as IMapMessage; Assert.IsNotNull(currentMessage, "currentMessage is null"); // This test should FAIL if the bug is fixed within the Apache NMS ActiveMQ framework var connecturi = new Uri("failover:(tcp://IP:PORT)?initialReconnectDelay=100"); IConnectionFactory factory = new ConnectionFactory(connecturi); using (IConnection connection = factory.CreateConnection()) using (ISession session = connection.CreateSession()) { IDestination destination = SessionUtil.GetDestination(session, "queue://FOO.BAR"); using (IMessageConsumer consumer = session.CreateConsumer(destination)) using (IMessageProducer producer = session.CreateProducer(destination)) { connection.Start(); producer.DeliveryMode = MsgDeliveryMode.Persistent; producer.RequestTimeout = TimeSpan.FromSeconds(5); consumer.Listener += DequeueSecondTime; // Queue again producer.Send(currentMessage); } } } private static void DequeueSecondTime(IMessage receivedMsg) { // Dequeue again var currentMessage = receivedMsg as IMapMessage; Assert.IsNotNull(currentMessage, "currentMessage is null"); // This entry in the map message should not be removed Assert.IsTrue(currentMessage.Body.Contains("Unit-Test-Key"), "Unit-Test-Key does not exist"); }
UNIT TEST (with Spring NMS)
[Test] public void QueueDequeueQueueDequeueTest() { IConnectionFactory factory = CreateConnectionFactory(); var nmsTemplate = new NmsTemplate(factory) { ReceiveTimeout = 5000 }; // Queue nmsTemplate.SendWithDelegate("queue://FOO.BAR", delegate(ISession session) { var mapMessage = session.CreateMapMessage(); mapMessage.Body.SetString("Unit-Test-Key", "Unit-Test-Value"); return mapMessage; }); // Dequeue var currentMessage = nmsTemplate.Receive("queue://FOO.BAR") as IMapMessage; Assert.IsNotNull(currentMessage, "currentMessage is null"); // Queue IMapMessage message = currentMessage; nmsTemplate.SendWithDelegate("queue://FOO.BAR", session => message); Assert.IsNotNull(currentMessage, "currentMessage is null"); // Dequeue currentMessage = nmsTemplate.Receive("queue://FOO.BAR") as IMapMessage; Assert.IsNotNull(currentMessage, "currentMessage is null"); Assert.IsTrue(currentMessage.Body.Contains("Unit-Test-Key"), "Unit-Test-Key does not exist"); }
I've checked the implementation. Using text messages everything is fine, but within the Apache.NMS.ActiveMQ.Commands.ActiveMQMapMessage class the Body property implementation is broken (with high probability )
Thanks for going on with Apache NMS!