You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ro...@apache.org on 2014/01/30 18:37:42 UTC

svn commit: r1562905 - in /qpid/jms/trunk/src: main/java/org/apache/qpid/jms/engine/ main/java/org/apache/qpid/jms/impl/ test/java/org/apache/qpid/jms/ test/java/org/apache/qpid/jms/engine/ test/java/org/apache/qpid/jms/impl/

Author: robbie
Date: Thu Jan 30 17:37:41 2014
New Revision: 1562905

URL: http://svn.apache.org/r1562905
Log:
QPIDJMS-9: initial work on message-id (and eventually correlation-id) handling

Added:
    qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageIdHelper.java
    qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageIdHelperTest.java
Modified:
    qpid/jms/trunk/src/main/java/org/apache/qpid/jms/engine/AmqpMessage.java
    qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/ConnectionImpl.java
    qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageImpl.java
    qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/SessionImpl.java
    qpid/jms/trunk/src/test/java/org/apache/qpid/jms/MessageIntegrationTest.java
    qpid/jms/trunk/src/test/java/org/apache/qpid/jms/engine/AmqpMessageTest.java
    qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageImplTest.java

Modified: qpid/jms/trunk/src/main/java/org/apache/qpid/jms/engine/AmqpMessage.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/main/java/org/apache/qpid/jms/engine/AmqpMessage.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/main/java/org/apache/qpid/jms/engine/AmqpMessage.java (original)
+++ qpid/jms/trunk/src/main/java/org/apache/qpid/jms/engine/AmqpMessage.java Thu Jan 30 17:37:41 2014
@@ -20,16 +20,21 @@
  */
 package org.apache.qpid.jms.engine;
 
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import org.apache.qpid.proton.Proton;
+import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedByte;
 import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.messaging.Accepted;
 import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
 import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
@@ -426,6 +431,82 @@ public abstract class AmqpMessage
         }
     }
 
+    /**
+     * Get the MessageId.
+     *
+     * If present, the returned object may be a String, UUID,
+     * ByteBuffer (representing binary), or BigInteger (representing ulong).
+     *
+     * @return the messageId, or null if there isn't any
+     */
+    public Object getMessageId()
+    {
+        Object underlyingMessageId = _message.getMessageId();
+
+        if(underlyingMessageId instanceof Binary)
+        {
+            return ((Binary) underlyingMessageId).asByteBuffer();
+        }
+        else if(underlyingMessageId instanceof UnsignedLong)
+        {
+            return ((UnsignedLong) underlyingMessageId).bigIntegerValue();
+        }
+        else
+        {
+            return underlyingMessageId;
+        }
+    }
+
+    /**
+     * Set a string message-id value on the message.
+     */
+    public void setMessageId(String messageId)
+    {
+        setUnderlyingMessageId(messageId);
+    }
+
+    /**
+     * Set a uuid message-id value on the message.
+     */
+    public void setMessageId(UUID messageId)
+    {
+        setUnderlyingMessageId(messageId);
+    }
+
+    /**
+     * Set an ulong (represented here as a BigInteger) message-id value on the message.
+     *
+     * @param messageId the value to set
+     * @throws IllegalArgumentException if the value is not within the ulong range of [0 - 2^64)
+     */
+    public void setMessageId(BigInteger messageId) throws IllegalArgumentException
+    {
+        if(messageId.signum() == -1 || messageId.bitLength() > 64)
+        {
+            throw new IllegalArgumentException("Value \""+messageId+"\" lies outside the range [0 - 2^64).");
+        }
+
+        //TODO: add UnsignedLong.valueOf(BigInteger)?
+        setUnderlyingMessageId(UnsignedLong.valueOf(messageId.toString()));
+    }
+
+    /**
+     * Set a Binary (represented here as a ByteBuffer) message-id value on the message.
+     *
+     * @param messageId the value to set
+     */
+    public void setMessageId(ByteBuffer messageId)
+    {
+        Binary bin = Binary.create(messageId);
+
+        setUnderlyingMessageId(bin);
+    }
+
+    private void setUnderlyingMessageId(Object messageId)
+    {
+        _message.setMessageId(messageId);
+    }
+
     //===== Application Properties ======
 
     private void createApplicationProperties()

Modified: qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/ConnectionImpl.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/ConnectionImpl.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/ConnectionImpl.java (original)
+++ qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/ConnectionImpl.java Thu Jan 30 17:37:41 2014
@@ -63,6 +63,7 @@ public class ConnectionImpl implements C
     private volatile boolean _isStarted;
 
     private DestinationHelper _destinationHelper;
