diff --git a/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs b/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs index 329ad34b..c3e82f7d 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/DefaultMessageQueueFactory.cs @@ -47,6 +47,12 @@ namespace Spring.Messaging.Core #region IMessageQueueFactory Members + /// + /// Registers the message queue, its creation specified via the factory method + /// MessageQueueCreatorDelegate, with the provided name in the application context + /// + /// Name of the message queue object. + /// The message queue creator delegate. public void RegisterMessageQueue(string messageQueueObjectName, MessageQueueCreatorDelegate messageQueueCreatorDelegate) { @@ -55,6 +61,13 @@ namespace Spring.Messaging.Core applicationContext.ObjectFactory.RegisterSingleton(messageQueueObjectName, mqfo); } + /// + /// Creates the message queue given its name in the application context. + /// + /// Name of the message queue object. + /// + /// A MessageQueue instance configured via the application context + /// public MessageQueue CreateMessageQueue(string messageQueueObjectName) { AssertUtils.ArgumentHasText(messageQueueObjectName, "DefaultMessageQueueObjectName"); @@ -72,11 +85,23 @@ namespace Spring.Messaging.Core return queues[messageQueueObjectName] as MessageQueue; } + /// + /// Determines whether the application context contains the message queue object definition. + /// + /// Name of the message queue object. + /// + /// true if the application context contains the specified message queue object name; otherwise, false. + /// public bool ContainsMessageQueue(string messageQueueObjectName) { return applicationContext.ContainsObject(messageQueueObjectName); } + /// + /// Registers the message converter. + /// + /// Name of the message converter. + /// The message converter creator delegate. public void RegisterMessageConverter(string messageConverterName, MessageConverterCreatorDelegate messageConverterCreatorDelegate) { @@ -85,6 +110,13 @@ namespace Spring.Messaging.Core applicationContext.ObjectFactory.RegisterSingleton(messageConverterName, mcfo); } + /// + /// Creates the message converter given its name in the application context. + /// + /// Name of the message converter object. + /// + /// A IMessageConverter instance configured via the application context + /// public IMessageConverter CreateMessageConverter(string messageConverterObjectName) { AssertUtils.ArgumentHasText(messageConverterObjectName, "MessgaeFormatterObjectName"); @@ -103,6 +135,13 @@ namespace Spring.Messaging.Core } + /// + /// Determines whether the application context contains the message queue object definition. + /// + /// Name of the message converter object. + /// + /// true if the application context contains the specified message message converter object name; otherwise, false. + /// public bool ContainsMessageConverter(string messageConverterObjectName) { return applicationContext.ContainsObject(messageConverterObjectName); diff --git a/src/Spring/Spring.Messaging/Messaging/Core/IMessageQueueFactory.cs b/src/Spring/Spring.Messaging/Messaging/Core/IMessageQueueFactory.cs index 6292b81b..c43ba6a5 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/IMessageQueueFactory.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/IMessageQueueFactory.cs @@ -37,21 +37,57 @@ namespace Spring.Messaging.Core /// Mark Pollack public interface IMessageQueueFactory { + /// + /// Registers the message queue, its creation specified via the factory method + /// MessageQueueCreatorDelegate, with the provided name in the application context + /// + /// Name of the message queue object. + /// The message queue creator delegate. void RegisterMessageQueue(string messageQueueObjectName, MessageQueueCreatorDelegate messageQueueCreatorDelegate); + /// + /// Creates the message queue given its name in the application context. + /// + /// Name of the message queue object. + /// A MessageQueue instance configured via the application context MessageQueue CreateMessageQueue(string messageQueueObjectName); + /// + /// Determines whether the application context contains the message queue object definition. + /// + /// Name of the message queue object. + /// + /// true if the application context contains the specified message queue object name; otherwise, false. + /// bool ContainsMessageQueue(string messageQueueObjectName); - - - + + + + /// + /// Registers the message converter, its creation specified via the factory method + /// MessageConverterCreatorDelegate, with the provided name in the application context. + /// + /// Name of the message converter. + /// The message converter creator delegate. void RegisterMessageConverter(string messageConverterName, MessageConverterCreatorDelegate MessageConverterCreatorDelegate); + /// + /// Creates the message converter given its name in the application context. + /// + /// Name of the message converter object. + /// A IMessageConverter instance configured via the application context IMessageConverter CreateMessageConverter(string messageConverterObjectName); + /// + /// Determines whether the application context contains the message queue object definition. + /// + /// Name of the message converter object. + /// + /// true if the application context contains the specified message message converter object name; otherwise, false. + /// bool ContainsMessageConverter(string messageConverterObjectName); diff --git a/src/Spring/Spring.Messaging/Messaging/Core/LocallyExposedMessageQueueResourceHolder.cs b/src/Spring/Spring.Messaging/Messaging/Core/LocallyExposedMessageQueueResourceHolder.cs index 0a98539b..3660f2da 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/LocallyExposedMessageQueueResourceHolder.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/LocallyExposedMessageQueueResourceHolder.cs @@ -29,6 +29,10 @@ namespace Spring.Messaging.Core /// Mark Pollack public class LocallyExposedMessageQueueResourceHolder : MessageQueueResourceHolder { + /// + /// Initializes a new instance of the class. + /// + /// The message queue transaction. public LocallyExposedMessageQueueResourceHolder(MessageQueueTransaction messageQueueTransaction) : base(messageQueueTransaction) { diff --git a/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTemplate.cs b/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTemplate.cs index aa49c18c..c3fb88fa 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTemplate.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTemplate.cs @@ -269,24 +269,61 @@ namespace Spring.Messaging.Core #region IMessageQueueOperations Members + /// + /// Send the given object to the default destination, converting the object + /// to a MSMQ message with a configured IMessageConverter. + /// + /// The obj. + /// This will only work with a default destination queue specified! public void ConvertAndSend(object obj) { CheckDefaultMessageQueue(); ConvertAndSend(DefaultMessageQueueObjectName, obj); } + /// + /// Send the given object to the default destination, converting the object + /// to a MSMQ message with a configured IMessageConverter. The IMessagePostProcessor + /// callback allows for modification of the message after conversion. + ///

This will only work with a default destination specified!

+ ///
+ /// the object to convert to a message + /// the callback to modify the message + /// if thrown by MSMQ API methods public void ConvertAndSend(object obj, MessagePostProcessorDelegate messagePostProcessorDelegate) { CheckDefaultMessageQueue(); ConvertAndSend(DefaultMessageQueueObjectName, obj, messagePostProcessorDelegate); } + /// + /// Send the given object to the specified destination, converting the object + /// to a MSMQ message with a configured and resolving the + /// destination name to a using a + /// + /// the name of the destination queue + /// to send this message to (to be resolved to an actual MessageQueue + /// by a IMessageQueueFactory) + /// the object to convert to a message + /// NMSException if there is any problem public void ConvertAndSend(string messageQueueObjectName, object obj) { Message msg = MessageConverter.ToMessage(obj); Send(MessageQueueFactory.CreateMessageQueue(messageQueueObjectName), msg); } + /// + /// Send the given object to the specified destination, converting the object + /// to a MSMQ message with a configured and resolving the + /// destination name to a with an + /// The callback allows for modification of the message after conversion. + /// + /// the name of the destination queue + /// to send this message to (to be resolved to an actual MessageQueue + /// by a IMessageQueueFactory) + /// the object to convert to a message + /// the callback to modify the message + /// if thrown by MSMQ API methods public void ConvertAndSend(string messageQueueObjectName, object obj, MessagePostProcessorDelegate messagePostProcessorDelegate) { @@ -295,6 +332,13 @@ namespace Spring.Messaging.Core Send(MessageQueueFactory.CreateMessageQueue(messageQueueObjectName), msgToSend); } + /// + /// Receive and convert a message synchronously from the default message queue. + /// + /// The converted object + /// if thrown by MSMQ API methods. Note an + /// exception will be thrown if the timeout of the syncrhonous recieve operation expires. + /// public object ReceiveAndConvert() { MessageQueue mq = DefaultMessageQueue; @@ -302,6 +346,14 @@ namespace Spring.Messaging.Core return DoConvertMessage(m); } + /// + /// Receives and convert a message synchronously from the specified message queue. + /// + /// Name of the message queue object. + /// the converted object + /// if thrown by MSMQ API methods. Note an + /// exception will be thrown if the timeout of the syncrhonous recieve operation expires. + /// public object ReceiveAndConvert(string messageQueueObjectName) { MessageQueue mq = MessageQueueFactory.CreateMessageQueue(messageQueueObjectName); @@ -309,26 +361,64 @@ namespace Spring.Messaging.Core return DoConvertMessage(m); } + /// + /// Receives a message on the default message queue using the transactional settings as dicted by MessageQueue's Transactional property and + /// the current Spring managed ambient transaction. + /// + /// A message. public Message Receive() { return DefaultMessageQueue.Receive(ReceiveTimeout); } + /// + /// Receives a message on the specified queue using the transactional settings as dicted by MessageQueue's Transactional property and + /// the current Spring managed ambient transaction. + /// + /// Name of the message queue object. + /// public Message Receive(string messageQueueObjectName) { return MessageQueueFactory.CreateMessageQueue(messageQueueObjectName).Receive(ReceiveTimeout); } + /// + /// Sends the specified message to the default message queue using the + /// transactional settings as dicted by MessageQueue's Transactional property and + /// the current Spring managed ambient transaction. + /// + /// The message to send public void Send(Message message) { Send(DefaultMessageQueue, message); } + /// + /// Sends the specified message to the message queue using the + /// transactional settings as dicted by MessageQueue's Transactional property and + /// the current Spring managed ambient transaction. + /// + /// Name of the message queue object. + /// The message. public void Send(string messageQueueObjectName, Message message) { Send(MessageQueueFactory.CreateMessageQueue(messageQueueObjectName), message); } + /// + /// Sends the specified message on the provided MessageQueue using the + /// transactional settings as dicted by MessageQueue's Transactional property and + /// the current Spring managed ambient transaction. + /// + /// The DefaultMessageQueue to send a message to. + /// The message to send + /// + /// Note that it is the callers responsibility to ensure that the MessageQueue instance + /// passed into this not being access simultaneously by other threads. + /// + /// A transactional send (either local or DTC transaction) will be + /// attempted for a transacitonal queue, falling back to a single-transaction send + /// to a transactional queue if there is not ambient Spring managed transaction. public virtual void Send(MessageQueue messageQueue, Message message) { DoSend(messageQueue, message); @@ -338,6 +428,13 @@ namespace Spring.Messaging.Core #region Protected Methods + /// + /// Sends the message to the given message queue. + /// + /// If System.Transactions.Transaction.Current is null, then send based on + /// the transaction semantics of the queue definition. See + /// The message queue. + /// The message. protected virtual void DoSend(MessageQueue messageQueue, Message message) { if (System.Transactions.Transaction.Current == null) @@ -350,6 +447,34 @@ namespace Spring.Messaging.Core } } + /// + /// Send the message queue selecting the appropriate transactional delivery options. + /// + /// + /// + /// If the message queue is transactional and there is an ambient MessageQueueTransaction + /// in thread local storage (put there via the use of Spring's MessageQueueTransactionManager + /// or TransactionalMessageListenerContainer), the message will be sent transactionally using the + /// MessageQueueTransaction object in thread local storage. This lets you group together multiple + /// messaging operations within the same transaction without having to explicitly pass around the + /// MessageQueueTransaction object. + /// + /// + /// If the message queue is transactional but there is no ambient MessageQueueTransaction, + /// then a single message transaction is created on each messaging operation. + /// (MessageQueueTransactionType = Single). + /// + /// + /// If there is an ambient System.Transactions transaction then that transaction will + /// be used (MessageQueueTransactionType = Automatic). + /// + /// + /// If the queue is not transactional, then a non-transactional send + /// (MessageQueueTransactionType = None) is used. + /// + /// + /// The mq. + /// The MSG. protected virtual void DoSendMessageQueueTransactional(MessageQueue mq, Message msg) { MessageQueueTransaction transactionToUse = QueueUtils.GetMessageQueueTransaction(null); @@ -400,11 +525,21 @@ namespace Spring.Messaging.Core } + /// + /// Sends using MessageQueueTransactionType.Automatic transaction type + /// + /// The message queue. + /// The message. protected virtual void DoSendTxScope(MessageQueue mq, Message msg) { mq.Send(msg, MessageQueueTransactionType.Automatic); } + /// + /// Template method to convert the message if it is not null. + /// + /// The message. + /// The converted message ,or null if no message converter is set. protected virtual object DoConvertMessage(Message m) { if (m != null) @@ -417,6 +552,9 @@ namespace Spring.Messaging.Core } } + /// + /// Checks if the default message queue if defined. + /// protected virtual void CheckDefaultMessageQueue() { if (DefaultMessageQueueObjectName == null) diff --git a/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTransactionManager.cs b/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTransactionManager.cs index 9ecc8dc3..84ab8a99 100644 --- a/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTransactionManager.cs +++ b/src/Spring/Spring.Messaging/Messaging/Core/MessageQueueTransactionManager.cs @@ -48,6 +48,9 @@ namespace Spring.Messaging.Core /// Mark Pollack public class MessageQueueTransactionManager : AbstractPlatformTransactionManager { + /// + /// Location where the message transaction is stored in thread local storage. + /// public static readonly string CURRENT_TRANSACTION_SLOTNAME = UniqueKey.GetTypeScopedString(typeof (MessageQueueTransaction), "Current"); @@ -71,6 +74,16 @@ namespace Spring.Messaging.Core TransactionSynchronization = TransactionSynchronizationState.Never; } + /// + /// Return the current transaction object. + /// + /// The current transaction object. + /// + /// If transaction support is not available. + /// + /// + /// In the case of lookup or system errors. + /// protected override object DoGetTransaction() { MessageQueueTransactionObject txObject = new MessageQueueTransactionObject(); @@ -79,16 +92,33 @@ namespace Spring.Messaging.Core return txObject; } + /// + /// Check if the given transaction object indicates an existing transaction + /// (that is, a transaction which has already started). + /// + /// MessageQueueTransactionObject object returned by + /// . + /// + /// True if there is an existing transaction. + /// protected override bool IsExistingTransaction(object transaction) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction; return (txObject.ResourceHolder != null); } + /// + /// Begin a new transaction with the given transaction definition. + /// + /// Transaction object returned by + /// . + /// instance, describing + /// propagation behavior, isolation level, timeout etc. + /// + /// In the case of creation or system errors. + /// protected override void DoBegin(object transaction, ITransactionDefinition definition) { - //TODO check isolation level is different than default value? - MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction; MessageQueueTransaction mqt = new MessageQueueTransaction(); @@ -105,6 +135,15 @@ namespace Spring.Messaging.Core TransactionSynchronizationManager.BindResource(CURRENT_TRANSACTION_SLOTNAME, txObject.ResourceHolder); } + /// + /// Suspend the resources of the current transaction. + /// + /// Transaction object returned by + /// . + /// + /// An object that holds suspended resources (will be kept unexamined for passing it into + /// .) + /// protected override object DoSuspend(object transaction) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction; @@ -112,12 +151,28 @@ namespace Spring.Messaging.Core return TransactionSynchronizationManager.UnbindResource(CURRENT_TRANSACTION_SLOTNAME); } + /// + /// Resume the resources of the current transaction. + /// + /// Transaction object returned by + /// . + /// The object that holds suspended resources as returned by + /// . protected override void DoResume(object transaction, object suspendedResources) { MessageQueueResourceHolder queueHolder = (MessageQueueResourceHolder) suspendedResources; TransactionSynchronizationManager.BindResource(CURRENT_TRANSACTION_SLOTNAME, queueHolder); } + /// + /// Perform an actual commit on the given transaction. + /// + /// The status representation of the transaction. + /// + ///

