diff --git a/sdk/core/Azure.Core.Experimental/src/Amqp/AmqpAnnotatedMessage.cs b/sdk/core/Azure.Core.Experimental/src/Amqp/AmqpAnnotatedMessage.cs index a0f2d4e54e18..d38b19e6d012 100644 --- a/sdk/core/Azure.Core.Experimental/src/Amqp/AmqpAnnotatedMessage.cs +++ b/sdk/core/Azure.Core.Experimental/src/Amqp/AmqpAnnotatedMessage.cs @@ -17,7 +17,8 @@ public class AmqpAnnotatedMessage /// The message to copy. public AmqpAnnotatedMessage(AmqpAnnotatedMessage message) { - Body = message.Body; + var data = message.Body as AmqpDataBody; + Body = new AmqpDataBody(data!.Data); ApplicationProperties = new Dictionary(message.ApplicationProperties); Properties = new AmqpMessageProperties(message.Properties); MessageAnnotations = new Dictionary(message.MessageAnnotations); diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpMessageConstants.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpMessageConstants.cs index f020cdde37dd..b03f54c76c86 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpMessageConstants.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpMessageConstants.cs @@ -23,5 +23,18 @@ internal class AmqpMessageConstants internal const string TimeSpanName = AmqpConstants.Vendor + ":timespan"; internal const string UriName = AmqpConstants.Vendor + ":uri"; internal const string DateTimeOffsetName = AmqpConstants.Vendor + ":datetime-offset"; + /// + /// Property key representing deadletter reason, when a message is received from a deadletter subqueue of an entity. + /// This key and the associated values are stored in the dictionary + /// for dead lettered messages. + /// + internal const string DeadLetterReasonHeader = "DeadLetterReason"; + + /// + /// Property key representing detailed error description, when a message is received from a deadletter subqueue of an entity. + /// This key and the associated values are stored in the dictionary + /// for dead lettered messages. + /// + internal const string DeadLetterErrorDescriptionHeader = "DeadLetterErrorDescription"; } } diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpReceiver.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpReceiver.cs index a582bfb94551..c9f30ce449d6 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpReceiver.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Amqp/AmqpReceiver.cs @@ -654,12 +654,12 @@ private Rejected GetRejectedOutcome( rejected = new Rejected { Error = new Error { Condition = AmqpClientConstants.DeadLetterName, Info = new Fields() } }; if (deadLetterReason != null) { - rejected.Error.Info.Add(ServiceBusReceivedMessage.DeadLetterReasonHeader, deadLetterReason); + rejected.Error.Info.Add(AmqpMessageConstants.DeadLetterReasonHeader, deadLetterReason); } if (deadLetterErrorDescription != null) { - rejected.Error.Info.Add(ServiceBusReceivedMessage.DeadLetterErrorDescriptionHeader, deadLetterErrorDescription); + rejected.Error.Info.Add(AmqpMessageConstants.DeadLetterErrorDescriptionHeader, deadLetterErrorDescription); } if (propertiesToModify != null) diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusMessage.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusMessage.cs index 95b84bd675bf..8ad6e6db8ae0 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusMessage.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusMessage.cs @@ -63,6 +63,14 @@ public ServiceBusMessage(ServiceBusReceivedMessage receivedMessage) { Argument.AssertNotNull(receivedMessage, nameof(receivedMessage)); AmqpMessage = new AmqpAnnotatedMessage(receivedMessage.AmqpMessage); + AmqpMessage.Header.DeliveryCount = null; + AmqpMessage.MessageAnnotations.Remove(AmqpMessageConstants.LockedUntilName); + AmqpMessage.MessageAnnotations.Remove(AmqpMessageConstants.SequenceNumberName); + AmqpMessage.MessageAnnotations.Remove(AmqpMessageConstants.DeadLetterSourceName); + AmqpMessage.MessageAnnotations.Remove(AmqpMessageConstants.EnqueueSequenceNumberName); + AmqpMessage.MessageAnnotations.Remove(AmqpMessageConstants.EnqueuedTimeUtcName); + ApplicationProperties.Remove(AmqpMessageConstants.DeadLetterReasonHeader); + ApplicationProperties.Remove(AmqpMessageConstants.DeadLetterErrorDescriptionHeader); } /// diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusReceivedMessage.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusReceivedMessage.cs index 6067a8d0cccb..71c61fc8bf84 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusReceivedMessage.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/src/Primitives/ServiceBusReceivedMessage.cs @@ -197,16 +197,6 @@ public BinaryData Body /// public IReadOnlyDictionary ApplicationProperties => new ReadOnlyDictionary(AmqpMessage.ApplicationProperties); - /// - /// User property key representing deadletter reason, when a message is received from a deadletter subqueue of an entity. - /// - internal const string DeadLetterReasonHeader = "DeadLetterReason"; - - /// - /// User property key representing detailed error description, when a message is received from a deadletter subqueue of an entity. - /// - internal const string DeadLetterErrorDescriptionHeader = "DeadLetterErrorDescription"; - /// /// Gets the lock token for the current message. /// @@ -396,7 +386,7 @@ public string DeadLetterReason { get { - if (ApplicationProperties.TryGetValue(DeadLetterReasonHeader, out object reason)) + if (ApplicationProperties.TryGetValue(AmqpMessageConstants.DeadLetterReasonHeader, out object reason)) { return reason as string; } @@ -411,7 +401,7 @@ public string DeadLetterErrorDescription { get { - if (ApplicationProperties.TryGetValue(DeadLetterErrorDescriptionHeader, out object description)) + if (ApplicationProperties.TryGetValue(AmqpMessageConstants.DeadLetterErrorDescriptionHeader, out object description)) { return description as string; } diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Message/MessageLiveTests.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Message/MessageLiveTests.cs index 78bb5cc82cfc..611d29a6dcfa 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Message/MessageLiveTests.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Message/MessageLiveTests.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Azure.Core.Amqp; using Azure.Core.Serialization; +using Azure.Messaging.ServiceBus.Amqp; using NUnit.Framework; namespace Azure.Messaging.ServiceBus.Tests.Message @@ -121,6 +122,18 @@ public async Task CreateFromReceivedMessageCopiesProperties() var received = await receiver.ReceiveMessageAsync(); AssertMessagesEqual(msg, received); var toSend = new ServiceBusMessage(received); + + // verify that all system set properties have been cleared out + Assert.IsNull(toSend.AmqpMessage.Header.DeliveryCount); + Assert.IsFalse(toSend.AmqpMessage.MessageAnnotations.ContainsKey(AmqpMessageConstants.LockedUntilName)); + Assert.IsFalse(toSend.AmqpMessage.MessageAnnotations.ContainsKey(AmqpMessageConstants.SequenceNumberName)); + Assert.IsFalse(toSend.AmqpMessage.MessageAnnotations.ContainsKey(AmqpMessageConstants.DeadLetterSourceName)); + Assert.IsFalse(toSend.AmqpMessage.MessageAnnotations.ContainsKey(AmqpMessageConstants.EnqueueSequenceNumberName)); + Assert.IsFalse(toSend.AmqpMessage.MessageAnnotations.ContainsKey(AmqpMessageConstants.EnqueuedTimeUtcName)); + Assert.IsFalse(toSend.AmqpMessage.MessageAnnotations.ContainsKey(AmqpMessageConstants.DeadLetterSourceName)); + Assert.IsFalse(toSend.ApplicationProperties.ContainsKey(AmqpMessageConstants.DeadLetterReasonHeader)); + Assert.IsFalse(toSend.ApplicationProperties.ContainsKey(AmqpMessageConstants.DeadLetterErrorDescriptionHeader)); + AssertMessagesEqual(toSend, received); void AssertMessagesEqual(ServiceBusMessage sentMessage, ServiceBusReceivedMessage received) diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Plugins/PluginTests.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Plugins/PluginTests.cs index dd63f46adbb3..1c7f87178c45 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Plugins/PluginTests.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Plugins/PluginTests.cs @@ -4,6 +4,7 @@ using System; using System.Threading.Tasks; using Azure.Core; +using Azure.Messaging.ServiceBus.Amqp; using Azure.Messaging.ServiceBus.Plugins; using Moq; using NUnit.Framework; @@ -44,8 +45,8 @@ public override ValueTask AfterMessageReceiveAsync(ServiceBusReceivedMessage mes SetContentType(message, "contentType"); SetCorrelationId(message, "correlationId"); SetUserProperty(message, "propertyKey", "propertyValue"); - SetUserProperty(message, ServiceBusReceivedMessage.DeadLetterErrorDescriptionHeader, "deadLetterDescription"); - SetUserProperty(message, ServiceBusReceivedMessage.DeadLetterReasonHeader, "deadLetterReason"); + SetUserProperty(message, AmqpMessageConstants.DeadLetterErrorDescriptionHeader, "deadLetterDescription"); + SetUserProperty(message, AmqpMessageConstants.DeadLetterReasonHeader, "deadLetterReason"); SetLabel(message, "label"); SetMessageId(message, "messageId"); SetPartitionKey(message, "partitionKey"); diff --git a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/SessionReceiverLiveTests.cs b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/SessionReceiverLiveTests.cs index e345e2e21057..8b7343709c50 100644 --- a/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/SessionReceiverLiveTests.cs +++ b/sdk/servicebus/Azure.Messaging.ServiceBus/tests/Receiver/SessionReceiverLiveTests.cs @@ -7,6 +7,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Azure.Messaging.ServiceBus.Amqp; using NUnit.Framework; using NUnit.Framework.Internal; @@ -486,8 +487,8 @@ public async Task DeadLetterMessagesSubscription(bool useSpecificSession) Assert.AreEqual(messageEnum.Current.SessionId, item.SessionId); var props = new Dictionary(); // these should be ignored by DeadLetter property getters as they are not strings - props[ServiceBusReceivedMessage.DeadLetterReasonHeader] = DateTime.UtcNow; - props[ServiceBusReceivedMessage.DeadLetterErrorDescriptionHeader] = DateTime.UtcNow; + props[AmqpMessageConstants.DeadLetterReasonHeader] = DateTime.UtcNow; + props[AmqpMessageConstants.DeadLetterErrorDescriptionHeader] = DateTime.UtcNow; await receiver.DeadLetterMessageAsync(item.LockToken, props); } @@ -514,8 +515,8 @@ public async Task DeadLetterMessagesSubscription(bool useSpecificSession) Assert.AreEqual(messageEnum.Current.SessionId, msg.SessionId); Assert.IsNull(msg.DeadLetterErrorDescription); Assert.IsNull(msg.DeadLetterReason); - Assert.IsNotNull(msg.ApplicationProperties[ServiceBusReceivedMessage.DeadLetterReasonHeader]); - Assert.IsNotNull(msg.ApplicationProperties[ServiceBusReceivedMessage.DeadLetterErrorDescriptionHeader]); + Assert.IsNotNull(msg.ApplicationProperties[AmqpMessageConstants.DeadLetterReasonHeader]); + Assert.IsNotNull(msg.ApplicationProperties[AmqpMessageConstants.DeadLetterErrorDescriptionHeader]); await deadLetterReceiver.CompleteMessageAsync(msg.LockToken); } }