add XML code comments
Minor cleanup
This commit is contained in:
@@ -47,6 +47,12 @@ namespace Spring.Messaging.Core
|
||||
|
||||
#region IMessageQueueFactory Members
|
||||
|
||||
/// <summary>
|
||||
/// Registers the message queue, its creation specified via the factory method
|
||||
/// MessageQueueCreatorDelegate, with the provided name in the application context
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <param name="messageQueueCreatorDelegate">The message queue creator delegate.</param>
|
||||
public void RegisterMessageQueue(string messageQueueObjectName,
|
||||
MessageQueueCreatorDelegate messageQueueCreatorDelegate)
|
||||
{
|
||||
@@ -55,6 +61,13 @@ namespace Spring.Messaging.Core
|
||||
applicationContext.ObjectFactory.RegisterSingleton(messageQueueObjectName, mqfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the message queue given its name in the application context.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <returns>
|
||||
/// A MessageQueue instance configured via the application context
|
||||
/// </returns>
|
||||
public MessageQueue CreateMessageQueue(string messageQueueObjectName)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(messageQueueObjectName, "DefaultMessageQueueObjectName");
|
||||
@@ -72,11 +85,23 @@ namespace Spring.Messaging.Core
|
||||
return queues[messageQueueObjectName] as MessageQueue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the application context contains the message queue object definition.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the application context contains the specified message queue object name; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool ContainsMessageQueue(string messageQueueObjectName)
|
||||
{
|
||||
return applicationContext.ContainsObject(messageQueueObjectName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the message converter.
|
||||
/// </summary>
|
||||
/// <param name="messageConverterName">Name of the message converter.</param>
|
||||
/// <param name="messageConverterCreatorDelegate">The message converter creator delegate.</param>
|
||||
public void RegisterMessageConverter(string messageConverterName,
|
||||
MessageConverterCreatorDelegate messageConverterCreatorDelegate)
|
||||
{
|
||||
@@ -85,6 +110,13 @@ namespace Spring.Messaging.Core
|
||||
applicationContext.ObjectFactory.RegisterSingleton(messageConverterName, mcfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the message converter given its name in the application context.
|
||||
/// </summary>
|
||||
/// <param name="messageConverterObjectName">Name of the message converter object.</param>
|
||||
/// <returns>
|
||||
/// A IMessageConverter instance configured via the application context
|
||||
/// </returns>
|
||||
public IMessageConverter CreateMessageConverter(string messageConverterObjectName)
|
||||
{
|
||||
AssertUtils.ArgumentHasText(messageConverterObjectName, "MessgaeFormatterObjectName");
|
||||
@@ -103,6 +135,13 @@ namespace Spring.Messaging.Core
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the application context contains the message queue object definition.
|
||||
/// </summary>
|
||||
/// <param name="messageConverterObjectName">Name of the message converter object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the application context contains the specified message message converter object name; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool ContainsMessageConverter(string messageConverterObjectName)
|
||||
{
|
||||
return applicationContext.ContainsObject(messageConverterObjectName);
|
||||
|
||||
@@ -37,21 +37,57 @@ namespace Spring.Messaging.Core
|
||||
/// <author>Mark Pollack</author>
|
||||
public interface IMessageQueueFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers the message queue, its creation specified via the factory method
|
||||
/// MessageQueueCreatorDelegate, with the provided name in the application context
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <param name="messageQueueCreatorDelegate">The message queue creator delegate.</param>
|
||||
void RegisterMessageQueue(string messageQueueObjectName,
|
||||
MessageQueueCreatorDelegate messageQueueCreatorDelegate);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the message queue given its name in the application context.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <returns>A MessageQueue instance configured via the application context</returns>
|
||||
MessageQueue CreateMessageQueue(string messageQueueObjectName);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the application context contains the message queue object definition.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the application context contains the specified message queue object name; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
bool ContainsMessageQueue(string messageQueueObjectName);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Registers the message converter, its creation specified via the factory method
|
||||
/// MessageConverterCreatorDelegate, with the provided name in the application context.
|
||||
/// </summary>
|
||||
/// <param name="messageConverterName">Name of the message converter.</param>
|
||||
/// <param name="MessageConverterCreatorDelegate">The message converter creator delegate.</param>
|
||||
void RegisterMessageConverter(string messageConverterName,
|
||||
MessageConverterCreatorDelegate MessageConverterCreatorDelegate);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the message converter given its name in the application context.
|
||||
/// </summary>
|
||||
/// <param name="messageConverterObjectName">Name of the message converter object.</param>
|
||||
/// <returns>A IMessageConverter instance configured via the application context</returns>
|
||||
IMessageConverter CreateMessageConverter(string messageConverterObjectName);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the application context contains the message queue object definition.
|
||||
/// </summary>
|
||||
/// <param name="messageConverterObjectName">Name of the message converter object.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the application context contains the specified message message converter object name; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
bool ContainsMessageConverter(string messageConverterObjectName);
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace Spring.Messaging.Core
|
||||
/// <author>Mark Pollack</author>
|
||||
public class LocallyExposedMessageQueueResourceHolder : MessageQueueResourceHolder
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocallyExposedMessageQueueResourceHolder"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueTransaction">The message queue transaction.</param>
|
||||
public LocallyExposedMessageQueueResourceHolder(MessageQueueTransaction messageQueueTransaction)
|
||||
: base(messageQueueTransaction)
|
||||
{
|
||||
|
||||
@@ -269,24 +269,61 @@ namespace Spring.Messaging.Core
|
||||
|
||||
#region IMessageQueueOperations Members
|
||||
|
||||
/// <summary>
|
||||
/// Send the given object to the default destination, converting the object
|
||||
/// to a MSMQ message with a configured IMessageConverter.
|
||||
/// </summary>
|
||||
/// <param name="obj">The obj.</param>
|
||||
/// <remarks>This will only work with a default destination queue specified!</remarks>
|
||||
public void ConvertAndSend(object obj)
|
||||
{
|
||||
CheckDefaultMessageQueue();
|
||||
ConvertAndSend(DefaultMessageQueueObjectName, obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// <p>This will only work with a default destination specified!</p>
|
||||
/// </summary>
|
||||
/// <param name="obj">the object to convert to a message</param>
|
||||
/// <param name="messagePostProcessorDelegate">the callback to modify the message</param>
|
||||
/// <exception cref="MessagingException">if thrown by MSMQ API methods</exception>
|
||||
public void ConvertAndSend(object obj, MessagePostProcessorDelegate messagePostProcessorDelegate)
|
||||
{
|
||||
CheckDefaultMessageQueue();
|
||||
ConvertAndSend(DefaultMessageQueueObjectName, obj, messagePostProcessorDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send the given object to the specified destination, converting the object
|
||||
/// to a MSMQ message with a configured <see cref="IMessageConverter"/> and resolving the
|
||||
/// destination name to a <see cref="MessageQueue"/> using a <see cref="IMessageQueueFactory"/>
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">the name of the destination queue
|
||||
/// to send this message to (to be resolved to an actual MessageQueue
|
||||
/// by a IMessageQueueFactory)</param>
|
||||
/// <param name="obj">the object to convert to a message</param>
|
||||
/// <throws>NMSException if there is any problem</throws>
|
||||
public void ConvertAndSend(string messageQueueObjectName, object obj)
|
||||
{
|
||||
Message msg = MessageConverter.ToMessage(obj);
|
||||
Send(MessageQueueFactory.CreateMessageQueue(messageQueueObjectName), msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send the given object to the specified destination, converting the object
|
||||
/// to a MSMQ message with a configured <see cref="IMessageConverter"/> and resolving the
|
||||
/// destination name to a <see cref="MessageQueue"/> with an <see cref="IMessageQueueFactory"/>
|
||||
/// The <see cref="MessagePostProcessorDelegate"/> callback allows for modification of the message after conversion.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">the name of the destination queue
|
||||
/// to send this message to (to be resolved to an actual MessageQueue
|
||||
/// by a IMessageQueueFactory)</param>
|
||||
/// <param name="obj">the object to convert to a message</param>
|
||||
/// <param name="messagePostProcessorDelegate">the callback to modify the message</param>
|
||||
/// <exception cref="MessagingException">if thrown by MSMQ API methods</exception>
|
||||
public void ConvertAndSend(string messageQueueObjectName, object obj,
|
||||
MessagePostProcessorDelegate messagePostProcessorDelegate)
|
||||
{
|
||||
@@ -295,6 +332,13 @@ namespace Spring.Messaging.Core
|
||||
Send(MessageQueueFactory.CreateMessageQueue(messageQueueObjectName), msgToSend);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receive and convert a message synchronously from the default message queue.
|
||||
/// </summary>
|
||||
/// <returns>The converted object</returns>
|
||||
/// <exception cref="MessageQueueException">if thrown by MSMQ API methods. Note an
|
||||
/// exception will be thrown if the timeout of the syncrhonous recieve operation expires.
|
||||
/// </exception>
|
||||
public object ReceiveAndConvert()
|
||||
{
|
||||
MessageQueue mq = DefaultMessageQueue;
|
||||
@@ -302,6 +346,14 @@ namespace Spring.Messaging.Core
|
||||
return DoConvertMessage(m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receives and convert a message synchronously from the specified message queue.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <returns>the converted object</returns>
|
||||
/// <exception cref="MessageQueueException">if thrown by MSMQ API methods. Note an
|
||||
/// exception will be thrown if the timeout of the syncrhonous recieve operation expires.
|
||||
/// </exception>
|
||||
public object ReceiveAndConvert(string messageQueueObjectName)
|
||||
{
|
||||
MessageQueue mq = MessageQueueFactory.CreateMessageQueue(messageQueueObjectName);
|
||||
@@ -309,26 +361,64 @@ namespace Spring.Messaging.Core
|
||||
return DoConvertMessage(m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <returns>A message.</returns>
|
||||
public Message Receive()
|
||||
{
|
||||
return DefaultMessageQueue.Receive(ReceiveTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <returns></returns>
|
||||
public Message Receive(string messageQueueObjectName)
|
||||
{
|
||||
return MessageQueueFactory.CreateMessageQueue(messageQueueObjectName).Receive(ReceiveTimeout);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to send</param>
|
||||
public void Send(Message message)
|
||||
{
|
||||
Send(DefaultMessageQueue, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="messageQueueObjectName">Name of the message queue object.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
public void Send(string messageQueueObjectName, Message message)
|
||||
{
|
||||
Send(MessageQueueFactory.CreateMessageQueue(messageQueueObjectName), message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="messageQueue">The DefaultMessageQueue to send a message to.</param>
|
||||
/// <param name="message">The message to send</param>
|
||||
/// <para>
|
||||
/// Note that it is the callers responsibility to ensure that the MessageQueue instance
|
||||
/// passed into this not being access simultaneously by other threads.
|
||||
/// </para>
|
||||
/// <remarks>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.</remarks>
|
||||
public virtual void Send(MessageQueue messageQueue, Message message)
|
||||
{
|
||||
DoSend(messageQueue, message);
|
||||
@@ -338,6 +428,13 @@ namespace Spring.Messaging.Core
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message to the given message queue.
|
||||
/// </summary>
|
||||
/// <remarks>If System.Transactions.Transaction.Current is null, then send based on
|
||||
/// the transaction semantics of the queue definition. See <see cref="DoSendMessageQueueTransactional"/> </remarks>
|
||||
/// <param name="messageQueue">The message queue.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
protected virtual void DoSend(MessageQueue messageQueue, Message message)
|
||||
{
|
||||
if (System.Transactions.Transaction.Current == null)
|
||||
@@ -350,6 +447,34 @@ namespace Spring.Messaging.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send the message queue selecting the appropriate transactional delivery options.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// 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.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// 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).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If there is an ambient System.Transactions transaction then that transaction will
|
||||
/// be used (MessageQueueTransactionType = Automatic).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If the queue is not transactional, then a non-transactional send
|
||||
/// (MessageQueueTransactionType = None) is used.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="mq">The mq.</param>
|
||||
/// <param name="msg">The MSG.</param>
|
||||
protected virtual void DoSendMessageQueueTransactional(MessageQueue mq, Message msg)
|
||||
{
|
||||
MessageQueueTransaction transactionToUse = QueueUtils.GetMessageQueueTransaction(null);
|
||||
@@ -400,11 +525,21 @@ namespace Spring.Messaging.Core
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends using MessageQueueTransactionType.Automatic transaction type
|
||||
/// </summary>
|
||||
/// <param name="mq">The message queue.</param>
|
||||
/// <param name="msg">The message.</param>
|
||||
protected virtual void DoSendTxScope(MessageQueue mq, Message msg)
|
||||
{
|
||||
mq.Send(msg, MessageQueueTransactionType.Automatic);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Template method to convert the message if it is not null.
|
||||
/// </summary>
|
||||
/// <param name="m">The message.</param>
|
||||
/// <returns>The converted message ,or null if no message converter is set.</returns>
|
||||
protected virtual object DoConvertMessage(Message m)
|
||||
{
|
||||
if (m != null)
|
||||
@@ -417,6 +552,9 @@ namespace Spring.Messaging.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the default message queue if defined.
|
||||
/// </summary>
|
||||
protected virtual void CheckDefaultMessageQueue()
|
||||
{
|
||||
if (DefaultMessageQueueObjectName == null)
|
||||
|
||||
@@ -48,6 +48,9 @@ namespace Spring.Messaging.Core
|
||||
/// <author>Mark Pollack</author>
|
||||
public class MessageQueueTransactionManager : AbstractPlatformTransactionManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Location where the message transaction is stored in thread local storage.
|
||||
/// </summary>
|
||||
public static readonly string CURRENT_TRANSACTION_SLOTNAME =
|
||||
UniqueKey.GetTypeScopedString(typeof (MessageQueueTransaction), "Current");
|
||||
|
||||
@@ -71,6 +74,16 @@ namespace Spring.Messaging.Core
|
||||
TransactionSynchronization = TransactionSynchronizationState.Never;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the current transaction object.
|
||||
/// </summary>
|
||||
/// <returns>The current transaction object.</returns>
|
||||
/// <exception cref="Spring.Transaction.CannotCreateTransactionException">
|
||||
/// If transaction support is not available.
|
||||
/// </exception>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of lookup or system errors.
|
||||
/// </exception>
|
||||
protected override object DoGetTransaction()
|
||||
{
|
||||
MessageQueueTransactionObject txObject = new MessageQueueTransactionObject();
|
||||
@@ -79,16 +92,33 @@ namespace Spring.Messaging.Core
|
||||
return txObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given transaction object indicates an existing transaction
|
||||
/// (that is, a transaction which has already started).
|
||||
/// </summary>
|
||||
/// <param name="transaction">MessageQueueTransactionObject object returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
|
||||
/// <returns>
|
||||
/// True if there is an existing transaction.
|
||||
/// </returns>
|
||||
protected override bool IsExistingTransaction(object transaction)
|
||||
{
|
||||
MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction;
|
||||
return (txObject.ResourceHolder != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Begin a new transaction with the given transaction definition.
|
||||
/// </summary>
|
||||
/// <param name="transaction">Transaction object returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
|
||||
/// <param name="definition"><see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing
|
||||
/// propagation behavior, isolation level, timeout etc.</param>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of creation or system errors.
|
||||
/// </exception>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Suspend the resources of the current transaction.
|
||||
/// </summary>
|
||||
/// <param name="transaction">Transaction object returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
|
||||
/// <returns>
|
||||
/// An object that holds suspended resources (will be kept unexamined for passing it into
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoResume"/>.)
|
||||
/// </returns>
|
||||
protected override object DoSuspend(object transaction)
|
||||
{
|
||||
MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction;
|
||||
@@ -112,12 +151,28 @@ namespace Spring.Messaging.Core
|
||||
return TransactionSynchronizationManager.UnbindResource(CURRENT_TRANSACTION_SLOTNAME);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resume the resources of the current transaction.
|
||||
/// </summary>
|
||||
/// <param name="transaction">Transaction object returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
|
||||
/// <param name="suspendedResources">The object that holds suspended resources as returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoSuspend"/>.</param>
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
MessageQueueResourceHolder queueHolder = (MessageQueueResourceHolder) suspendedResources;
|
||||
TransactionSynchronizationManager.BindResource(CURRENT_TRANSACTION_SLOTNAME, queueHolder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an actual commit on the given transaction.
|
||||
/// </summary>
|
||||
/// <param name="status">The status representation of the transaction.</param>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// An implementation does not need to check the rollback-only flag.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
protected override void DoCommit(DefaultTransactionStatus status)
|
||||
{
|
||||
MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) status.Transaction;
|
||||
@@ -136,6 +191,13 @@ namespace Spring.Messaging.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an actual rollback on the given transaction, calls Transaction.Abort().
|
||||
/// </summary>
|
||||
/// <param name="status">The status representation of the transaction.</param>
|
||||
/// <remarks>
|
||||
/// An implementation does not need to check the new transaction flag.
|
||||
/// </remarks>
|
||||
protected override void DoRollback(DefaultTransactionStatus status)
|
||||
{
|
||||
MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) status.Transaction;
|
||||
@@ -154,12 +216,37 @@ namespace Spring.Messaging.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the given transaction rollback-only. Only called on rollback
|
||||
/// if the current transaction takes part in an existing one.
|
||||
/// </summary>
|
||||
/// <param name="status">The status representation of the transaction.</param>
|
||||
/// <remarks>Default implementation throws an IllegalTransactionStateException,
|
||||
/// assuming that participating in existing transactions is generally not
|
||||
/// supported. Subclasses are of course encouraged to provide such support.
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of system errors.
|
||||
/// </exception>
|
||||
protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
|
||||
{
|
||||
MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) status.Transaction;
|
||||
txObject.ResourceHolder.RollbackOnly = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cleanup resources after transaction completion.
|
||||
/// </summary>
|
||||
/// <param name="transaction">Transaction object returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Called after <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoCommit"/>
|
||||
/// and
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoRollback"/>
|
||||
/// execution on any outcome.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
protected override void DoCleanupAfterCompletion(object transaction)
|
||||
{
|
||||
MessageQueueTransactionObject txObject = (MessageQueueTransactionObject) transaction;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
|
||||
namespace Spring.Messaging.Core
|
||||
{
|
||||
public enum QueueIdentifierType
|
||||
{
|
||||
/// <summary>
|
||||
/// Use a Label to identify the queue, for example new MessageQueue("Label:TheLabel");
|
||||
/// </summary>
|
||||
Label,
|
||||
|
||||
/// <summary>
|
||||
/// Use a FormatName to idenitfy the queue,
|
||||
/// </summary>
|
||||
FormatName,
|
||||
|
||||
MachineName,
|
||||
|
||||
Path,
|
||||
|
||||
QueueName,
|
||||
}
|
||||
}
|
||||
@@ -152,6 +152,11 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this container. Calls the abstract method DoStart if the
|
||||
/// property <see cref="AutoStartup"/> is set to true, then calls
|
||||
/// <see cref="DoInitialize"/>
|
||||
/// </summary>
|
||||
public virtual void Initialize()
|
||||
{
|
||||
lock (lifecycleMonitor)
|
||||
@@ -166,6 +171,10 @@ namespace Spring.Messaging.Listener
|
||||
DoInitialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container state to inactive and not running, calls template method
|
||||
/// <see cref="DoShutdown"/>
|
||||
/// </summary>
|
||||
public virtual void Shutdown()
|
||||
{
|
||||
LOG.Debug("Shutting down MessageListenerContainer");
|
||||
@@ -178,11 +187,17 @@ namespace Spring.Messaging.Listener
|
||||
DoShutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts this container.
|
||||
/// </summary>
|
||||
public virtual void Start()
|
||||
{
|
||||
DoStart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the state to running, can be overridden in subclasses.
|
||||
/// </summary>
|
||||
protected virtual void DoStart()
|
||||
{
|
||||
lock (lifecycleMonitor)
|
||||
@@ -192,11 +207,17 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops this instance.
|
||||
/// </summary>
|
||||
public virtual void Stop()
|
||||
{
|
||||
DoStop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Template method suitable for overriding that stops the container.
|
||||
/// </summary>
|
||||
public virtual void DoStop()
|
||||
{
|
||||
lock (lifecycleMonitor)
|
||||
|
||||
@@ -158,6 +158,10 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Validates that the <see cref="messageQueueObjectName"/> is not null. If <see cref="MessageQueueFactory"/>
|
||||
/// is null, a <see cref="DefaultMessageQueueFactory"/> is created. Can be be overridden in subclasses.
|
||||
/// </summary>
|
||||
protected override void ValidateConfiguration()
|
||||
{
|
||||
if (MessageQueueObjectName == null)
|
||||
@@ -173,6 +177,14 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Template method that execute listener with the provided message if
|
||||
/// <see cref="AbstractListenerContainer.Running"/> 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.
|
||||
/// </summary>
|
||||
/// <remarks>Calls the template method <see cref="InvokeListener"/></remarks>
|
||||
/// <param name="message">The message.</param>
|
||||
protected virtual void DoExecuteListener(Message message)
|
||||
{
|
||||
if (!Running)
|
||||
@@ -187,6 +199,11 @@ namespace Spring.Messaging.Listener
|
||||
InvokeListener(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the listener if it is not null. Invokes the method <see cref="DoInvokeListener"/>.
|
||||
/// Can be overridden in subclasses.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
protected virtual void InvokeListener(Message message)
|
||||
{
|
||||
if (MessageListener != null)
|
||||
@@ -199,6 +216,11 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the listener. Can be overriden in subclasses.
|
||||
/// </summary>
|
||||
/// <param name="listener">The listener.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
protected virtual void DoInvokeListener(IMessageListener listener, Message message)
|
||||
{
|
||||
listener.OnMessage(message);
|
||||
|
||||
@@ -419,6 +419,11 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Configures the initial peek thread, setting it to be a background thread.
|
||||
/// Can be overridden in subclasses.
|
||||
/// </summary>
|
||||
/// <param name="thread">The peek thread.</param>
|
||||
protected virtual void ConfigureInitialPeekThread(Thread thread)
|
||||
{
|
||||
thread.IsBackground = true;
|
||||
|
||||
@@ -7,6 +7,14 @@ using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Messaging.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides common functionality to exception handlers that will send the exceptional message to
|
||||
/// another queue.
|
||||
/// </summary>
|
||||
/// <remarks>Allows for setting of MaxRetry limit and contains an internal dictionary to keep track
|
||||
/// of the Message Ids of messages.
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class AbstractSendToQueueExceptionHandler : IInitializingObject, IApplicationContextAware
|
||||
{
|
||||
private int maxRetry = 5;
|
||||
@@ -15,7 +23,15 @@ namespace Spring.Messaging.Listener
|
||||
private string messageQueueObjectName;
|
||||
private IApplicationContext applicationContext;
|
||||
|
||||
/// <summary>
|
||||
/// Synchronization object for access to messageMap protected variable
|
||||
/// </summary>
|
||||
protected object messageMapMonitor = new object();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// In-memory storage to keep track of Message Ids that have been already processed.
|
||||
/// </summary>
|
||||
protected IDictionary messageMap = new Hashtable();
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -58,12 +58,20 @@ namespace Spring.Messaging.Listener
|
||||
private DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the platform transaction manager.
|
||||
/// </summary>
|
||||
/// <value>The platform transaction manager.</value>
|
||||
public IPlatformTransactionManager PlatformTransactionManager
|
||||
{
|
||||
get { return platformTransactionManager; }
|
||||
set { platformTransactionManager = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transaction definition.
|
||||
/// </summary>
|
||||
/// <value>The transaction definition.</value>
|
||||
public DefaultTransactionDefinition TransactionDefinition
|
||||
{
|
||||
get { return transactionDefinition; }
|
||||
@@ -80,6 +88,14 @@ namespace Spring.Messaging.Listener
|
||||
set { transactionDefinition.TransactionTimeout = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subclasses perform a receive opertion on the message queue and execute the
|
||||
/// message listener
|
||||
/// </summary>
|
||||
/// <param name="mq">The DefaultMessageQueue.</param>
|
||||
/// <returns>
|
||||
/// true if received a message, false otherwise
|
||||
/// </returns>
|
||||
protected override bool DoReceiveAndExecute(MessageQueue mq)
|
||||
{
|
||||
bool messageReceived = false;
|
||||
@@ -100,9 +116,20 @@ namespace Spring.Messaging.Listener
|
||||
return messageReceived;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the receive and execute using platform transaction manager.
|
||||
/// </summary>
|
||||
/// <param name="mq">The message queue.</param>
|
||||
/// <param name="status">The transactional status.</param>
|
||||
/// <returns>true if should continue peeking, false otherwise.</returns>
|
||||
protected abstract bool DoReceiveAndExecuteUsingPlatformTransactionManager(MessageQueue mq,
|
||||
ITransactionStatus status);
|
||||
|
||||
/// <summary>
|
||||
/// Rollback the transaction on exception.
|
||||
/// </summary>
|
||||
/// <param name="status">The transactional status.</param>
|
||||
/// <param name="ex">The exception.</param>
|
||||
protected void RollbackOnException(ITransactionStatus status, Exception ex)
|
||||
{
|
||||
LOG.Debug("Initiating transaction rollback on listener exception", ex);
|
||||
|
||||
@@ -84,6 +84,15 @@ namespace Spring.Messaging.Listener
|
||||
base.Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the receive and execute using TxPlatformTransactionManager. Starts a distributed
|
||||
/// transaction before calling Receive.
|
||||
/// </summary>
|
||||
/// <param name="mq">The message queue.</param>
|
||||
/// <param name="status">The transactional status.</param>
|
||||
/// <returns>
|
||||
/// true if should continue peeking, false otherwise.
|
||||
/// </returns>
|
||||
protected override bool DoReceiveAndExecuteUsingPlatformTransactionManager(MessageQueue mq,
|
||||
ITransactionStatus status)
|
||||
{
|
||||
@@ -186,6 +195,12 @@ namespace Spring.Messaging.Listener
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the distributed transaction listener exception by calling the
|
||||
/// <see cref="IDistributedTransactionExceptionHandler"/> if not null.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
protected virtual void HandleDistributedTransactionListenerException(Exception exception, Message message)
|
||||
{
|
||||
IDistributedTransactionExceptionHandler exceptionHandler = DistributedTransactionExceptionHandler;
|
||||
|
||||
@@ -161,12 +161,28 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the handler object to delegate message listening to.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 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.
|
||||
/// </remarks>
|
||||
/// <value>The handler object.</value>
|
||||
public object HandlerObject
|
||||
{
|
||||
get { return handlerObject; }
|
||||
set { handlerObject = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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".
|
||||
/// </summary>
|
||||
/// <value>The default handler method.</value>
|
||||
public string DefaultHandlerMethod
|
||||
{
|
||||
get { return defaultHandlerMethod; }
|
||||
@@ -256,18 +272,42 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message queue factory.
|
||||
/// </summary>
|
||||
/// <value>The message queue factory.</value>
|
||||
public IMessageQueueFactory MessageQueueFactory
|
||||
{
|
||||
get { return messageQueueFactory; }
|
||||
set { messageQueueFactory = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// <para>Alternatively, specify a response queue via the property
|
||||
/// <see cref="DefaultResponseQueue"/>.</para>
|
||||
/// </summary>
|
||||
/// <value>The name of the default response destination queue.</value>
|
||||
public string DefaultResponseQueueName
|
||||
{
|
||||
get { return defaultResponseQueueName; }
|
||||
set { defaultResponseQueueName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// <para>
|
||||
/// Alternatively, specify a "DefaultResponseQueueName"
|
||||
/// to be dynamically resolved via the MessageQueueFactory.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <value>The default response destination.</value>
|
||||
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;
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the message converter object used to resolved a <see cref="IMessageConverter"/>
|
||||
/// instance.
|
||||
/// </summary>
|
||||
/// <value>The name of the message converter object.</value>
|
||||
public string MessageConverterObjectName
|
||||
{
|
||||
get { return messageConverterObjectName; }
|
||||
set { messageConverterObjectName = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets message converter that will convert incoming MSMQ messages to
|
||||
/// listener method arguments, and objects returned from listener
|
||||
/// methods back to MSMQ messages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The converter used is the one returned by CreateMessageConverter on MessageQueueFactory.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>The message converter.</value>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the message body from the given message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>the content of the message, to be passed into the
|
||||
/// listener method as argument</returns>
|
||||
protected virtual object ExtractMessage(Message message)
|
||||
{
|
||||
IMessageConverter converter = MessageConverter;
|
||||
@@ -389,12 +429,23 @@ namespace Spring.Messaging.Listener
|
||||
SendResponse(destination, response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the given response message to the given destination.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination to send to.</param>
|
||||
/// <param name="response">The outgoing message about to be sent.</param>
|
||||
protected virtual void SendResponse(MessageQueue destination, Message response)
|
||||
{
|
||||
//Will send with appropriate transaction semantics
|
||||
messageQueueTemplate.Send(destination, response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a MSMQ message to be sent as response based on the given result object.
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <returns>the MSMQ <code>Message</code> (never <code>null</code>)</returns>
|
||||
/// <exception cref="MessagingException">If no messgae converter is specified.</exception>
|
||||
protected virtual Message BuildMessage(object result)
|
||||
{
|
||||
IMessageConverter converter = MessageConverter;
|
||||
@@ -421,11 +472,32 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="request">The original incoming message.</param>
|
||||
/// <param name="response">The outgoing MSMQ message about to be sent.</param>
|
||||
protected virtual void PostProcessResponse(Message request, Message response)
|
||||
{
|
||||
response.CorrelationId = request.CorrelationId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine a response destination for the given message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The default implementation first checks the MSMQ ResponseQueue
|
||||
/// of the supplied request; if that is not <code>null</code>
|
||||
/// it is returned; if it is <code>null</code>, then the configured
|
||||
/// <see cref="DefaultResponseQueue"/> default response destination}
|
||||
/// is returned; if this too is <code>null</code>, then an
|
||||
/// <see cref="MessagingException"/>is thrown.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <param name="response">The response.</param>
|
||||
/// <returns></returns>
|
||||
protected virtual MessageQueue GetResponseDestination(Message request, Message response)
|
||||
{
|
||||
MessageQueue replyTo = request.ResponseQueue;
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Spring.Messaging.Listener
|
||||
/// Exceptions that occur during message processing are handled by an instance
|
||||
/// of <see cref="IExceptionHandler"/>.
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class NonTransactionalMessageListenerContainer : AbstractPeekingMessageListenerContainer
|
||||
{
|
||||
#region Logging Definition
|
||||
@@ -43,6 +44,10 @@ namespace Spring.Messaging.Listener
|
||||
private IExceptionHandler exceptionHandler;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exception handler.
|
||||
/// </summary>
|
||||
/// <value>The exception handler.</value>
|
||||
public IExceptionHandler ExceptionHandler
|
||||
{
|
||||
get { return exceptionHandler; }
|
||||
@@ -50,6 +55,11 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles the listener exception.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception.</param>
|
||||
/// <param name="message">The message delivered that resultd in an processing exception.</param>
|
||||
protected virtual void HandleListenerException(Exception e, Message message)
|
||||
{
|
||||
IExceptionHandler exceptionHandler = ExceptionHandler;
|
||||
@@ -59,6 +69,14 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a receive opertion on the message queue and execute the
|
||||
/// message listener
|
||||
/// </summary>
|
||||
/// <param name="mq">The DefaultMessageQueue.</param>
|
||||
/// <returns>
|
||||
/// true if received a message, false otherwise
|
||||
/// </returns>
|
||||
protected override bool DoReceiveAndExecute(MessageQueue mq)
|
||||
{
|
||||
Message message = null;
|
||||
|
||||
@@ -25,6 +25,13 @@ using Common.Logging;
|
||||
|
||||
namespace Spring.Messaging.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <remarks>Exception handler when using DistributedTxMessageListenerContainer</remarks>
|
||||
public class SendToQueueDistributedTransactionExceptionHandler : AbstractSendToQueueExceptionHandler,
|
||||
IDistributedTransactionExceptionHandler
|
||||
{
|
||||
@@ -37,6 +44,19 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#region IDistributedTransactionExceptionHandler Members
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the incoming message is a poison message. This method is
|
||||
/// called before the <see cref="IMessageListener"/> is invoked.
|
||||
/// </summary>
|
||||
/// <param name="message">The incoming message.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if it is a poison message; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// The <see cref="DistributedTxMessageListenerContainer"/> will call
|
||||
/// <see cref="HandlePoisonMessage"/> if this method returns true and will
|
||||
/// then commit the distibuted transaction (removing the message from the queue).
|
||||
/// </remarks>
|
||||
public bool IsPoisonMessage(Message message)
|
||||
{
|
||||
string messageId = message.Id;
|
||||
@@ -56,11 +76,20 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the poison message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public void HandlePoisonMessage(Message message)
|
||||
{
|
||||
SendMessageToQueue(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an exception is thrown in listener processing.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
public void OnException(Exception exception, Message message)
|
||||
{
|
||||
string messageId = message.Id;
|
||||
@@ -84,6 +113,10 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message to queue.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
protected virtual void SendMessageToQueue(Message message)
|
||||
{
|
||||
MessageQueue mq = MessageQueueFactory.CreateMessageQueue(MessageQueueObjectName);
|
||||
|
||||
@@ -25,6 +25,12 @@ using Common.Logging;
|
||||
|
||||
namespace Spring.Messaging.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public class SendToQueueExceptionHandler : AbstractSendToQueueExceptionHandler, IMessageTransactionExceptionHandler
|
||||
{
|
||||
#region Logging Definition
|
||||
@@ -58,6 +64,17 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#region IMessageTransactionExceptionHandler Members
|
||||
|
||||
/// <summary>
|
||||
/// Called when an exception is thrown during listener processing under the
|
||||
/// scope of a <see cref="MessageQueueTransaction"/>.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="messageQueueTransaction">The message queue transaction.</param>
|
||||
/// <returns>
|
||||
/// An action indicating if the caller should commit or rollback the
|
||||
/// <see cref="MessageQueueTransaction"/>
|
||||
/// </returns>
|
||||
public TransactionAction OnException(Exception exception, Message message,
|
||||
MessageQueueTransaction messageQueueTransaction)
|
||||
{
|
||||
@@ -100,6 +117,13 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this exception was already processed.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the exception was already processed; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
protected virtual bool IsMessageAlreadyProcessedException(Exception exception)
|
||||
{
|
||||
if (MessageAlreadyProcessedExceptionNames != null)
|
||||
@@ -115,6 +139,12 @@ namespace Spring.Messaging.Listener
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the message to queue.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="messageQueueTransaction">The message queue transaction.</param>
|
||||
/// <returns>TransactionAction.Commit</returns>
|
||||
protected virtual TransactionAction SendMessageToQueue(Message message,
|
||||
MessageQueueTransaction messageQueueTransaction)
|
||||
{
|
||||
|
||||
@@ -241,6 +241,14 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
#region Protected Methods
|
||||
|
||||
/// <summary>
|
||||
/// Does the receive and execute using platform transaction manager.
|
||||
/// </summary>
|
||||
/// <param name="mq">The message queue.</param>
|
||||
/// <param name="status">The transactional status.</param>
|
||||
/// <returns>
|
||||
/// true if should continue peeking, false otherwise.
|
||||
/// </returns>
|
||||
protected override bool DoReceiveAndExecuteUsingPlatformTransactionManager(MessageQueue mq,
|
||||
ITransactionStatus status)
|
||||
{
|
||||
@@ -273,6 +281,12 @@ namespace Spring.Messaging.Listener
|
||||
throw new NotImplementedException("Try using NonTransactionalMessageListenerContainer instead.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the recieve and execute using message queue transaction manager.
|
||||
/// </summary>
|
||||
/// <param name="mq">The message queue.</param>
|
||||
/// <param name="status">The transactional status.</param>
|
||||
/// <returns>true if should continue peeking, false otherise</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the recieve and execute using a local MessageQueueTransaction.
|
||||
/// </summary>
|
||||
/// <param name="mq">The mqessage queue.</param>
|
||||
/// <param name="status">The transactional status.</param>
|
||||
/// <returns>true if should continue peeking, false otherwise.</returns>
|
||||
protected virtual bool DoRecieveAndExecuteUsingResourceTransactionManagerWithTxQueue(MessageQueue mq,
|
||||
ITransactionStatus status)
|
||||
{
|
||||
@@ -598,6 +617,13 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handles the transactional listener exception.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception thrown while processing the message.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="messageQueueTransaction">The message queue transaction.</param>
|
||||
/// <returns>The TransactionAction retruned by the TransactionalExceptionListener</returns>
|
||||
protected virtual TransactionAction HandleTransactionalListenerException(Exception e, Message message,
|
||||
MessageQueueTransaction
|
||||
messageQueueTransaction)
|
||||
@@ -628,14 +654,22 @@ namespace Spring.Messaging.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the transactional exception listener.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception thrown during message processing.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="messageQueueTransaction">The message queue transaction.</param>
|
||||
/// <returns>TransactionAction.Rollback if no exception handler is defined, otherwise the
|
||||
/// TransactionAction returned by the exception handler</returns>
|
||||
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
|
||||
{
|
||||
|
||||
@@ -3,6 +3,10 @@ using System.Runtime.Serialization;
|
||||
|
||||
namespace Spring.Messaging
|
||||
{
|
||||
/// <summary>
|
||||
/// Base exception class for exceptions thrown by Spring in Spring.Messaging
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class MessagingException : ApplicationException
|
||||
{
|
||||
#region Constructor (s) / Destructor
|
||||
|
||||
@@ -18,22 +18,32 @@
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Messaging;
|
||||
|
||||
namespace Spring.Messaging.Support.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IMessageConverter"/> implementation that delegates to an instance of
|
||||
/// <see cref="ActiveXMessageFormatter"/> to convert messages.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class ActiveXMessageConverter : IMessageConverter
|
||||
{
|
||||
private ActiveXMessageFormatter messageFormatter;
|
||||
private readonly ActiveXMessageFormatter messageFormatter;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ActiveXMessageConverter"/> class.
|
||||
/// </summary>
|
||||
public ActiveXMessageConverter()
|
||||
{
|
||||
messageFormatter = new ActiveXMessageFormatter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ActiveXMessageConverter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messageFormatter">The message formatter.</param>
|
||||
public ActiveXMessageConverter(ActiveXMessageFormatter messageFormatter)
|
||||
{
|
||||
this.messageFormatter = messageFormatter;
|
||||
@@ -41,6 +51,11 @@ namespace Spring.Messaging.Support.Converters
|
||||
|
||||
#region IMessageConverter Members
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given object to a Message.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to send.</param>
|
||||
/// <returns>Message to send</returns>
|
||||
public Message ToMessage(object obj)
|
||||
{
|
||||
Message m = new Message();
|
||||
@@ -49,6 +64,11 @@ namespace Spring.Messaging.Support.Converters
|
||||
return m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given message to a object.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>the object</returns>
|
||||
public object FromMessage(Message message)
|
||||
{
|
||||
message.Formatter = messageFormatter;
|
||||
@@ -59,6 +79,12 @@ namespace Spring.Messaging.Support.Converters
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new object that is a copy of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A new object that is a copy of this instance.
|
||||
/// </returns>
|
||||
public object Clone()
|
||||
{
|
||||
ActiveXMessageConverter mc = new ActiveXMessageConverter(messageFormatter.Clone() as ActiveXMessageFormatter);
|
||||
|
||||
@@ -18,44 +18,73 @@
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
using System;
|
||||
using System.Messaging;
|
||||
using System.Runtime.Serialization.Formatters;
|
||||
|
||||
namespace Spring.Messaging.Support.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IMessageConverter"/> implementation that delegates to an instance of
|
||||
/// <see cref="BinaryMessageFormatter"/> to convert messages.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class BinaryMessageConverter : IMessageConverter
|
||||
{
|
||||
private BinaryMessageFormatter binaryMessageFormatter;
|
||||
private readonly BinaryMessageFormatter binaryMessageFormatter;
|
||||
|
||||
private FormatterTypeStyle typeFormat;
|
||||
private FormatterAssemblyStyle topObjectFormat;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BinaryMessageConverter"/> class.
|
||||
/// </summary>
|
||||
public BinaryMessageConverter()
|
||||
{
|
||||
binaryMessageFormatter = new BinaryMessageFormatter();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BinaryMessageConverter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="binaryMessageFormatter">The binary message formatter.</param>
|
||||
public BinaryMessageConverter(BinaryMessageFormatter binaryMessageFormatter)
|
||||
{
|
||||
this.binaryMessageFormatter = binaryMessageFormatter;
|
||||
this.binaryMessageFormatter = binaryMessageFormatter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type format used in the <see cref="BinaryMessageFormatter"/>
|
||||
/// </summary>
|
||||
/// <value>The type format.</value>
|
||||
public FormatterTypeStyle TypeFormat
|
||||
{
|
||||
get { return typeFormat; }
|
||||
set { typeFormat = value; }
|
||||
get
|
||||
{
|
||||
return binaryMessageFormatter.TypeFormat;
|
||||
}
|
||||
set {
|
||||
binaryMessageFormatter.TypeFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the top object format used in the <see cref="BinaryMessageFormatter"/>
|
||||
/// </summary>
|
||||
/// <value>The top object format.</value>
|
||||
public FormatterAssemblyStyle TopObjectFormat
|
||||
{
|
||||
get { return topObjectFormat; }
|
||||
set { topObjectFormat = value; }
|
||||
get { return binaryMessageFormatter.TopObjectFormat; }
|
||||
set
|
||||
{
|
||||
binaryMessageFormatter.TopObjectFormat = value;
|
||||
}
|
||||
}
|
||||
|
||||
#region IMessageConverter Members
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given object to a Message using the <see cref="BinaryMessageFormatter"/>
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to send.</param>
|
||||
/// <returns>Message to send</returns>
|
||||
public Message ToMessage(object obj)
|
||||
{
|
||||
Message m = new Message();
|
||||
@@ -64,6 +93,11 @@ namespace Spring.Messaging.Support.Converters
|
||||
return m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given message to a object using the <see cref="BinaryMessageFormatter"/>
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>the object</returns>
|
||||
public object FromMessage(Message message)
|
||||
{
|
||||
message.Formatter = binaryMessageFormatter;
|
||||
@@ -74,8 +108,15 @@ namespace Spring.Messaging.Support.Converters
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new object that is a copy of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A new object that is a copy of this instance.
|
||||
/// </returns>
|
||||
public object Clone()
|
||||
{
|
||||
//takes into account TypeFormat and TypeObjectFormat
|
||||
BinaryMessageConverter mc = new BinaryMessageConverter(binaryMessageFormatter.Clone() as BinaryMessageFormatter);
|
||||
return mc;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,9 @@ using System.Messaging;
|
||||
|
||||
namespace Spring.Messaging.Support.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface specifying the contract to convert to and from <see cref="Message"/> objects.
|
||||
/// </summary>
|
||||
public interface IMessageConverter : ICloneable
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts an <see cref="XmlDocument"/> to a Message and vice-versa by using the message's
|
||||
/// body stream.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class XmlDocumentConverter : IMessageConverter
|
||||
{
|
||||
#region IMessageConverter Members
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given object to a Message.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to send.</param>
|
||||
/// <returns>Message to send</returns>
|
||||
public Message ToMessage(object obj)
|
||||
{
|
||||
XmlDocument doc = obj as XmlDocument;
|
||||
@@ -25,6 +53,11 @@ namespace Spring.Messaging.Support.Converters
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given message to a object.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>the object</returns>
|
||||
public object FromMessage(Message message)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
@@ -36,9 +69,15 @@ namespace Spring.Messaging.Support.Converters
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new object that is a copy of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A new object that is a copy of this instance.
|
||||
/// </returns>
|
||||
public object Clone()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return new XmlDocumentConverter();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -25,20 +25,36 @@ using Spring.Util;
|
||||
|
||||
namespace Spring.Messaging.Support.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IMessageConverter"/> implementation that delegates to an instance of
|
||||
/// <see cref="XmlMessageFormatter"/> to convert messages.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class XmlMessageConverter : IMessageConverter
|
||||
{
|
||||
private XmlMessageFormatter messageFormatter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="XmlMessageConverter"/> class.
|
||||
/// </summary>
|
||||
public XmlMessageConverter()
|
||||
{
|
||||
messageFormatter = new XmlMessageFormatter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="XmlMessageConverter"/> class.
|
||||
/// </summary>
|
||||
/// <param name="messageFormatter">The message formatter.</param>
|
||||
public XmlMessageConverter(XmlMessageFormatter messageFormatter)
|
||||
{
|
||||
this.messageFormatter = messageFormatter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target types used by the <see cref="XmlMessageFormatter"/>
|
||||
/// </summary>
|
||||
/// <value>The target types.</value>
|
||||
public Type[] TargetTypes
|
||||
{
|
||||
set
|
||||
@@ -49,6 +65,10 @@ namespace Spring.Messaging.Support.Converters
|
||||
get { return messageFormatter.TargetTypes; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target type names used by the <see cref="XmlMessageFormatter"/>
|
||||
/// </summary>
|
||||
/// <value>The target type names.</value>
|
||||
public string[] TargetTypeNames
|
||||
{
|
||||
set
|
||||
@@ -61,6 +81,11 @@ namespace Spring.Messaging.Support.Converters
|
||||
|
||||
#region IMessageConverter Members
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given object to a Message.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to send.</param>
|
||||
/// <returns>Message to send</returns>
|
||||
public Message ToMessage(object obj)
|
||||
{
|
||||
Message m = new Message();
|
||||
@@ -69,6 +94,11 @@ namespace Spring.Messaging.Support.Converters
|
||||
return m;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the given message to a object.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>the object</returns>
|
||||
public object FromMessage(Message message)
|
||||
{
|
||||
message.Formatter = messageFormatter;
|
||||
@@ -79,6 +109,12 @@ namespace Spring.Messaging.Support.Converters
|
||||
|
||||
#region ICloneable Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new object that is a copy of the current instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A new object that is a copy of this instance.
|
||||
/// </returns>
|
||||
public object Clone()
|
||||
{
|
||||
XmlMessageConverter mc = new XmlMessageConverter(messageFormatter.Clone() as XmlMessageFormatter);
|
||||
|
||||
@@ -28,6 +28,9 @@ using Spring.Transaction.Support;
|
||||
|
||||
namespace Spring.Messaging.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility methods to support Spring's MSMQ functionality
|
||||
/// </summary>
|
||||
public class QueueUtils
|
||||
{
|
||||
|
||||
@@ -54,6 +57,12 @@ namespace Spring.Messaging.Support
|
||||
return messageConverterObjectName;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message queue transaction from thread local storage
|
||||
/// </summary>
|
||||
/// <param name="resourceFactory">The resource factory.</param>
|
||||
/// <returns>null if not found in thread local storage</returns>
|
||||
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
|
||||
}
|
||||
|
||||
/// <summary> Callback interface for resource creation.
|
||||
/// Serving as argument for the <code>GetMessageQueueTransaction</code> method.
|
||||
/// </summary>
|
||||
public interface IResourceFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
bool SynchedLocalTransactionAllowed { get; }
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>Spring.Messaging.xml</DocumentationFile>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -52,7 +53,6 @@
|
||||
<Compile Include="Messaging\Support\Converters\MessageConverterCreatorDelegate.cs" />
|
||||
<Compile Include="Messaging\Core\DefaultMessageQueueFactory.cs" />
|
||||
<Compile Include="Messaging\Support\MessageQueueCreatorDelegate.cs" />
|
||||
<Compile Include="Messaging\Core\QueueIdentifierType.cs" />
|
||||
<Compile Include="Messaging\Core\IMessageQueueFactory.cs" />
|
||||
<Compile Include="Messaging\Core\MessagePostProcessorDelegate.cs" />
|
||||
<Compile Include="Messaging\Listener\AbstractSendToQueueExceptionHandler.cs" />
|
||||
|
||||
Reference in New Issue
Block a user