+    private MessageIdHelper _messageIdHelper;
 
     /**
      * TODO: accept a client id
@@ -97,6 +98,7 @@ public class ConnectionImpl implements C
         }
 
         _destinationHelper = new DestinationHelper();
+        _messageIdHelper = new MessageIdHelper();
     }
 
     void waitUntil(Predicate condition, long timeoutMillis) throws JmsTimeoutException, JmsInterruptedException
@@ -287,7 +289,7 @@ public class ConnectionImpl implements C
         {
             AmqpSession amqpSession = _amqpConnection.createSession();
 
-            SessionImpl session = new SessionImpl(acknowledgeMode, amqpSession, this, _destinationHelper);
+            SessionImpl session = new SessionImpl(acknowledgeMode, amqpSession, this, _destinationHelper, _messageIdHelper);
             stateChanged();
             session.establish();
 

Added: qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageIdHelper.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageIdHelper.java?rev=1562905&view=auto
==============================================================================
--- qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageIdHelper.java (added)
+++ qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageIdHelper.java Thu Jan 30 17:37:41 2014
@@ -0,0 +1,146 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.jms.impl;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+
+/**
+ * Helper class for identifying and converting message-id and correlation-id strings.
+ *
+ * <p>AMQP messages allow for 4 types of message-id/correlation-id: string, binary, uuid, ulong.
+ * In order to accept or return a string representation of these for interoperability with
+ * other AMQP clients, the following encoding can be used after the "ID:" prefix used for a JMSMessageID<br/>
+ *
+ * "AMQP_BINARY:&lt;hex representation of binary content&gt;"<br/>
+ * "AMQP_UUID:&lt;string representation of uuid&gt;"<br/>
+ * "AMQP_ULONG:&lt;string representation of ulong&gt;"<br/>
+ * "AMQP_STRING:&lt;string&gt;"<br/>
+ *
+ * <p>The AMQP_STRING encoding exists only for escaping string values that happen to begin with one
+ * of the encoding prefixes (including AMQP_STRING), or for consistency of appearance. It need not be used unless necessary.
+ *
+ * <p>When setting a JMSMessageID, any value that attempts to identify itself as an encoded Binary, UUID, or ulong but cant be
+ * converted into the indicated format will default to being treated as a simple String in its entirety (including the
+ * encoding prefix). For example, "AMQP_ULONG:hello" can't be encoded as a ulong, and so the full string "AMQP_ULONG:hello"
+ * would be used as the message-id value on the AMQP message.
+ *
+ * <p>When setting a JMSCorrelationID using setJMSCorrelationID(String id), any value which begins with the "ID:" prefix of a
+ * JMSMessageID that attempts to identify itself as an encoded binary, uuid, or ulong but cant be converted into the indicated
+ * format will cause an exception to be thrown. Any JMSCorrelationID String being set which does not begin with the "ID:"
+ * prefix of a JMSMessageID will beencoded as a String in the AMQP message, regardless whether it includes the above encoding
+ * prefixes.
+ *
+ */
+public class MessageIdHelper
+{
+    public static final String AMQP_STRING_PREFIX="AMQP_STRING:";
+    public static final String AMQP_UUID_PREFIX="AMQP_UUID:";
+    public static final String AMQP_LONG_PREFIX="AMQP_LONG:";
+    public static final String AMQP_BINARY_PREFIX="AMQP_BINARY:";
+    public static final String JMS_ID_PREFIX = "ID:";
+
+    private static final int JMS_ID_PREFIX_LENGTH = JMS_ID_PREFIX.length();
+
+    /**
+     * Checks whether the given string begins with "ID:" prefix used to denote a JMSMessageID
+     *
+     * @param string the string to check
+     * @return true if and only id the string begins with "ID:"
+     */
+    public boolean hasMessageIdPrefix(String string)
+    {
+        if(string == null)
+        {
+            return false;
+        }
+
+        return string.startsWith(JMS_ID_PREFIX);
+    }
+
+    /**
+     * Returns the suffix of the given string after removing the first "ID:" prefix (if present).
+     *
+     * @param string the string to process
+     * @return the suffix, or the original String if the "ID:" prefix is not present
+     */
+    public String stripMessageIdPrefix(String id)
+    {
+        if(hasMessageIdPrefix(id))
+        {
+            return id.substring(JMS_ID_PREFIX_LENGTH);
+        }
+        else
+        {
+            return id;
+        }
+    }
+
+    public String toBaseMessageIdString(Object messageId)
+    {
+        if(messageId == null)
+        {
+            return null;
+        }
+        else if(messageId instanceof String)
+        {
+            String stringId = (String) messageId;
+
+            //If the given string has a type encoding prefix,
+            //we need to escape it as an encoded string (even if
+            //the existing encoding prefix was also for string)
+            if(hasTypeEncodingPrefix(stringId))
+            {
+                return AMQP_STRING_PREFIX + stringId;
+            }
+            else
+            {
+                return stringId;
+            }
+        }
+        else if(messageId instanceof UUID)
+        {
+            return AMQP_UUID_PREFIX + messageId.toString();
+        }
+        else if(messageId instanceof Number)
+        {
+            //TODO: use Byte/Short/Integer/Long/BigInteger check instead?
+            return AMQP_LONG_PREFIX + messageId.toString();
+        }
+        else if(messageId instanceof ByteBuffer)
+        {
+            //TODO: implement
+            throw new UnsupportedOperationException("Support for Binary has yet to be implemented");
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unsupported type provided: " + messageId.getClass());
+        }
+    }
+
+    private boolean hasTypeEncodingPrefix(String stringId)
+    {
+        return stringId.startsWith(AMQP_BINARY_PREFIX) ||
+                    stringId.startsWith(AMQP_UUID_PREFIX) ||
+                        stringId.startsWith(AMQP_LONG_PREFIX) ||
+                            stringId.startsWith(AMQP_STRING_PREFIX);
+    }
+}

