Uploaded image for project: 'ActiveMQ .Net'
  1. ActiveMQ .Net
  2. AMQNET-514

Lazy loading of map messages does not work correctly

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Critical
    • Resolution: Fixed
    • Affects Version/s: 1.7.0, 1.7.1
    • Fix Version/s: 1.7.2
    • Component/s: ActiveMQ, NMS
    • Labels:
    • Environment:

      Apache NMS 1.7.0.3635
      Apache NMS ActiveMQ 1.7.0.3660
      Runtime Version v4.0.30319
      Spring Messaging NMS 2.0.1.40000

    • Regression:
      Unit Test Broken
    • Flags:
      Important

      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!

        Attachments

          Activity

            People

            • Assignee:
              tabish Timothy A. Bish
              Reporter:
              oprobst88 Oliver Probst
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: