fix for: https://issues.apache.org/activemq/browse/AMQNET-271
diff --git a/src/main/csharp/IConnection.cs b/src/main/csharp/IConnection.cs
index 217f87e..0377083 100644
--- a/src/main/csharp/IConnection.cs
+++ b/src/main/csharp/IConnection.cs
@@ -83,7 +83,7 @@
/// clients that the Connection that was interrupted has now been restored.
/// </summary>
public delegate void ConnectionResumedListener();
-
+
/// <summary>
/// Represents a connection with a message broker
/// </summary>
@@ -120,6 +120,30 @@
/// has been resumed.
/// </summary>
event ConnectionResumedListener ConnectionResumedListener;
+
+ /// <summary>
+ /// A Delegate that is called each time a Message is dispatched to allow the client to do
+ /// any necessary transformations on the received message before it is delivered. The
+ /// Connection sets the provided delegate instance on each Session it creates which then
+ /// passes that along to the Consumers it creates.
+ /// </summary>
+ ConsumerTransformerDelegate ConsumerTransformer
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// A delegate that is called each time a Message is sent from this Producer which allows
+ /// the application to perform any needed transformations on the Message before it is sent.
+ /// The Connection sets the provided delegate instance on each Session it creates which then
+ /// passes that along to the Producer it creates.
+ /// </summary>
+ ProducerTransformerDelegate ProducerTransformer
+ {
+ get;
+ set;
+ }
#region Attributes
diff --git a/src/main/csharp/IConnectionFactory.cs b/src/main/csharp/IConnectionFactory.cs
index 18529b0..c2956d5 100644
--- a/src/main/csharp/IConnectionFactory.cs
+++ b/src/main/csharp/IConnectionFactory.cs
@@ -44,5 +44,31 @@
/// assigned upon creation.
/// </summary>
IRedeliveryPolicy RedeliveryPolicy{ get; set; }
+
+ /// <summary>
+ /// A Delegate that is called each time a Message is dispatched to allow the client to do
+ /// any necessary transformations on the received message before it is delivered. The
+ /// ConnectionFactory sets the provided delegate instance on each Connection instance that
+ /// is created from this factory, each connection in turn passes the delegate along to each
+ /// Session it creates which then passes that along to the Consumers it creates.
+ /// </summary>
+ ConsumerTransformerDelegate ConsumerTransformer
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// A delegate that is called each time a Message is sent from this Producer which allows
+ /// the application to perform any needed transformations on the Message before it is sent.
+ /// The ConnectionFactory sets the provided delegate instance on each Connection instance that
+ /// is created from this factory, each connection in turn passes the delegate along to each
+ /// Session it creates which then passes that along to the Producers it creates.
+ /// </summary>
+ ProducerTransformerDelegate ProducerTransformer
+ {
+ get;
+ set;
+ }
}
}
diff --git a/src/main/csharp/IMessageConsumer.cs b/src/main/csharp/IMessageConsumer.cs
index 060281c..4ad781d 100644
--- a/src/main/csharp/IMessageConsumer.cs
+++ b/src/main/csharp/IMessageConsumer.cs
@@ -21,12 +21,22 @@
/// </summary>
public delegate void MessageListener(IMessage message);
+ /// <summary>
+ /// A delegate that a client can register that will be called each time a consumer dispatches a message
+ /// to the client code to allow the client to Transform a received message from one type to another,
+ /// StreamMessage to TextMessage, ObjectMessage to TextMessage containing XML, etc. This allows a
+ /// client to create a consumer that will automatically transform a message to a type that the client is
+ /// capable of processing or adding additional information to a received message. For messages that do
+ /// not need to be processed the client should return null from this method, in this case the original
+ /// message will be dispatched to the client.
+ /// </summary>
+ public delegate IMessage ConsumerTransformerDelegate(ISession session, IMessageConsumer consumer, IMessage message);
+
/// <summary>
/// A consumer of messages
/// </summary>
public interface IMessageConsumer : System.IDisposable
{
-
/// <summary>
/// Waits until a message is available and returns it
/// </summary>
@@ -56,7 +66,18 @@
/// A blocked message consumer receive call returns null when this message consumer is closed.
/// </remarks>
void Close();
- }
+
+ /// <summary>
+ /// A Delegate that is called each time a Message is dispatched to allow the client to do
+ /// any necessary transformations on the received message before it is delivered.
+ /// </summary>
+ ConsumerTransformerDelegate ConsumerTransformer
+ {
+ get;
+ set;
+ }
+
+ }
}
diff --git a/src/main/csharp/IMessageProducer.cs b/src/main/csharp/IMessageProducer.cs
index a4341e9..b009f39 100644
--- a/src/main/csharp/IMessageProducer.cs
+++ b/src/main/csharp/IMessageProducer.cs
@@ -18,6 +18,17 @@
namespace Apache.NMS
{
+ /// <summary>
+ /// A delegate that a client can register that will be called each time a Producer's send method is
+ /// called to allow the client to Transform a sent message from one type to another, StreamMessage to
+ /// TextMessage, ObjectMessage to TextMessage containing XML, etc. This allows a client to create a
+ /// producer that will automatically transform a message to a type that some receiving client is
+ /// capable of processing or adding additional information to a sent message such as additional message
+ /// headers, etc. For messages that do not need to be processed the client should return null from
+ /// this method, in this case the original message will be sent.
+ /// </summary>
+ public delegate IMessage ProducerTransformerDelegate(ISession session, IMessageProducer producer, IMessage message);
+
/// <summary>
/// An object capable of sending messages to some destination
/// </summary>
@@ -48,6 +59,16 @@
/// </summary>
void Close();
+ /// <summary>
+ /// A delegate that is called each time a Message is sent from this Producer which allows
+ /// the application to perform any needed transformations on the Message before it is sent.
+ /// </summary>
+ ProducerTransformerDelegate ProducerTransformer
+ {
+ get;
+ set;
+ }
+
MsgDeliveryMode DeliveryMode { get; set; }
TimeSpan TimeToLive { get; set; }
diff --git a/src/main/csharp/ISession.cs b/src/main/csharp/ISession.cs
index ad430be..b12f4dc 100644
--- a/src/main/csharp/ISession.cs
+++ b/src/main/csharp/ISession.cs
@@ -23,7 +23,7 @@
/// So the ISession can be used to perform transactional receive and sends
/// </summary>
public interface ISession : IDisposable
- {
+ {
/// <summary>
/// Creates a producer of messages
/// </summary>
@@ -165,6 +165,28 @@
/// </summary>
void Close();
+ /// <summary>
+ /// A Delegate that is called each time a Message is dispatched to allow the client to do
+ /// any necessary transformations on the received message before it is delivered.
+ /// The Session instance sets the delegate on each Consumer it creates.
+ /// </summary>
+ ConsumerTransformerDelegate ConsumerTransformer
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// A delegate that is called each time a Message is sent from this Producer which allows
+ /// the application to perform any needed transformations on the Message before it is sent.
+ /// The Session instance sets the delegate on each Producer it creates.
+ /// </summary>
+ ProducerTransformerDelegate ProducerTransformer
+ {
+ get;
+ set;
+ }
+
#region Transaction methods
/// <summary>
diff --git a/src/main/csharp/NMSConnectionFactory.cs b/src/main/csharp/NMSConnectionFactory.cs
index ee51a8e..402fc58 100644
--- a/src/main/csharp/NMSConnectionFactory.cs
+++ b/src/main/csharp/NMSConnectionFactory.cs
@@ -397,5 +397,24 @@
set { this.factory.RedeliveryPolicy = value; }
}
+ /// <summary>
+ /// Get/or Set the ConsumerTransformerDelegate using the IConnectionFactory implementation
+ /// that is currently being used.
+ /// </summary>
+ public ConsumerTransformerDelegate ConsumerTransformer
+ {
+ get { return this.factory.ConsumerTransformer; }
+ set { this.factory.ConsumerTransformer = value; }
+ }
+
+ /// <summary>
+ /// Get/or Set the ProducerTransformerDelegate using the IConnectionFactory implementation
+ /// that is currently being used.
+ /// </summary>
+ public ProducerTransformerDelegate ProducerTransformer
+ {
+ get { return this.factory.ProducerTransformer; }
+ set { this.factory.ProducerTransformer = value; }
+ }
}
}
diff --git a/src/main/csharp/Util/MessageTransformation.cs b/src/main/csharp/Util/MessageTransformation.cs
index 1141367..cee5da4 100644
--- a/src/main/csharp/Util/MessageTransformation.cs
+++ b/src/main/csharp/Util/MessageTransformation.cs
@@ -122,14 +122,11 @@
}
}
- /**
- * Copies the standard JMS and user defined properties from the givem
- * message to the specified message
- *
- * @param fromMessage the message to take the properties from
- * @param toMessage the message to add the properties to
- * @throws JMSException
- */
+ /// <summary>
+ /// Copies the standard NMS and user defined properties from the givem
+ /// message to the specified message, the class version transforms the
+ /// Destination instead of just doing a straight copy.
+ /// </summary>
public virtual void CopyProperties(IMessage fromMessage, IMessage toMessage)
{
toMessage.NMSMessageId = fromMessage.NMSMessageId;
@@ -149,6 +146,30 @@
}
}
+ /// <summary>
+ /// Copies the standard NMS and user defined properties from the givem
+ /// message to the specified message, this method makes no attempt to convert
+ /// the values in the Message to native provider implementations.
+ /// </summary>
+ public static void CopyNMSMessageProperties(IMessage fromMessage, IMessage toMessage)
+ {
+ toMessage.NMSMessageId = fromMessage.NMSMessageId;
+ toMessage.NMSCorrelationID = fromMessage.NMSCorrelationID;
+ toMessage.NMSReplyTo = fromMessage.NMSReplyTo;
+ toMessage.NMSDestination = fromMessage.NMSDestination;
+ toMessage.NMSDeliveryMode = fromMessage.NMSDeliveryMode;
+ toMessage.NMSRedelivered = fromMessage.NMSRedelivered;
+ toMessage.NMSType = fromMessage.NMSType;
+ toMessage.NMSPriority = fromMessage.NMSPriority;
+ toMessage.NMSTimestamp = fromMessage.NMSTimestamp;
+ toMessage.NMSTimeToLive = fromMessage.NMSTimeToLive;
+
+ foreach(string key in fromMessage.Properties.Keys)
+ {
+ toMessage.Properties[key] = fromMessage.Properties[key];
+ }
+ }
+
#region Creation Methods and Conversion Support Methods
protected abstract IMessage DoCreateMessage();
diff --git a/src/test/csharp/MessageTransformerTest.cs b/src/test/csharp/MessageTransformerTest.cs
new file mode 100644
index 0000000..992fdc3
--- /dev/null
+++ b/src/test/csharp/MessageTransformerTest.cs
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+using System;
+
+using Apache.NMS.Util;
+
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+ [TestFixture]
+ public class MessageTransformerTest : NMSTestSupport
+ {
+ private string propertyName = "ADDITIONAL-PROPERTY";
+ private string propertyValue = "ADDITIONAL-PROPERTY-VALUE";
+
+ [Test]
+ public void TestProducerTransformer(
+ [Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+ MsgDeliveryMode deliveryMode)
+ {
+ using(IConnection connection = CreateConnection())
+ {
+ connection.Start();
+ using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+ {
+ IDestination destination = session.CreateTemporaryTopic();
+ using(IMessageConsumer consumer = session.CreateConsumer(destination))
+ using(IMessageProducer producer = session.CreateProducer(destination))
+ {
+ producer.DeliveryMode = deliveryMode;
+ producer.ProducerTransformer = DoProducerTransform;
+
+ IMessage message = session.CreateMessage();
+
+ message.Properties["Test"] = "Value";
+
+ producer.Send(message);
+
+ message = consumer.Receive(TimeSpan.FromMilliseconds(5000));
+
+ Assert.IsNotNull(message);
+ Assert.IsTrue(message.Properties.Count == 2);
+
+ Assert.AreEqual("Value", message.Properties["Test"]);
+ Assert.AreEqual(propertyValue, message.Properties[propertyName]);
+ }
+ }
+ }
+ }
+
+ [Test]
+ public void TestConsumerTransformer(
+ [Values(MsgDeliveryMode.Persistent, MsgDeliveryMode.NonPersistent)]
+ MsgDeliveryMode deliveryMode)
+ {
+ using(IConnection connection = CreateConnection())
+ {
+ connection.Start();
+ using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+ {
+ IDestination destination = session.CreateTemporaryTopic();
+ using(IMessageConsumer consumer = session.CreateConsumer(destination))
+ using(IMessageProducer producer = session.CreateProducer(destination))
+ {
+ producer.DeliveryMode = deliveryMode;
+
+ consumer.ConsumerTransformer = DoConsumerTransform;
+
+ IMessage message = session.CreateMessage();
+
+ message.Properties["Test"] = "Value";
+
+ producer.Send(message);
+
+ message = consumer.Receive(TimeSpan.FromMilliseconds(5000));
+
+ Assert.IsNotNull(message);
+ Assert.IsTrue(message.Properties.Count == 2, "Property Count should be 2");
+
+ Assert.AreEqual("Value", message.Properties["Test"], "Propert 'Value' was incorrect");
+ Assert.AreEqual(propertyValue, message.Properties[propertyName], "Property not inserted");
+ }
+ }
+ }
+ }
+
+ private IMessage DoProducerTransform(ISession session, IMessageProducer producer, IMessage message)
+ {
+ message.Properties[propertyName] = propertyValue;
+
+ return message;
+ }
+
+ private IMessage DoConsumerTransform(ISession session, IMessageConsumer consumer, IMessage message)
+ {
+ IMessage newMessage = session.CreateMessage();
+
+ MessageTransformation.CopyNMSMessageProperties(message, newMessage);
+
+ newMessage.Properties[propertyName] = propertyValue;
+
+ return newMessage;
+ }
+ }
+}
+