Modified: qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageImpl.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageImpl.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageImpl.java (original)
+++ qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/MessageImpl.java Thu Jan 30 17:37:41 2014
@@ -19,6 +19,7 @@
 package org.apache.qpid.jms.impl;
 
 import static org.apache.qpid.jms.impl.ClientProperties.JMS_AMQP_TTL;
+import static org.apache.qpid.jms.impl.MessageIdHelper.JMS_ID_PREFIX;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -173,15 +174,35 @@ public abstract class MessageImpl<T exte
     @Override
     public String getJMSMessageID() throws JMSException
     {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException("Not Implemented");
+        MessageIdHelper messageIdHelper = _sessionImpl.getMessageIdHelper();
+
+        String baseIdString = messageIdHelper.toBaseMessageIdString(_amqpMessage.getMessageId());
+
+        if(baseIdString == null)
+        {
+            return null;
+        }
+        else
+        {
+            return JMS_ID_PREFIX + baseIdString;
+        }
     }
 
     @Override
     public void setJMSMessageID(String id) throws JMSException
     {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException("Not Implemented");
+        MessageIdHelper messageIdHelper = _sessionImpl.getMessageIdHelper();
+
+        //We permit null, but otherwise ensure that the value starts "ID:"
+        if(id != null && !messageIdHelper.hasMessageIdPrefix(id))
+        {
+            throw new QpidJmsException("Provided JMSMessageID does not have required '" + JMS_ID_PREFIX + "' prefix");
+        }
+
+        String stripped = messageIdHelper.stripMessageIdPrefix(id);
+        //TODO: convert the string if necessary, i.e. it indicates an encoded AMQP type
+
+        _amqpMessage.setMessageId(stripped);
     }
 
     @Override

Modified: qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/SessionImpl.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/SessionImpl.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/SessionImpl.java (original)
+++ qpid/jms/trunk/src/main/java/org/apache/qpid/jms/impl/SessionImpl.java Thu Jan 30 17:37:41 2014
@@ -55,13 +55,15 @@ public class SessionImpl implements Sess
     private final AmqpSession _amqpSession;
     private final ConnectionImpl _connectionImpl;
     private final DestinationHelper _destinationHelper;
+    private final MessageIdHelper _messageIdHelper;
 
-    public SessionImpl(int acknowledgeMode, AmqpSession amqpSession, ConnectionImpl connectionImpl, DestinationHelper destinationHelper)
+    public SessionImpl(int acknowledgeMode, AmqpSession amqpSession, ConnectionImpl connectionImpl, DestinationHelper destinationHelper, MessageIdHelper messageIdHelper)
     {
         _acknowledgeMode = acknowledgeMode;
         _amqpSession = amqpSession;
         _connectionImpl = connectionImpl;
         _destinationHelper = destinationHelper;
+        _messageIdHelper = messageIdHelper;
     }
 
      void establish() throws JmsTimeoutException, JmsInterruptedException
@@ -124,6 +126,11 @@ public class SessionImpl implements Sess
         }
     }
 
+    public MessageIdHelper getMessageIdHelper()
+    {
+        return _messageIdHelper;
+    }
+
     DestinationHelper getDestinationHelper()
     {
         return _destinationHelper;

Modified: qpid/jms/trunk/src/test/java/org/apache/qpid/jms/MessageIntegrationTest.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/test/java/org/apache/qpid/jms/MessageIntegrationTest.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/test/java/org/apache/qpid/jms/MessageIntegrationTest.java (original)
+++ qpid/jms/trunk/src/test/java/org/apache/qpid/jms/MessageIntegrationTest.java Thu Jan 30 17:37:41 2014
@@ -25,7 +25,9 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import java.math.BigInteger;
 import java.util.Date;
+import java.util.UUID;
 
 import javax.jms.Connection;
 import javax.jms.Destination;
@@ -38,6 +40,7 @@ import javax.jms.TextMessage;
 import javax.jms.Topic;
 
 import org.apache.qpid.jms.impl.DestinationHelper;
+import org.apache.qpid.jms.impl.MessageIdHelper;
 import org.apache.qpid.jms.test.testpeer.TestAmqpPeer;
 import org.apache.qpid.jms.test.testpeer.describedtypes.sections.AmqpValueDescribedType;
 import org.apache.qpid.jms.test.testpeer.describedtypes.sections.ApplicationPropertiesDescribedType;
@@ -50,6 +53,7 @@ import org.apache.qpid.jms.test.testpeer
 import org.apache.qpid.jms.test.testpeer.matchers.sections.TransferPayloadCompositeMatcher;
 import org.apache.qpid.jms.test.testpeer.matchers.types.EncodedAmqpValueMatcher;
 import org.apache.qpid.proton.amqp.DescribedType;
+import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.junit.Test;
 
 public class MessageIntegrationTest extends QpidJmsTestCase
@@ -449,4 +453,72 @@ public class MessageIntegrationTest exte
             assertEquals(timestamp, receivedMessage.getJMSExpiration());
         }
     }