+ /// An implementation does not need to check the rollback-only flag. + ///

+ ///
protected override void DoCommit(DefaultTransactionStatus status) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) status.Transaction; @@ -136,6 +191,13 @@ namespace Spring.Messaging.Core } } + /// + /// Perform an actual rollback on the given transaction, calls Transaction.Abort(). + /// + /// The status representation of the transaction. + /// + /// An implementation does not need to check the new transaction flag. + /// protected override void DoRollback(DefaultTransactionStatus status) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) status.Transaction; @@ -154,12 +216,37 @@ namespace Spring.Messaging.Core } } + /// + /// Set the given transaction rollback-only. Only called on rollback + /// if the current transaction takes part in an existing one. + /// + /// The status representation of the transaction. + /// Default implementation throws an IllegalTransactionStateException, + /// assuming that participating in existing transactions is generally not + /// supported. Subclasses are of course encouraged to provide such support. + /// + /// + /// In the case of system errors. + /// protected override void DoSetRollbackOnly(DefaultTransactionStatus status) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) status.Transaction; txObject.ResourceHolder.RollbackOnly = true; } + /// + /// Cleanup resources after transaction completion. + /// + /// Transaction object returned by + /// . + /// + /// + /// Called after + /// and + /// + /// execution on any outcome. + /// + /// protected override void DoCleanupAfterCompletion(object transaction) { MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction; diff --git a/src/Spring/Spring.Messaging/Messaging/Core/QueueIdentifierType.cs b/src/Spring/Spring.Messaging/Messaging/Core/QueueIdentifierType.cs deleted file mode 100644 index 11f41a81..00000000 --- a/src/Spring/Spring.Messaging/Messaging/Core/QueueIdentifierType.cs +++ /dev/null @@ -1,23 +0,0 @@ - - -namespace Spring.Messaging.Core -{ - public enum QueueIdentifierType - { - /// - /// Use a Label to identify the queue, for example new MessageQueue("Label:TheLabel"); - /// - Label, - - /// - /// Use a FormatName to idenitfy the queue, - /// - FormatName, - - MachineName, - - Path, - - QueueName, - } -} \ No newline at end of file diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractListenerContainer.cs index 41d9221b..0c36ddcc 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractListenerContainer.cs @@ -152,6 +152,11 @@ namespace Spring.Messaging.Listener #endregion + /// + /// Initializes this container. Calls the abstract method DoStart if the + /// property is set to true, then calls + /// + /// public virtual void Initialize() { lock (lifecycleMonitor) @@ -166,6 +171,10 @@ namespace Spring.Messaging.Listener DoInitialize(); } + /// + /// Sets the container state to inactive and not running, calls template method + /// + /// public virtual void Shutdown() { LOG.Debug("Shutting down MessageListenerContainer"); @@ -178,11 +187,17 @@ namespace Spring.Messaging.Listener DoShutdown(); } + /// + /// Starts this container. + /// public virtual void Start() { DoStart(); } + /// + /// Sets the state to running, can be overridden in subclasses. + /// protected virtual void DoStart() { lock (lifecycleMonitor) @@ -192,11 +207,17 @@ namespace Spring.Messaging.Listener } } + /// + /// Stops this instance. + /// public virtual void Stop() { DoStop(); } + /// + /// Template method suitable for overriding that stops the container. + /// public virtual void DoStop() { lock (lifecycleMonitor) diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractMessageListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractMessageListenerContainer.cs index d71a6507..a0e5dd21 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractMessageListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractMessageListenerContainer.cs @@ -158,6 +158,10 @@ namespace Spring.Messaging.Listener #region Protected Methods + /// + /// Validates that the is not null. If + /// is null, a is created. Can be be overridden in subclasses. + /// protected override void ValidateConfiguration() { if (MessageQueueObjectName == null) @@ -173,6 +177,14 @@ namespace Spring.Messaging.Listener } + /// + /// Template method that execute listener with the provided message if + /// is true. Subclasses will call + /// this method at the appropriate point in their processing lifecycle, for example + /// committing or rolling back a transaction if needed. + /// + /// Calls the template method + /// The message. protected virtual void DoExecuteListener(Message message) { if (!Running) @@ -187,6 +199,11 @@ namespace Spring.Messaging.Listener InvokeListener(message); } + /// + /// Invokes the listener if it is not null. Invokes the method . + /// Can be overridden in subclasses. + /// + /// The message. protected virtual void InvokeListener(Message message) { if (MessageListener != null) @@ -199,6 +216,11 @@ namespace Spring.Messaging.Listener } } + /// + /// Invokes the listener. Can be overriden in subclasses. + /// + /// The listener. + /// The message. protected virtual void DoInvokeListener(IMessageListener listener, Message message) { listener.OnMessage(message); diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractPeekingMessageListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractPeekingMessageListenerContainer.cs index 7c712694..6afc42c5 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractPeekingMessageListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractPeekingMessageListenerContainer.cs @@ -419,6 +419,11 @@ namespace Spring.Messaging.Listener } + /// + /// Configures the initial peek thread, setting it to be a background thread. + /// Can be overridden in subclasses. + /// + /// The peek thread. protected virtual void ConfigureInitialPeekThread(Thread thread) { thread.IsBackground = true; diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractSendToQueueExceptionHandler.cs b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractSendToQueueExceptionHandler.cs index 8fb97398..33aa727b 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractSendToQueueExceptionHandler.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractSendToQueueExceptionHandler.cs @@ -7,6 +7,14 @@ using Spring.Objects.Factory; namespace Spring.Messaging.Listener { + /// + /// Provides common functionality to exception handlers that will send the exceptional message to + /// another queue. + /// + /// Allows for setting of MaxRetry limit and contains an internal dictionary to keep track + /// of the Message Ids of messages. + /// + /// Mark Pollack public class AbstractSendToQueueExceptionHandler : IInitializingObject, IApplicationContextAware { private int maxRetry = 5; @@ -15,7 +23,15 @@ namespace Spring.Messaging.Listener private string messageQueueObjectName; private IApplicationContext applicationContext; + /// + /// Synchronization object for access to messageMap protected variable + /// protected object messageMapMonitor = new object(); + + + /// + /// In-memory storage to keep track of Message Ids that have been already processed. + /// protected IDictionary messageMap = new Hashtable(); /// diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractTransactionalMessageListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractTransactionalMessageListenerContainer.cs index a1f49957..d7ead973 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/AbstractTransactionalMessageListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/AbstractTransactionalMessageListenerContainer.cs @@ -58,12 +58,20 @@ namespace Spring.Messaging.Listener private DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); + /// + /// Gets or sets the platform transaction manager. + /// + /// The platform transaction manager. public IPlatformTransactionManager PlatformTransactionManager { get { return platformTransactionManager; } set { platformTransactionManager = value; } } + /// + /// Gets or sets the transaction definition. + /// + /// The transaction definition. public DefaultTransactionDefinition TransactionDefinition { get { return transactionDefinition; } @@ -80,6 +88,14 @@ namespace Spring.Messaging.Listener set { transactionDefinition.TransactionTimeout = value; } } + /// + /// Subclasses perform a receive opertion on the message queue and execute the + /// message listener + /// + /// The DefaultMessageQueue. + /// + /// true if received a message, false otherwise + /// protected override bool DoReceiveAndExecute(MessageQueue mq) { bool messageReceived = false; @@ -100,9 +116,20 @@ namespace Spring.Messaging.Listener return messageReceived; } + /// + /// Does the receive and execute using platform transaction manager. + /// + /// The message queue. + /// The transactional status. + /// true if should continue peeking, false otherwise. protected abstract bool DoReceiveAndExecuteUsingPlatformTransactionManager(MessageQueue mq, ITransactionStatus status); + /// + /// Rollback the transaction on exception. + /// + /// The transactional status. + /// The exception. protected void RollbackOnException(ITransactionStatus status, Exception ex) { LOG.Debug("Initiating transaction rollback on listener exception", ex); diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/DistributedTxMessageListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/DistributedTxMessageListenerContainer.cs index fc492970..6153eb45 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/DistributedTxMessageListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/DistributedTxMessageListenerContainer.cs @@ -84,6 +84,15 @@ namespace Spring.Messaging.Listener base.Initialize(); } + /// + /// Does the receive and execute using TxPlatformTransactionManager. Starts a distributed + /// transaction before calling Receive. + /// + /// The message queue. + /// The transactional status. + /// + /// true if should continue peeking, false otherwise. + /// protected override bool DoReceiveAndExecuteUsingPlatformTransactionManager(MessageQueue mq, ITransactionStatus status) { @@ -186,6 +195,12 @@ namespace Spring.Messaging.Listener return true; } + /// + /// Handles the distributed transaction listener exception by calling the + /// if not null. + /// + /// The exception. + /// The message. protected virtual void HandleDistributedTransactionListenerException(Exception exception, Message message) { IDistributedTransactionExceptionHandler exceptionHandler = DistributedTransactionExceptionHandler; diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/MessageListenerAdapter.cs b/src/Spring/Spring.Messaging/Messaging/Listener/MessageListenerAdapter.cs index d1237537..8ebab361 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/MessageListenerAdapter.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/MessageListenerAdapter.cs @@ -161,12 +161,28 @@ namespace Spring.Messaging.Listener #endregion + /// + /// Gets or sets the handler object to delegate message listening to. + /// + /// + /// Specified listener methods have to be present on this target object. + /// If no explicit handler object has been specified, listener + /// methods are expected to present on this adapter instance, that is, + /// on a custom subclass of this adapter, defining listener methods. + /// + /// The handler object. public object HandlerObject { get { return handlerObject; } set { handlerObject = value; } } + /// + /// Gets or sets the default handler method to delegate to, + /// for the case where no specific listener method has been determined. + /// Out-of-the-box value is "HandleMessage". + /// + /// The default handler method. public string DefaultHandlerMethod { get { return defaultHandlerMethod; } @@ -256,18 +272,42 @@ namespace Spring.Messaging.Listener #endregion + /// + /// Gets or sets the message queue factory. + /// + /// The message queue factory. public IMessageQueueFactory MessageQueueFactory { get { return messageQueueFactory; } set { messageQueueFactory = value; } } + /// + /// Sets the name of the default response queue to send response messages to. + /// This will be applied in case of a request message that does not carry a + /// "ResponseQueue" value. + /// Alternatively, specify a response queue via the property + /// . + /// + /// The name of the default response destination queue. public string DefaultResponseQueueName { get { return defaultResponseQueueName; } set { defaultResponseQueueName = value; } } + /// + /// Sets the default destination to send response messages to. This will be applied + /// in case of a request message that does not carry a "ResponseQueue" property + /// Response destinations are only relevant for listener methods that return + /// result objects, which will be wrapped in a response message and sent to a + /// response destination. + /// + /// Alternatively, specify a "DefaultResponseQueueName" + /// to be dynamically resolved via the MessageQueueFactory. + /// + /// + /// The default response destination. public MessageQueue DefaultResponseQueue { get @@ -280,42 +320,36 @@ namespace Spring.Messaging.Listener { return null; } - /* - DefaultMessageQueue mq = LogicalThreadContext.GetData(CURRENT_RESPONSEQUEUE_SLOTNAME) as DefaultMessageQueue; - if (mq == null) - { - mq = ApplicationContext.GetObject(DefaultResponseQueueName) as DefaultMessageQueue; - LogicalThreadContext.SetData(CURRENT_RESPONSEQUEUE_SLOTNAME, mq); - } - return mq; - */ } } + /// + /// Gets or sets the name of the message converter object used to resolved a + /// instance. + /// + /// The name of the message converter object. public string MessageConverterObjectName { get { return messageConverterObjectName; } set { messageConverterObjectName = value; } } + /// + /// Gets message converter that will convert incoming MSMQ messages to + /// listener method arguments, and objects returned from listener + /// methods back to MSMQ messages. + /// + /// + /// The converter used is the one returned by CreateMessageConverter on MessageQueueFactory. + /// + /// + /// The message converter. public IMessageConverter MessageConverter { get { return messageQueueFactory.CreateMessageConverter(MessageConverterObjectName); - /* - if (messageConverter == null) - { - throw new InvalidOperationException("No MessageConverter registered. Check configuration of MessageQueueTemplate."); - } - IMessageConverter mc = LogicalThreadContext.GetData(CURRENT_CONVERTER_SLOTNAME) as IMessageConverter; - if (mc == null) - { - mc = messageConverter.Clone() as IMessageConverter; - LogicalThreadContext.SetData(CURRENT_CONVERTER_SLOTNAME, mc); - } - return mc;*/ } } @@ -366,6 +400,12 @@ namespace Spring.Messaging.Listener messageQueueTemplate = new MessageQueueTemplate(); } + /// + /// Extracts the message body from the given message. + /// + /// The message. + /// the content of the message, to be passed into the + /// listener method as argument protected virtual object ExtractMessage(Message message) { IMessageConverter converter = MessageConverter; @@ -389,12 +429,23 @@ namespace Spring.Messaging.Listener SendResponse(destination, response); } + /// + /// Sends the given response message to the given destination. + /// + /// The destination to send to. + /// The outgoing message about to be sent. protected virtual void SendResponse(MessageQueue destination, Message response) { //Will send with appropriate transaction semantics messageQueueTemplate.Send(destination, response); } + /// + /// Builds a MSMQ message to be sent as response based on the given result object. + /// + /// The result. + /// the MSMQ Message (never null) + /// If no messgae converter is specified. protected virtual Message BuildMessage(object result) { IMessageConverter converter = MessageConverter; @@ -421,11 +472,32 @@ namespace Spring.Messaging.Listener } } + /// + /// Post-process the given response message before it will be sent. The default implementation + /// sets the response's correlation id to the request message's correlation id. + /// + /// The original incoming message. + /// The outgoing MSMQ message about to be sent. protected virtual void PostProcessResponse(Message request, Message response) { response.CorrelationId = request.CorrelationId; } + /// + /// Determine a response destination for the given message. + /// + /// + /// The default implementation first checks the MSMQ ResponseQueue + /// of the supplied request; if that is not null + /// it is returned; if it is null, then the configured + /// default response destination} + /// is returned; if this too is null, then an + /// is thrown. + /// + /// + /// The request. + /// The response. + /// protected virtual MessageQueue GetResponseDestination(Message request, Message response) { MessageQueue replyTo = request.ResponseQueue; diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/NonTransactionalMessageListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/NonTransactionalMessageListenerContainer.cs index e6b59f5e..03310f30 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/NonTransactionalMessageListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/NonTransactionalMessageListenerContainer.cs @@ -32,6 +32,7 @@ namespace Spring.Messaging.Listener /// Exceptions that occur during message processing are handled by an instance /// of . /// + /// Mark Pollack public class NonTransactionalMessageListenerContainer : AbstractPeekingMessageListenerContainer { #region Logging Definition @@ -43,6 +44,10 @@ namespace Spring.Messaging.Listener private IExceptionHandler exceptionHandler; + /// + /// Gets or sets the exception handler. + /// + /// The exception handler. public IExceptionHandler ExceptionHandler { get { return exceptionHandler; } @@ -50,6 +55,11 @@ namespace Spring.Messaging.Listener } + /// + /// Handles the listener exception. + /// + /// The exception. + /// The message delivered that resultd in an processing exception. protected virtual void HandleListenerException(Exception e, Message message) { IExceptionHandler exceptionHandler = ExceptionHandler; @@ -59,6 +69,14 @@ namespace Spring.Messaging.Listener } } + /// + /// Perform a receive opertion on the message queue and execute the + /// message listener + /// + /// The DefaultMessageQueue. + /// + /// true if received a message, false otherwise + /// protected override bool DoReceiveAndExecute(MessageQueue mq) { Message message = null; diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueDistributedTransactionExceptionHandler.cs b/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueDistributedTransactionExceptionHandler.cs index 12ea15b8..1967d3c0 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueDistributedTransactionExceptionHandler.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueDistributedTransactionExceptionHandler.cs @@ -25,6 +25,13 @@ using Common.Logging; namespace Spring.Messaging.Listener { + /// + /// detects poison messages by tracking the Message Id property in memory with a count of how many + /// times an exception has occurred. If that count is greater than the handler's MaxRetry count it + /// will be sent to another queue. The queue to send the message to is specified via the property M + /// essageQueueObjectName. + /// + /// Exception handler when using DistributedTxMessageListenerContainer public class SendToQueueDistributedTransactionExceptionHandler : AbstractSendToQueueExceptionHandler, IDistributedTransactionExceptionHandler { @@ -37,6 +44,19 @@ namespace Spring.Messaging.Listener #region IDistributedTransactionExceptionHandler Members + /// + /// Determines whether the incoming message is a poison message. This method is + /// called before the is invoked. + /// + /// The incoming message. + /// + /// true if it is a poison message; otherwise, false. + /// + /// + /// The will call + /// if this method returns true and will + /// then commit the distibuted transaction (removing the message from the queue). + /// public bool IsPoisonMessage(Message message) { string messageId = message.Id; @@ -56,11 +76,20 @@ namespace Spring.Messaging.Listener } } + /// + /// Handles the poison message. + /// + /// The message. public void HandlePoisonMessage(Message message) { SendMessageToQueue(message); } + /// + /// Called when an exception is thrown in listener processing. + /// + /// The exception. + /// The message. public void OnException(Exception exception, Message message) { string messageId = message.Id; @@ -84,6 +113,10 @@ namespace Spring.Messaging.Listener #endregion + /// + /// Sends the message to queue. + /// + /// The message. protected virtual void SendMessageToQueue(Message message) { MessageQueue mq = MessageQueueFactory.CreateMessageQueue(MessageQueueObjectName); diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueExceptionHandler.cs b/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueExceptionHandler.cs index 113da746..63d5318f 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueExceptionHandler.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/SendToQueueExceptionHandler.cs @@ -25,6 +25,12 @@ using Common.Logging; namespace Spring.Messaging.Listener { + /// + /// Keeps track of the Message's Id property in memory with a count of how many times an + /// exception has occurred. If that count is greater than the handler's MaxRetry count it + /// will be sent to another queue using the provided MessageQueueTransaction. The queue to + /// send the message to is specified via the property MessageQueueObjectName. + /// public class SendToQueueExceptionHandler : AbstractSendToQueueExceptionHandler, IMessageTransactionExceptionHandler { #region Logging Definition @@ -58,6 +64,17 @@ namespace Spring.Messaging.Listener #region IMessageTransactionExceptionHandler Members + /// + /// Called when an exception is thrown during listener processing under the + /// scope of a . + /// + /// The exception. + /// The message. + /// The message queue transaction. + /// + /// An action indicating if the caller should commit or rollback the + /// + /// public TransactionAction OnException(Exception exception, Message message, MessageQueueTransaction messageQueueTransaction) { @@ -100,6 +117,13 @@ namespace Spring.Messaging.Listener #region Protected Methods + /// + /// Determines whether this exception was already processed. + /// + /// The exception. + /// + /// true if the exception was already processed; otherwise, false. + /// protected virtual bool IsMessageAlreadyProcessedException(Exception exception) { if (MessageAlreadyProcessedExceptionNames != null) @@ -115,6 +139,12 @@ namespace Spring.Messaging.Listener return false; } + /// + /// Sends the message to queue. + /// + /// The message. + /// The message queue transaction. + /// TransactionAction.Commit protected virtual TransactionAction SendMessageToQueue(Message message, MessageQueueTransaction messageQueueTransaction) { diff --git a/src/Spring/Spring.Messaging/Messaging/Listener/TransactionalMessageListenerContainer.cs b/src/Spring/Spring.Messaging/Messaging/Listener/TransactionalMessageListenerContainer.cs index 10beda56..dbfb0678 100644 --- a/src/Spring/Spring.Messaging/Messaging/Listener/TransactionalMessageListenerContainer.cs +++ b/src/Spring/Spring.Messaging/Messaging/Listener/TransactionalMessageListenerContainer.cs @@ -241,6 +241,14 @@ namespace Spring.Messaging.Listener #region Protected Methods + /// + /// Does the receive and execute using platform transaction manager. + /// + /// The message queue. + /// The transactional status. + /// + /// true if should continue peeking, false otherwise. + /// protected override bool DoReceiveAndExecuteUsingPlatformTransactionManager(MessageQueue mq, ITransactionStatus status) { @@ -273,6 +281,12 @@ namespace Spring.Messaging.Listener throw new NotImplementedException("Try using NonTransactionalMessageListenerContainer instead."); } + /// + /// Does the recieve and execute using message queue transaction manager. + /// + /// The message queue. + /// The transactional status. + /// true if should continue peeking, false otherise protected virtual bool DoRecieveAndExecuteUsingMessageQueueTransactionManager(MessageQueue mq, ITransactionStatus status) { @@ -291,7 +305,6 @@ namespace Spring.Messaging.Listener try { - //TODO check that GetMessageQueueTransction doesn't return null. message = mq.Receive(TimeSpan.Zero, QueueUtils.GetMessageQueueTransaction(null)); } catch (MessageQueueException ex) @@ -403,6 +416,12 @@ namespace Spring.Messaging.Listener return true; } + /// + /// Does the recieve and execute using a local MessageQueueTransaction. + /// + /// The mqessage queue. + /// The transactional status. + /// true if should continue peeking, false otherwise. protected virtual bool DoRecieveAndExecuteUsingResourceTransactionManagerWithTxQueue(MessageQueue mq, ITransactionStatus status) { @@ -598,6 +617,13 @@ namespace Spring.Messaging.Listener } + /// + /// Handles the transactional listener exception. + /// + /// The exception thrown while processing the message. + /// The message. + /// The message queue transaction. + /// The TransactionAction retruned by the TransactionalExceptionListener protected virtual TransactionAction HandleTransactionalListenerException(Exception e, Message message, MessageQueueTransaction messageQueueTransaction) @@ -628,14 +654,22 @@ namespace Spring.Messaging.Listener } + /// + /// Invokes the transactional exception listener. + /// + /// The exception thrown during message processing. + /// The message. + /// The message queue transaction. + /// TransactionAction.Rollback if no exception handler is defined, otherwise the + /// TransactionAction returned by the exception handler protected virtual TransactionAction InvokeTransactionalExceptionListener(Exception e, Message message, MessageQueueTransaction messageQueueTransaction) { - IMessageTransactionExceptionHandler exMessageTransaction = MessageTransactionExceptionHandler; - if (exMessageTransaction != null) + IMessageTransactionExceptionHandler exceptionHandler = MessageTransactionExceptionHandler; + if (exceptionHandler != null) { - return exMessageTransaction.OnException(e, message, messageQueueTransaction); + return exceptionHandler.OnException(e, message, messageQueueTransaction); } else { diff --git a/src/Spring/Spring.Messaging/Messaging/MessagingException.cs b/src/Spring/Spring.Messaging/Messaging/MessagingException.cs index 4919c167..409f11e9 100644 --- a/src/Spring/Spring.Messaging/Messaging/MessagingException.cs +++ b/src/Spring/Spring.Messaging/Messaging/MessagingException.cs @@ -3,6 +3,10 @@ using System.Runtime.Serialization; namespace Spring.Messaging { + /// + /// Base exception class for exceptions thrown by Spring in Spring.Messaging + /// + /// Mark Pollack public class MessagingException : ApplicationException { #region Constructor (s) / Destructor diff --git a/src/Spring/Spring.Messaging/Messaging/Support/Converters/ActiveXMessageConverter.cs b/src/Spring/Spring.Messaging/Messaging/Support/Converters/ActiveXMessageConverter.cs index a95057e7..8f72212e 100644 --- a/src/Spring/Spring.Messaging/Messaging/Support/Converters/ActiveXMessageConverter.cs +++ b/src/Spring/Spring.Messaging/Messaging/Support/Converters/ActiveXMessageConverter.cs @@ -18,22 +18,32 @@ #endregion - -using System; using System.Messaging; namespace Spring.Messaging.Support.Converters { + /// + /// An implementation that delegates to an instance of + /// to convert messages. + /// + /// Mark Pollack public class ActiveXMessageConverter : IMessageConverter { - private ActiveXMessageFormatter messageFormatter; + private readonly ActiveXMessageFormatter messageFormatter; + /// + /// Initializes a new instance of the class. + /// public ActiveXMessageConverter() { messageFormatter = new ActiveXMessageFormatter(); } + /// + /// Initializes a new instance of the class. + /// + /// The message formatter. public ActiveXMessageConverter(ActiveXMessageFormatter messageFormatter) { this.messageFormatter = messageFormatter; @@ -41,6 +51,11 @@ namespace Spring.Messaging.Support.Converters #region IMessageConverter Members + /// + /// Convert the given object to a Message. + /// + /// The object to send. + /// Message to send public Message ToMessage(object obj) { Message m = new Message(); @@ -49,6 +64,11 @@ namespace Spring.Messaging.Support.Converters return m; } + /// + /// Convert the given message to a object. + /// + /// The message. + /// the object public object FromMessage(Message message) { message.Formatter = messageFormatter; @@ -59,6 +79,12 @@ namespace Spring.Messaging.Support.Converters #region ICloneable Members + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// public object Clone() { ActiveXMessageConverter mc = new ActiveXMessageConverter(messageFormatter.Clone() as ActiveXMessageFormatter); diff --git a/src/Spring/Spring.Messaging/Messaging/Support/Converters/BinaryMessageConverter.cs b/src/Spring/Spring.Messaging/Messaging/Support/Converters/BinaryMessageConverter.cs index df1608bf..1b7aa370 100644 --- a/src/Spring/Spring.Messaging/Messaging/Support/Converters/BinaryMessageConverter.cs +++ b/src/Spring/Spring.Messaging/Messaging/Support/Converters/BinaryMessageConverter.cs @@ -18,44 +18,73 @@ #endregion - -using System; using System.Messaging; using System.Runtime.Serialization.Formatters; namespace Spring.Messaging.Support.Converters { + /// + /// An implementation that delegates to an instance of + /// to convert messages. + /// + /// Mark Pollack public class BinaryMessageConverter : IMessageConverter { - private BinaryMessageFormatter binaryMessageFormatter; + private readonly BinaryMessageFormatter binaryMessageFormatter; - private FormatterTypeStyle typeFormat; - private FormatterAssemblyStyle topObjectFormat; + /// + /// Initializes a new instance of the class. + /// public BinaryMessageConverter() { binaryMessageFormatter = new BinaryMessageFormatter(); } + /// + /// Initializes a new instance of the class. + /// + /// The binary message formatter. public BinaryMessageConverter(BinaryMessageFormatter binaryMessageFormatter) { - this.binaryMessageFormatter = binaryMessageFormatter; + this.binaryMessageFormatter = binaryMessageFormatter; } + /// + /// Gets or sets the type format used in the + /// + /// The type format. public FormatterTypeStyle TypeFormat { - get { return typeFormat; } - set { typeFormat = value; } + get + { + return binaryMessageFormatter.TypeFormat; + } + set { + binaryMessageFormatter.TypeFormat = value; + } } + /// + /// Gets or sets the top object format used in the + /// + /// The top object format. public FormatterAssemblyStyle TopObjectFormat { - get { return topObjectFormat; } - set { topObjectFormat = value; } + get { return binaryMessageFormatter.TopObjectFormat; } + set + { + binaryMessageFormatter.TopObjectFormat = value; + } } #region IMessageConverter Members + /// + /// Convert the given object to a Message using the + /// + /// The object to send. + /// Message to send public Message ToMessage(object obj) { Message m = new Message(); @@ -64,6 +93,11 @@ namespace Spring.Messaging.Support.Converters return m; } + /// + /// Convert the given message to a object using the + /// + /// The message. + /// the object public object FromMessage(Message message) { message.Formatter = binaryMessageFormatter; @@ -74,8 +108,15 @@ namespace Spring.Messaging.Support.Converters #region ICloneable Members + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// public object Clone() { + //takes into account TypeFormat and TypeObjectFormat BinaryMessageConverter mc = new BinaryMessageConverter(binaryMessageFormatter.Clone() as BinaryMessageFormatter); return mc; } diff --git a/src/Spring/Spring.Messaging/Messaging/Support/Converters/IMessageConverter.cs b/src/Spring/Spring.Messaging/Messaging/Support/Converters/IMessageConverter.cs index ceecaf95..7919baf3 100644 --- a/src/Spring/Spring.Messaging/Messaging/Support/Converters/IMessageConverter.cs +++ b/src/Spring/Spring.Messaging/Messaging/Support/Converters/IMessageConverter.cs @@ -23,6 +23,9 @@ using System.Messaging; namespace Spring.Messaging.Support.Converters { + /// + /// An interface specifying the contract to convert to and from objects. + /// public interface IMessageConverter : ICloneable { /// diff --git a/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlDocumentConverter.cs b/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlDocumentConverter.cs index 237648b5..21ea1c85 100644 --- a/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlDocumentConverter.cs +++ b/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlDocumentConverter.cs @@ -1,4 +1,22 @@ +#region License +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed 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. + */ + +#endregion using System; using System.Messaging; @@ -6,10 +24,20 @@ using System.Xml; namespace Spring.Messaging.Support.Converters { + /// + /// Converts an to a Message and vice-versa by using the message's + /// body stream. + /// + /// Mark Pollack public class XmlDocumentConverter : IMessageConverter { #region IMessageConverter Members + /// + /// Convert the given object to a Message. + /// + /// The object to send. + /// Message to send public Message ToMessage(object obj) { XmlDocument doc = obj as XmlDocument; @@ -25,6 +53,11 @@ namespace Spring.Messaging.Support.Converters } } + /// + /// Convert the given message to a object. + /// + /// The message. + /// the object public object FromMessage(Message message) { XmlDocument doc = new XmlDocument(); @@ -36,9 +69,15 @@ namespace Spring.Messaging.Support.Converters #region ICloneable Members + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// public object Clone() { - throw new NotImplementedException(); + return new XmlDocumentConverter(); } #endregion diff --git a/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlMessageConverter.cs b/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlMessageConverter.cs index 37c5befd..d587d802 100644 --- a/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlMessageConverter.cs +++ b/src/Spring/Spring.Messaging/Messaging/Support/Converters/XmlMessageConverter.cs @@ -25,20 +25,36 @@ using Spring.Util; namespace Spring.Messaging.Support.Converters { + /// + /// An implementation that delegates to an instance of + /// to convert messages. + /// + /// Mark Pollack public class XmlMessageConverter : IMessageConverter { private XmlMessageFormatter messageFormatter; + /// + /// Initializes a new instance of the class. + /// public XmlMessageConverter() { messageFormatter = new XmlMessageFormatter(); } + /// + /// Initializes a new instance of the class. + /// + /// The message formatter. public XmlMessageConverter(XmlMessageFormatter messageFormatter) { this.messageFormatter = messageFormatter; } + /// + /// Gets or sets the target types used by the + /// + /// The target types. public Type[] TargetTypes { set @@ -49,6 +65,10 @@ namespace Spring.Messaging.Support.Converters get { return messageFormatter.TargetTypes; } } + /// + /// Gets or sets the target type names used by the + /// + /// The target type names. public string[] TargetTypeNames { set @@ -61,6 +81,11 @@ namespace Spring.Messaging.Support.Converters #region IMessageConverter Members + /// + /// Convert the given object to a Message. + /// + /// The object to send. + /// Message to send public Message ToMessage(object obj) { Message m = new Message(); @@ -69,6 +94,11 @@ namespace Spring.Messaging.Support.Converters return m; } + /// + /// Convert the given message to a object. + /// + /// The message. + /// the object public object FromMessage(Message message) { message.Formatter = messageFormatter; @@ -79,6 +109,12 @@ namespace Spring.Messaging.Support.Converters #region ICloneable Members + /// + /// Creates a new object that is a copy of the current instance. + /// + /// + /// A new object that is a copy of this instance. + /// public object Clone() { XmlMessageConverter mc = new XmlMessageConverter(messageFormatter.Clone() as XmlMessageFormatter); diff --git a/src/Spring/Spring.Messaging/Messaging/Support/QueueUtils.cs b/src/Spring/Spring.Messaging/Messaging/Support/QueueUtils.cs index 60814c08..af619723 100644 --- a/src/Spring/Spring.Messaging/Messaging/Support/QueueUtils.cs +++ b/src/Spring/Spring.Messaging/Messaging/Support/QueueUtils.cs @@ -28,6 +28,9 @@ using Spring.Transaction.Support; namespace Spring.Messaging.Support { + /// + /// Utility methods to support Spring's MSMQ functionality + /// public class QueueUtils { @@ -54,6 +57,12 @@ namespace Spring.Messaging.Support return messageConverterObjectName; } + + /// + /// Gets the message queue transaction from thread local storage + /// + /// The resource factory. + /// null if not found in thread local storage public static MessageQueueTransaction GetMessageQueueTransaction(IResourceFactory resourceFactory) { MessageQueueResourceHolder resourceHolder = @@ -64,25 +73,10 @@ namespace Spring.Messaging.Support { return resourceHolder.MessageQueueTransaction; } - if (!TransactionSynchronizationManager.SynchronizationActive) + else { return null; - } - throw new NotImplementedException(); - /* - MessageQueueResourceHolder resourceHolderToUse = resourceHolder; - if (resourceHolderToUse == null) - { - resourceHolderToUse = new MessageQueueResourceHolder(new MessageQueueTransaction()); - } - if (resourceHolderToUse != resourceHolder) - { - TransactionSynchronizationManager.RegisterSynchronization( - new MessageQueueResourceSynchronization(resourceHolderToUse, resourceFactory.SynchedLocalTransactionAllowed)); - resourceHolderToUse.SynchronizedWithTransaction = true; - TransactionSynchronizationManager.BindResource(MessageQueueTransactionManager.CURRENT_TRANSACTION_SLOTNAME, resourceHolderToUse); - } - return resourceHolderToUse.MessageQueueTransaction;*/ + } } } @@ -144,8 +138,18 @@ namespace Spring.Messaging.Support #endregion } + /// Callback interface for resource creation. + /// Serving as argument for the GetMessageQueueTransaction method. + /// public interface IResourceFactory { + /// + /// Return whether to allow for a local transaction that is synchronized with + /// a Spring-managed transaction (where the main transaction might be a ADO.NET-based + /// one for a specific IDbProvider, for example), with the MSMQ transaction + /// committing right after the main transaction. + /// Returns whether to allow for synchronizing a local MSMQ transaction + /// bool SynchedLocalTransactionAllowed { get; } } } \ No newline at end of file diff --git a/src/Spring/Spring.Messaging/Spring.Messaging.2008.csproj b/src/Spring/Spring.Messaging/Spring.Messaging.2008.csproj index 2b5437f4..2596de2a 100644 --- a/src/Spring/Spring.Messaging/Spring.Messaging.2008.csproj +++ b/src/Spring/Spring.Messaging/Spring.Messaging.2008.csproj @@ -20,6 +20,7 @@ prompt 4 Spring.Messaging.xml + false pdbonly @@ -52,7 +53,6 @@ -