From 19aebe19ca3ab98f2b23feff7f3b4de82ea169e0 Mon Sep 17 00:00:00 2001 From: David Voit Date: Mon, 13 Apr 2026 19:57:02 +0200 Subject: [PATCH] Also support non-byte type-annotations NMS AMQP is using "byte" which are unsigned in dotnet. Yes, this is non-std compatible, but not handling these values is also non-std compatible. It's a MUST to sent data as signed byte. But it's also a MUST to read other numeric values in the type-annotations fields in the binding spec. --- .../amqp/message/AmqpDestinationHelper.java | 6 ++-- .../message/AmqpDestinationHelperTest.java | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelper.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelper.java index 3f6dc2cc9..7e904c4fb 100644 --- a/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelper.java +++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelper.java @@ -277,9 +277,9 @@ static byte getTypeByte(AmqpJmsMessageFacade message, Symbol annotationName) { if (typeAnnotation == null) { // Doesn't exist, or null. return UNKNOWN_TYPE; - } else if (typeAnnotation instanceof Byte) { - // Return the value found. - return (Byte) typeAnnotation; + } else if (typeAnnotation instanceof Number) { + // Return the found value as a byte. + return ((Number)typeAnnotation).byteValue(); } else { // Handle legacy strings. String typeString = String.valueOf(typeAnnotation); diff --git a/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelperTest.java b/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelperTest.java index 1534eb4ef..066dae9f2 100644 --- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelperTest.java +++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/provider/amqp/message/AmqpDestinationHelperTest.java @@ -44,6 +44,7 @@ import org.apache.qpid.jms.JmsTemporaryTopic; import org.apache.qpid.jms.JmsTopic; import org.apache.qpid.jms.provider.amqp.AmqpConnection; +import org.apache.qpid.proton.amqp.UnsignedByte; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -688,6 +689,34 @@ public void testGetJmsReplToWithLegacyTempTopicTypeAnnotationNoConsumerDestinati assertEquals(testAddress, destination.getAddress()); } + @Test + public void doGetJmsReplToWithTempQueueUnsignedByteTypeAnnotationTestImpl() throws Exception { + String testAddress = "testAddress"; + AmqpJmsMessageFacade message = Mockito.mock(AmqpJmsMessageFacade.class); + Mockito.when(message.getReplyToAddress()).thenReturn(testAddress); + Mockito.when(message.getMessageAnnotation(JMS_REPLY_TO_TYPE_MSG_ANNOTATION_SYMBOL)).thenReturn(UnsignedByte.valueOf(TEMP_QUEUE_TYPE)); + + JmsDestination destination = AmqpDestinationHelper.getJmsReplyTo(message, null); + assertNotNull(destination); + assertTrue(destination.isQueue()); + assertTrue(destination.isTemporary()); + assertEquals(testAddress, destination.getAddress()); + } + + @Test + public void doGetJmsReplToWithTempQueueLongTypeAnnotationTestImpl() throws Exception { + String testAddress = "testAddress"; + AmqpJmsMessageFacade message = Mockito.mock(AmqpJmsMessageFacade.class); + Mockito.when(message.getReplyToAddress()).thenReturn(testAddress); + Mockito.when(message.getMessageAnnotation(JMS_REPLY_TO_TYPE_MSG_ANNOTATION_SYMBOL)).thenReturn((long) TEMP_QUEUE_TYPE); + + JmsDestination destination = AmqpDestinationHelper.getJmsReplyTo(message, null); + assertNotNull(destination); + assertTrue(destination.isQueue()); + assertTrue(destination.isTemporary()); + assertEquals(testAddress, destination.getAddress()); + } + //========================================================================// //--------------- Test setToAddressFromDestination method ----------------// //========================================================================//