+
+    /**
+     * Tests that receiving a message with a string typed message-id results in returning the
+     * expected value for JMSMessageId where the JMS "ID:" prefix has been added.
+     */
+    @Test
+    public void testReceivedMessageWithStringMessageIdReturnsExpectedJMSMessageID() throws Exception
+    {
+        receivedMessageWithMessageIdTestImpl("myTestMessageIdString");
+    }
+
+    /**
+     * Tests that receiving a message with a UUID typed message-id results in returning the
+     * expected value for JMSMessageId where the JMS "ID:" prefix has been added to the UUID.tostring()
+     */
+    @Test
+    public void testReceivedMessageWithUUIDMessageIdReturnsExpectedJMSMessageID() throws Exception
+    {
+        receivedMessageWithMessageIdTestImpl(UUID.randomUUID());
+    }
+
+    /**
+     * Tests that receiving a message with a UUID typed message-id results in returning the
+     * expected value for JMSMessageId where the JMS "ID:" prefix has been added to the UUID.tostring()
+     */
+    @Test
+    public void testReceivedMessageWithLongMessageIdReturnsExpectedJMSMessageID() throws Exception
+    {
+        receivedMessageWithMessageIdTestImpl(BigInteger.valueOf(123456789L));
+    }
+
+    private void receivedMessageWithMessageIdTestImpl(Object messageId) throws Exception
+    {
+        try(TestAmqpPeer testPeer = new TestAmqpPeer(IntegrationTestFixture.PORT);)
+        {
+            Connection connection = _testFixture.establishConnecton(testPeer);
+            connection.start();
+
+            testPeer.expectBegin();
+
+            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            Queue queue = session.createQueue("myQueue");
+
+            Object underlyingAmqpMessageId = messageId;
+            if(underlyingAmqpMessageId instanceof BigInteger)
+            {
+                //Proton uses UnsignedLong
+                underlyingAmqpMessageId = UnsignedLong.valueOf(underlyingAmqpMessageId.toString());
+            }
+
+            PropertiesDescribedType props = new PropertiesDescribedType();
+            props.setMessageId(underlyingAmqpMessageId);
+            DescribedType amqpValueNullContent = new AmqpValueDescribedType(null);
+
+            testPeer.expectReceiverAttach();
+            testPeer.expectLinkFlowRespondWithTransfer(null, null, props, null, amqpValueNullContent);
+            testPeer.expectDispositionThatIsAcceptedAndSettled();
+
+            MessageConsumer messageConsumer = session.createConsumer(queue);
+            Message receivedMessage = messageConsumer.receive(1000);
+            testPeer.waitForAllHandlersToComplete(3000);
+
+            assertNotNull(receivedMessage);
+            String expectedBaseIdString = new MessageIdHelper().toBaseMessageIdString(underlyingAmqpMessageId);
+
+            assertEquals("ID:" + expectedBaseIdString, receivedMessage.getJMSMessageID());
+        }
+    }
 }

Modified: qpid/jms/trunk/src/test/java/org/apache/qpid/jms/engine/AmqpMessageTest.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/test/java/org/apache/qpid/jms/engine/AmqpMessageTest.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/test/java/org/apache/qpid/jms/engine/AmqpMessageTest.java (original)
+++ qpid/jms/trunk/src/test/java/org/apache/qpid/jms/engine/AmqpMessageTest.java Thu Jan 30 17:37:41 2014
@@ -22,15 +22,20 @@ package org.apache.qpid.jms.engine;
 
 import static org.junit.Assert.*;
 
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
 import org.apache.qpid.jms.QpidJmsTestCase;
 import org.apache.qpid.proton.Proton;
+import org.apache.qpid.proton.amqp.Binary;
 import org.apache.qpid.proton.amqp.Symbol;
 import org.apache.qpid.proton.amqp.UnsignedByte;
 import org.apache.qpid.proton.amqp.UnsignedInteger;
+import org.apache.qpid.proton.amqp.UnsignedLong;
 import org.apache.qpid.proton.amqp.messaging.ApplicationProperties;
 import org.apache.qpid.proton.amqp.messaging.Header;
 import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
@@ -47,6 +52,7 @@ public class AmqpMessageTest extends Qpi
     private static final String TEST_PROP_B = "TEST_PROP_B";
     private static final String TEST_VALUE_STRING_A = "TEST_VALUE_STRING_A";
     private static final String TEST_VALUE_STRING_B = "TEST_VALUE_STRING_B";
+    private static final byte[] TWO_TO_64_BYTES = new byte[] { (byte) 1, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 };
 
     private AmqpConnection _mockAmqpConnection;
     private Delivery _mockDelivery;
@@ -551,6 +557,188 @@ public class AmqpMessageTest extends Qpi
         assertNull(testAmqpMessage.getAbsoluteExpiryTime());
     }
 
+    //TODO: delete this marker comment
+    @Test
+    public void testGetMessageIdIsNullOnNewMessage()
+    {
+        TestAmqpMessage testAmqpMessage = new TestAmqpMessage();
+
+        assertNull("Expected messageId to be null on new message", testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that setting then getting a String as the messageId returns the expected value
+     */
+    @Test
+    public void testSetGetMessageIdOnNewMessageWithString()
+    {
+        String testMessageId = "myStringMessageId";
+
+        AmqpMessage testAmqpMessage = new TestAmqpMessage();
+        testAmqpMessage.setMessageId(testMessageId);
+
+        assertEquals("Expected messageId not returned", testMessageId, testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that getting the messageId when using an underlying received message with a
+     * String message id returns the expected value.
+     */
+    @Test
+    public void testGetMessageIdOnReceivedMessageWithString()
+    {
+        messageIdOnReceivedMessageTestImpl("myMessageIdString");
+    }
+
+    /**
+     * Test that setting then getting a UUID as the messageId returns the expected value
+     */
+    @Test
+    public void testSetGetMessageIdOnNewMessageWithUUID()
+    {
+        UUID testMessageId = UUID.randomUUID();
+
+        AmqpMessage testAmqpMessage = new TestAmqpMessage();
+        testAmqpMessage.setMessageId(testMessageId);
+
+        assertEquals("Expected messageId not returned", testMessageId, testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that getting the messageId when using an underlying received message with a
+     * UUID message id returns the expected value.
+     */
+    @Test
+    public void testGetMessageIdOnReceivedMessageWithUUID()
+    {
+        messageIdOnReceivedMessageTestImpl(UUID.randomUUID());
+    }
+
+    /**
+     * Test that setting then getting a ulong messageId (using BigInteger) returns the expected value
+     */
+    @Test
+    public void testSetGetMessageIdOnNewMessageWithULong()
+    {
+        BigInteger testMessageId = BigInteger.valueOf(123456789);
+
+        AmqpMessage testAmqpMessage = new TestAmqpMessage();
+        testAmqpMessage.setMessageId(testMessageId);
+
+        assertEquals("Expected messageId not returned", testMessageId, testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that getting the messageId when using an underlying received message with a
+     * ulong message id (using BigInteger) returns the expected value.
+     */
+    @Test
+    public void testGetMessageIdOnReceivedMessageWithLong()
+    {
+        messageIdOnReceivedMessageTestImpl(BigInteger.valueOf(123456789L));
+    }
+
+    /**
+     * Test that attempting to set a ulong messageId (using BigInteger) with a value
+     * outwith the allowed [0 - 2^64) range results in an IAE being thrown
+     */
+    @Test
+    public void testSetMessageIdOnNewMessageWithULongOurOfRangeThrowsIAE()
+    {
+        //negative value
+        AmqpMessage testAmqpMessage = new TestAmqpMessage();
+        try
+        {
+            testAmqpMessage.setMessageId(BigInteger.valueOf(-1));
+            fail("expected exception was not thrown");
+        }
+        catch(IllegalArgumentException iae)
+        {
+            //expected
+        }
+
+        //value 1 over max
+        BigInteger aboveLimit = new BigInteger(TWO_TO_64_BYTES);
+        try
+        {
+            testAmqpMessage.setMessageId(aboveLimit);
+            fail("expected exception was not thrown");
+        }
+        catch(IllegalArgumentException iae)
+        {
+            //expected
+        }
+
+        //confirm subtracting 1 to get the max value then allows success
+        BigInteger onLimit = aboveLimit.subtract(BigInteger.ONE);
+        testAmqpMessage.setMessageId(onLimit);
+    }
+
+    /**
+     * Test that setting then getting binary as the messageId returns the expected value
+     */
+    @Test
+    public void testSetGetMessageIdOnNewMessageWithBinary()
+    {
+        ByteBuffer testMessageId = createByteBufferForBinaryId();
+
+        AmqpMessage testAmqpMessage = new TestAmqpMessage();
+        testAmqpMessage.setMessageId(testMessageId);
+
+        assertEquals("Expected messageId not returned", testMessageId, testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that getting the messageId when using an underlying received message with a
+     * Binary message id returns the expected ByteBuffer value.
+     */
+    @Test
+    public void testGetMessageIdOnReceivedMessageWithBinary()
+    {
+        ByteBuffer testMessageId = createByteBufferForBinaryId();
+
+        messageIdOnReceivedMessageTestImpl(testMessageId);
+    }
+
+    private void messageIdOnReceivedMessageTestImpl(Object testMessageId)
+    {
+        Object underlyingIdObject = testMessageId;
+        if(testMessageId instanceof ByteBuffer)
+        {
+            //The proton message uses a Binary wrapper for binary ids, not a ByteBuffer
+            underlyingIdObject = Binary.create((ByteBuffer) testMessageId);
+        }
+        else if(testMessageId instanceof BigInteger)
+        {
+            //The proton message uses an UnsignedLong wrapper
+            underlyingIdObject = UnsignedLong.valueOf(((BigInteger) testMessageId).toString());
+        }
+
+        Message message = Proton.message();
+
+        Properties props = new Properties();
+        props.setMessageId(underlyingIdObject);
+        message.setProperties(props);
+
+        TestAmqpMessage testAmqpMessage = new TestAmqpMessage(message, _mockDelivery, _mockAmqpConnection);
+
+        assertNotNull("Expected a messageId on received message", testAmqpMessage.getMessageId());
+
+        assertEquals("Incorrect messageId value received", testMessageId, testAmqpMessage.getMessageId());
+    }
+
+    private ByteBuffer createByteBufferForBinaryId()
+    {
+        byte length = 10;
+        byte[] idBytes = new byte[length];
+        for(int i = 0; i < length; i++)
+        {
+            idBytes[i] = (byte) (length - i);
+        }
+
+        return ByteBuffer.wrap(idBytes);
+    }
+
     // ====== Message Annotations =======
 
     @Test

Added: qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageIdHelperTest.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageIdHelperTest.java?rev=1562905&view=auto
==============================================================================
--- qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageIdHelperTest.java (added)
+++ qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageIdHelperTest.java Thu Jan 30 17:37:41 2014
@@ -0,0 +1,291 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.jms.impl;
+
+import static org.junit.Assert.*;
+
+import java.math.BigInteger;
+import java.util.UUID;
+
+import org.apache.qpid.jms.QpidJmsTestCase;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MessageIdHelperTest extends QpidJmsTestCase
+{
+    private MessageIdHelper _messageIdHelper;
+
+    @Before
+    public void setUp() throws Exception
+    {
+        super.setUp();
+
+        _messageIdHelper = new MessageIdHelper();
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#hasMessageIdPrefix(String)} returns true for strings that begin "ID:"
+     */
+    @Test
+    public void testHasIdPrefixWithPrefix()
+    {
+        String myId = "ID:something";
+        assertTrue("'ID:' prefix should have been identified", _messageIdHelper.hasMessageIdPrefix(myId));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#hasMessageIdPrefix(String)} returns false for string beings "ID" without colon.
+     */
+    @Test
+    public void testHasIdPrefixWithIDButNoColonPrefix()
+    {
+        String myIdNoColon = "IDsomething";
+        assertFalse("'ID' prefix should not have been identified without trailing colon", _messageIdHelper.hasMessageIdPrefix(myIdNoColon));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#hasMessageIdPrefix(String)} returns false for null
+     */
+    @Test
+    public void testHasIdPrefixWithNull()
+    {
+        String nullString = null;
+        assertFalse("null string should not result in identification as having the prefix", _messageIdHelper.hasMessageIdPrefix(nullString));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#hasMessageIdPrefix(String)} returns false for strings that doesnt have "ID:" anywhere
+     */
+    @Test
+    public void testHasIdPrefixWithoutPrefix()
+    {
+        String myNonId = "something";
+        assertFalse("string without 'ID:' anywhere should not have been identified as having the prefix", _messageIdHelper.hasMessageIdPrefix(myNonId));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#hasMessageIdPrefix(String)} returns false for strings has lowercase "id:" prefix
+     */
+    @Test
+    public void testHasIdPrefixWithLowercaseID()
+    {
+        String myLowerCaseNonId = "id:something";
+        assertFalse("lowercase 'id:' prefix should not result in identification as having 'ID:' prefix", _messageIdHelper.hasMessageIdPrefix(myLowerCaseNonId));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#stripMessageIdPrefix(String)} strips "ID:" from strings that do begin "ID:"
+     */
+    @Test
+    public void testStripMessageIdPrefixWithPrefix()
+    {
+        String myIdWithoutPrefix = "something";
+        String myId = "ID:" + myIdWithoutPrefix;
+        assertEquals("'ID:' prefix should have been stripped", myIdWithoutPrefix, _messageIdHelper.stripMessageIdPrefix(myId));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#stripMessageIdPrefix(String)} only strips one "ID:" from strings that
+     * begin "ID:ID:...."
+     */
+    @Test
+    public void testStripMessageIdPrefixWithDoublePrefix()
+    {
+        String myIdWithSinglePrefix = "ID:something";
+        String myIdWithDoublePrefix = "ID:" + myIdWithSinglePrefix;
+        assertEquals("'ID:' prefix should only have been stripped once", myIdWithSinglePrefix, _messageIdHelper.stripMessageIdPrefix(myIdWithDoublePrefix));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#stripMessageIdPrefix(String)} does not alter strings that begins "ID" without a colon.
+     */
+    @Test
+    public void testStripMessageIdPrefixWithIDButNoColonPrefix()
+    {
+        String myIdNoColon = "IDsomething";
+        assertEquals("string without 'ID:' prefix should have been returned unchanged", myIdNoColon, _messageIdHelper.stripMessageIdPrefix(myIdNoColon));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#stripMessageIdPrefix(String)} returns null if given null;
+     */
+    @Test
+    public void testStripMessageIdPrefixWithNull()
+    {
+        String nullString = null;
+        assertNull("null string should have been returned", _messageIdHelper.stripMessageIdPrefix(nullString));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#stripMessageIdPrefix(String)} does not alter string that doesn't begin "ID:"
+     */
+    @Test
+    public void testStripMessageIdPrefixWithoutIDAnywhere()
+    {
+        String myNonId = "something";
+        assertEquals("string without 'ID:' anywhere should have been returned unchanged", myNonId, _messageIdHelper.stripMessageIdPrefix(myNonId));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#stripMessageIdPrefix(String)} does not alter string with lowercase "id:"
+     */
+    @Test
+    public void testStripMessageIdPrefixWithLowercaseID()
+    {
+        String myLowerCaseNonId = "id:something";
+        assertEquals("string with lowercase 'id:' prefix should have been returned unchanged", myLowerCaseNonId, _messageIdHelper.stripMessageIdPrefix(myLowerCaseNonId));
+    }
+
+    //TODO: delete this marker comment
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns null if given null
+     */
+    @Test
+    public void testToBaseMessageIdStringWithNull()
+    {
+        String nullString = null;
+        assertNull("null string should have been returned", _messageIdHelper.toBaseMessageIdString(nullString));
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} throws an IAE if given an unexpected object type.
+     */
+    @Test
+    public void testToBaseMessageIdStringThrowsIAEWithUnexpectedType()
+    {
+        try
+        {
+            _messageIdHelper.toBaseMessageIdString(new Object());
+            fail("expected exception not thrown");
+        }
+        catch(IllegalArgumentException iae)
+        {
+            //expected
+        }
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns the given
+     * basic string unchanged
+     */
+    @Test
+    public void testToBaseMessageIdStringWithString()
+    {
+        String stringMessageId = "myIdString";
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(stringMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", stringMessageId, baseMessageIdString);
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns a string
+     * indicating an AMQP encoded string, when the given string happens to already begin with
+     * the {@link MessageIdHelper#AMQP_UUID_PREFIX}.
+     */
+    @Test
+    public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForUUID()
+    {
+        String uuidStringMessageId = MessageIdHelper.AMQP_UUID_PREFIX + UUID.randomUUID();
+        String expected = MessageIdHelper.AMQP_STRING_PREFIX + uuidStringMessageId;
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(uuidStringMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns a string
+     * indicating an AMQP encoded string, when the given string happens to already begin with
+     * the {@link MessageIdHelper#AMQP_LONG_PREFIXM}.
+     */
+    @Test
+    public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForLong()
+    {
+        String longStringMessageId = MessageIdHelper.AMQP_LONG_PREFIX + Long.valueOf(123456789L);
+        String expected = MessageIdHelper.AMQP_STRING_PREFIX + longStringMessageId;
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(longStringMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns a string
+     * indicating an AMQP encoded string (effectively twice), when the given string happens to already begin with
+     * the {@link MessageIdHelper#AMQP_STRING_PREFIX}.
+     */
+    @Test
+    public void testToBaseMessageIdStringWithStringBeginningWithEncodingPrefixForString()
+    {
+        String stringMessageId = MessageIdHelper.AMQP_STRING_PREFIX + "myStringId";
+        String expected = MessageIdHelper.AMQP_STRING_PREFIX + stringMessageId;
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(stringMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns a string
+     * indicating an AMQP encoded UUID when given a UUID object.
+     */
+    @Test
+    public void testToBaseMessageIdStringWithUUID()
+    {
+        UUID uuidMessageId = UUID.randomUUID();
+        String expected = MessageIdHelper.AMQP_UUID_PREFIX + uuidMessageId.toString();
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(uuidMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns a string
+     * indicating an AMQP encoded Long when given a Long object.
+     */
+    @Test
+    public void testToBaseMessageIdStringWithLong()
+    {
+        Long longMessageId = Long.valueOf(123456789L);
+        String expected = MessageIdHelper.AMQP_LONG_PREFIX + longMessageId.toString();
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(longMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+    }
+
+    /**
+     * Test that {@link MessageIdHelper#toBaseMessageIdString(String)} returns a string
+     * indicating an AMQP encoded Long when given a BigInteger object.
+     */
+    @Test
+    public void testToBaseMessageIdStringWithBigInteger()
+    {
+        BigInteger bigIntMessageId = BigInteger.valueOf(123456789L);
+        String expected = MessageIdHelper.AMQP_LONG_PREFIX + bigIntMessageId.toString();
+
+        String baseMessageIdString = _messageIdHelper.toBaseMessageIdString(bigIntMessageId);
+        assertNotNull("null string should not have been returned", baseMessageIdString);
+        assertEquals("expected base id string was not returned", expected, baseMessageIdString);
+    }
+}

Modified: qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageImplTest.java
URL: http://svn.apache.org/viewvc/qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageImplTest.java?rev=1562905&r1=1562904&r2=1562905&view=diff
==============================================================================
--- qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageImplTest.java (original)
+++ qpid/jms/trunk/src/test/java/org/apache/qpid/jms/impl/MessageImplTest.java Thu Jan 30 17:37:41 2014
@@ -58,6 +58,7 @@ public class MessageImplTest extends Qpi
         _mockConnectionImpl = Mockito.mock(ConnectionImpl.class);
         _mockSessionImpl = Mockito.mock(SessionImpl.class);
         Mockito.when(_mockSessionImpl.getDestinationHelper()).thenReturn(new DestinationHelper());
+        Mockito.when(_mockSessionImpl.getMessageIdHelper()).thenReturn(new MessageIdHelper());
 
         _testAmqpMessage = new TestAmqpMessage();
         _testMessage = new TestMessageImpl(_testAmqpMessage, _mockSessionImpl, _mockConnectionImpl);
@@ -899,6 +900,130 @@ public class MessageImplTest extends Qpi
         assertEquals("expected JMSPriority value to be capped at 9", 9, _testMessage.getJMSPriority());
     }
 
+    //TODO: remove this marker comment
+    // ====== JMSMessageID =======
+
+    @Test
+    public void testGetJMSMessageIDOnNewMessage() throws Exception
+    {
+        //Should be null as it has not been set explicitly, and
+        //the message has not been sent anywhere
+        assertNull(_testMessage.getJMSMessageID());
+    }
+
+    /**
+     * Test that {@link MessageImpl#setJMSMessageID(String)} accepts null and clears an existing value
+     */
+    @Test
+    public void testSetJMSMessageIDAcceptsNull() throws Exception
+    {
+        //test setting null on fresh message is accepted
+        _testMessage.setJMSMessageID(null);
+        assertNull("JMSMessageID should still be null", _testMessage.getJMSMessageID());
+
+        //test that setting null clears an existing value
+        _testMessage.setJMSMessageID("ID:something");
+        assertNotNull("JMSMessageID should not be null anymore", _testMessage.getJMSMessageID());
+        assertNotNull("Underlying message id should not be null anymore", _testAmqpMessage.getMessageId());
+
+        _testMessage.setJMSMessageID(null);
+        assertNull("JMSMessageID should be null again", _testMessage.getJMSMessageID());
+        assertNull("Underlying message id should be null again", _testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that {@link MessageImpl#setJMSMessageID(String)} throws JMSException when
+     * the provided non-null value doesn't begin with "ID:".
+     */
+    @Test
+    public void testSetJMSMessageIDOnNewMessageThrowsExceptionForNonIdValues() throws Exception
+    {
+        try
+        {
+            //"ID:" is present, but in the middle instead of required prefix
+            _testMessage.setJMSMessageID("Central:ID:Included");
+            fail("Expected exception when setting non-null value without the required JMSMessageID 'ID:' prefix");
+        }
+        catch(JMSException jmse)
+        {
+            //expected
+        }
+
+        try
+        {
+            //"ID:" isn't present at all.
+            _testMessage.setJMSMessageID("MissingEntirely");
+            fail("Expected exception when setting non-null value without the required JMSMessageID 'ID:' prefix");
+        }
+        catch(JMSException jmse)
+        {
+            //expected
+        }
+
+        try
+        {
+            //Prefix exists, but with the wrong case (it must be "ID:").
+            _testMessage.setJMSMessageID("id:WrongCase");
+            fail("Expected exception when setting non-null value without the required JMSMessageID 'ID:' prefix");
+        }
+        catch(JMSException jmse)
+        {
+            //expected
+        }
+    }
+
+    /**
+     * Test that {@link MessageImpl#setJMSMessageID(String)} sets the expected value
+     * on the underlying message, i.e the JMS message ID minus the "ID:" prefix.
+     */
+    @Test
+    public void testSetJMSMessageIDSetsUnderlyingMessageWithString() throws Exception
+    {
+        String baseId = "something";
+        String jmsId = "ID:" + baseId;
+
+        _testMessage.setJMSMessageID(jmsId);
+
+        assertNotNull("Underlying message id should not be null", _testAmqpMessage.getMessageId());
+        assertEquals("Underlying message id value was not as expected", baseId, _testAmqpMessage.getMessageId());
+    }
+
+    /**
+     * Test that receiving a message with a string typed message-id value results in the
+     * expected JMSMessageID value being returned, i.e. the base string plus the JMS "ID:" prefix.
+     */
+    @Test
+    public void testGetJMSMessageIdOnRecievedMessageWithString() throws Exception
+    {
+        getJMSMessageIdOnRecievedMessageWithStringTestImpl(false);
+    }
+
+    /**
+     * Test that receiving a message with a string typed message-id value results in the
+     * expected JMSMessageID value being returned, i.e. the base string plus the JMS "ID:" prefix.
+     */
+    @Test
+    public void testGetJMSMessageIdOnRecievedMessageWithStringAlreadyContainingPrefix() throws Exception
+    {
+        getJMSMessageIdOnRecievedMessageWithStringTestImpl(true);
+    }
+
+    private void getJMSMessageIdOnRecievedMessageWithStringTestImpl(boolean prefixAlreadyExists) throws JMSException
+    {
+        String baseId = "something";
+        if(prefixAlreadyExists)
+        {
+            baseId = "ID:" + baseId;
+        }
+
+        String expectedJmsMessageId = "ID:" + baseId;
+
+        _testAmqpMessage.setMessageId(baseId);
+        _testMessage = new TestMessageImpl(_testAmqpMessage, _mockSessionImpl, _mockConnectionImpl, null);
+
+        assertEquals("expected JMSMessageID value not present", expectedJmsMessageId, _testMessage.getJMSMessageID());
+    }
+
     // ====== JMS_AMQP_TTL property =======
 
     @Test



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org