SPRNET-1233 - Support for sending to remote private queue. Clean up debug logging that would cause issues with remote private queues.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<ProjectType>Local</ProjectType>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<ProductVersion>9.0.21022</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</ProjectGuid>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -189,9 +189,7 @@
|
||||
<Compile Include="Context\IApplicationEventPublisher.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Context\IConfigurableApplicationContext.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Context\IConfigurableApplicationContext.cs" />
|
||||
<Compile Include="Context\IHierarchicalMessageSource.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#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
|
||||
|
||||
namespace Spring.Messaging.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates additional metadata information about the MessageQueue that can not be easily obtained
|
||||
/// from the MessageQueue itself.
|
||||
/// </summary>
|
||||
public class MessageQueueMetadata
|
||||
{
|
||||
private bool remoteQueue;
|
||||
|
||||
private bool remoteQueueIsTransactional;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MessageQueueMetadata"/> class.
|
||||
/// </summary>
|
||||
/// <param name="remoteQueue">if set to <c>true</c> [remote queue].</param>
|
||||
/// <param name="remoteQueueIsTransactional">if set to <c>true</c> [remote queue is transactional].</param>
|
||||
public MessageQueueMetadata(bool remoteQueue, bool remoteQueueIsTransactional)
|
||||
{
|
||||
this.remoteQueue = remoteQueue;
|
||||
this.remoteQueueIsTransactional = remoteQueueIsTransactional;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the queue is a remote queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The operations that one can perform on the MessageQueue depend on if it is local or remote, for
|
||||
/// example checking if it is transactional. This is very difficult to determine programmatically.
|
||||
/// The property was made virtual so it can be overridden to take into account custom heuristics you
|
||||
/// may want to use to determine this programmatically.
|
||||
/// </remarks>
|
||||
/// <value><c>true</c> if remote queue; otherwise, <c>false</c>.</value>
|
||||
public virtual bool RemoteQueue
|
||||
{
|
||||
get { return remoteQueue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the remote queue is transactional.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the remote queue is transactional; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public virtual bool RemoteQueueIsTransactional
|
||||
{
|
||||
get { return remoteQueueIsTransactional; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Common.Logging;
|
||||
using Spring.Context;
|
||||
using Spring.Messaging.Support;
|
||||
using Spring.Objects.Factory;
|
||||
|
||||
namespace Spring.Messaging.Core
|
||||
{
|
||||
public class MessageQueueMetadataCache : IApplicationContextAware, IInitializingObject
|
||||
{
|
||||
#region Logging Definition
|
||||
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(MessageQueueMetadataCache));
|
||||
|
||||
#endregion
|
||||
|
||||
private readonly IDictionary itemStore = new Hashtable();
|
||||
|
||||
private IConfigurableApplicationContext configurableApplicationContext;
|
||||
private IApplicationContext applicationContext;
|
||||
|
||||
|
||||
private bool isInitialized;
|
||||
|
||||
public MessageQueueMetadataCache()
|
||||
{
|
||||
}
|
||||
|
||||
public MessageQueueMetadataCache(IConfigurableApplicationContext configurableApplicationContext)
|
||||
{
|
||||
this.configurableApplicationContext = configurableApplicationContext;
|
||||
}
|
||||
|
||||
public IApplicationContext ApplicationContext
|
||||
{
|
||||
set { applicationContext = value; }
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
IDictionary messageQueueDictionary = configurableApplicationContext.GetObjectsOfType(typeof(MessageQueueFactoryObject));
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
foreach (DictionaryEntry entry in messageQueueDictionary)
|
||||
{
|
||||
MessageQueueFactoryObject mqfo = entry.Value as MessageQueueFactoryObject;
|
||||
if (mqfo != null)
|
||||
{
|
||||
if (mqfo.Path != null)
|
||||
{
|
||||
Insert(mqfo.Path,
|
||||
new MessageQueueMetadata(mqfo.RemoteQueue, mqfo.RemoteQueueIsTransactional));
|
||||
} else
|
||||
{
|
||||
#region Logging
|
||||
if (LOG.IsWarnEnabled)
|
||||
{
|
||||
LOG.Warn(
|
||||
"Path for MessageQueueFactoryObject named [" +
|
||||
mqfo.ObjectName + "] is null, so can't cache its metadata.");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
} else
|
||||
{
|
||||
// This would indicate some bug in GetObjectsOfType
|
||||
LOG.Error("Unexpected type of " + entry.Value.GetType() + " was given as candidate for caching MessageQueueMetadata.");
|
||||
}
|
||||
}
|
||||
isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
IConfigurableApplicationContext ctx = applicationContext as IConfigurableApplicationContext;
|
||||
if (ctx == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Implementations of IApplicationContext must also implement IConfigurableApplicationContext");
|
||||
}
|
||||
configurableApplicationContext = ctx;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the number of items in the cache.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
return itemStore.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Initalized
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
return isInitialized;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets a collection of all cache queue paths.
|
||||
/// </summary>
|
||||
public string[] Paths
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
string[] paths = new string[itemStore.Count];
|
||||
int count = 0;
|
||||
foreach (object path in itemStore.Keys)
|
||||
{
|
||||
paths[count] = (string) path;
|
||||
count++;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves MessageQueueMetadata from the cache.
|
||||
/// </summary>
|
||||
/// <param name="queuePath">The queue path.</param>
|
||||
/// <returns>
|
||||
/// Item for the specified <paramref name="queuePath"/>, or <c>null</c>.
|
||||
/// </returns>
|
||||
public MessageQueueMetadata Get(string queuePath)
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
return (MessageQueueMetadata) itemStore[queuePath];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified queue path from the cache
|
||||
/// </summary>
|
||||
/// <param name="queuePath">The queue path.</param>
|
||||
public void Remove(string queuePath)
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
itemStore.Remove(queuePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes collection of MessageQueueMetaCache from the cache.
|
||||
/// </summary>
|
||||
/// <param name="queuePaths">
|
||||
/// Array of MessageQueue paths to remove.
|
||||
/// </param>
|
||||
public void RemoveAll(string[] queuePaths)
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
foreach (string queuePath in queuePaths)
|
||||
{
|
||||
itemStore.Remove(queuePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all MessageQueueMetadata from the cache.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
itemStore.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Insert(string path, MessageQueueMetadata messageQueueMetadata)
|
||||
{
|
||||
lock (itemStore.SyncRoot)
|
||||
{
|
||||
itemStore[path] = messageQueueMetadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,14 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Messaging;
|
||||
using Common.Logging;
|
||||
using Spring.Context;
|
||||
using Spring.Messaging.Support;
|
||||
using Spring.Messaging.Support.Converters;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Config;
|
||||
|
||||
namespace Spring.Messaging.Core
|
||||
{
|
||||
@@ -80,10 +82,12 @@ namespace Spring.Messaging.Core
|
||||
private string messageConverterObjectName;
|
||||
|
||||
private IMessageQueueFactory messageQueueFactory;
|
||||
private IApplicationContext applicationContext;
|
||||
protected IApplicationContext applicationContext;
|
||||
|
||||
private TimeSpan timeout = MessageQueue.InfiniteTimeout;
|
||||
|
||||
private MessageQueueMetadataCache metadataCache;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
@@ -194,6 +198,16 @@ namespace Spring.Messaging.Core
|
||||
set { timeout = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the metadata cache.
|
||||
/// </summary>
|
||||
/// <value>The metadata cache.</value>
|
||||
public MessageQueueMetadataCache MetadataCache
|
||||
{
|
||||
get { return metadataCache; }
|
||||
set { metadataCache = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IApplicationContextAware Members
|
||||
@@ -263,6 +277,14 @@ namespace Spring.Messaging.Core
|
||||
{
|
||||
messageConverterObjectName = QueueUtils.RegisterDefaultMessageConverter(applicationContext);
|
||||
}
|
||||
//If it has not been set by the user explicitly, then initialize.
|
||||
if (metadataCache == null)
|
||||
{
|
||||
metadataCache = new MessageQueueMetadataCache();
|
||||
metadataCache.ApplicationContext = ApplicationContext;
|
||||
metadataCache.AfterPropertiesSet();
|
||||
metadataCache.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -432,14 +454,14 @@ namespace Spring.Messaging.Core
|
||||
/// 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>
|
||||
/// the transaction semantics of the queue definition. See <see cref="DoSendMessageQueue"/> </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)
|
||||
{
|
||||
DoSendMessageQueueTransactional(messageQueue, message);
|
||||
DoSendMessageQueue(messageQueue, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -475,52 +497,89 @@ namespace Spring.Messaging.Core
|
||||
/// </remarks>
|
||||
/// <param name="mq">The mq.</param>
|
||||
/// <param name="msg">The MSG.</param>
|
||||
protected virtual void DoSendMessageQueueTransactional(MessageQueue mq, Message msg)
|
||||
protected virtual void DoSendMessageQueue(MessageQueue mq, Message msg)
|
||||
{
|
||||
MessageQueueTransaction transactionToUse = QueueUtils.GetMessageQueueTransaction(null);
|
||||
MessageQueueMetadata mqMetadata = metadataCache.Get(mq.Path);
|
||||
if (mqMetadata != null)
|
||||
{
|
||||
if (mqMetadata.RemoteQueue)
|
||||
{
|
||||
if (mqMetadata.RemoteQueueIsTransactional)
|
||||
{
|
||||
// DefaultMessageQueue transaction is externally managed.
|
||||
DoSendMessageTransaction(mq, transactionToUse, msg);
|
||||
return;
|
||||
}
|
||||
DoSendMessageQueueNonTransactional(mq, transactionToUse, msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Handle assuming these are local queues.
|
||||
|
||||
if (mq.Transactional)
|
||||
{
|
||||
// DefaultMessageQueue transaction is externally managed.
|
||||
if (transactionToUse != null)
|
||||
DoSendMessageTransaction(mq, transactionToUse, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
DoSendMessageQueueNonTransactional(mq, transactionToUse, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the send message transaction.
|
||||
/// </summary>
|
||||
/// <param name="mq">The mq.</param>
|
||||
/// <param name="transactionToUse">The transaction to use.</param>
|
||||
/// <param name="msg">The MSG.</param>
|
||||
protected virtual void DoSendMessageTransaction(MessageQueue mq, MessageQueueTransaction transactionToUse, Message msg)
|
||||
{
|
||||
if (transactionToUse != null)
|
||||
{
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug(
|
||||
"Sending messsage using externally managed MessageQueueTransction to transactional queue [" +
|
||||
mq.QueueName + "].");
|
||||
}
|
||||
mq.Send(msg, transactionToUse);
|
||||
LOG.Debug(
|
||||
"Sending messsage using externally managed MessageQueueTransction to transactional queue with path [" + mq.Path + "].");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* From MSDN documentation
|
||||
mq.Send(msg, transactionToUse);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* From MSDN documentation
|
||||
* If a non-transactional message is sent to a transactional queue,
|
||||
* this component creates a single-message transaction for it,
|
||||
* except in the case of referencing a queue on a remote computer
|
||||
* using a direct format name. In this situation, if you do not specify a
|
||||
* transaction context when sending a message, one is not created for you
|
||||
* and the message will be sent to the dead-letter queue.*/
|
||||
LOG.Warn("Sending message using implicit single-message transaction to transactional queue [" +
|
||||
mq.QueueName + "].");
|
||||
mq.Send(msg, MessageQueueTransactionType.Single);
|
||||
}
|
||||
LOG.Warn("Sending message using implicit single-message transaction to transactional queue queue with path [" + mq.Path + "].");
|
||||
mq.Send(msg, MessageQueueTransactionType.Single);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the send message queue non transactional.
|
||||
/// </summary>
|
||||
/// <param name="mq">The mq.</param>
|
||||
/// <param name="transactionToUse">The transaction to use.</param>
|
||||
/// <param name="msg">The MSG.</param>
|
||||
protected virtual void DoSendMessageQueueNonTransactional(MessageQueue mq, MessageQueueTransaction transactionToUse, Message msg)
|
||||
{
|
||||
if (transactionToUse != null)
|
||||
{
|
||||
LOG.Warn("Thread local message transaction ignored for sending to non-transactional queue with path [" + mq.Path + "].");
|
||||
mq.Send(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transactionToUse != null)
|
||||
{
|
||||
LOG.Warn("Thread local message transaction ignored for sending to non-transactional queue.");
|
||||
mq.Send(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Sending messsage without MSMQ transaction to non-TX-QUEUE.");
|
||||
}
|
||||
//Typical case, non TLS transaction, non-tx queue.
|
||||
mq.Send(msg);
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Sending messsage without MSMQ transaction to non-transactional queue with path [" + mq.Path + "].");
|
||||
}
|
||||
//Typical case, non TLS transaction, non-tx queue.
|
||||
mq.Send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ namespace Spring.Messaging.Listener
|
||||
catch (Exception ex)
|
||||
{
|
||||
messageReceived = false;
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue = [" + mq.QueueName + "]", ex);
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue = [" + mq.Path + "]", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -440,6 +440,18 @@ namespace Spring.Messaging.Listener
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Template method that gets called right before a new message is received, i.e.
|
||||
/// messageQueue.Receive().
|
||||
/// </summary>
|
||||
/// <remarks>It allows subclasses to modify the state of the MessageQueue
|
||||
/// before receiving which maybe required when using remote queues, for example
|
||||
/// to set a MessageFormatter.</remarks>
|
||||
/// <param name="messageQueue"></param>
|
||||
protected virtual void BeforeMessageReceived(MessageQueue messageQueue)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -167,7 +167,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.QueueName + "]");
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Messaging;
|
||||
using Common.Logging;
|
||||
@@ -28,7 +27,6 @@ using Spring.Messaging.Core;
|
||||
using Spring.Messaging.Support;
|
||||
using Spring.Messaging.Support.Converters;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Support;
|
||||
using Spring.Reflection.Dynamic;
|
||||
|
||||
namespace Spring.Messaging.Listener
|
||||
@@ -451,6 +449,9 @@ namespace Spring.Messaging.Listener
|
||||
IMessageConverter converter = MessageConverter;
|
||||
if (converter != null)
|
||||
{
|
||||
// This is the default Message converter registered in QueueUtils.RegisterDefaultMessageConverter
|
||||
// and used by MessageQueueTemplate and the MessageListenerAdapter if no other Message converage is
|
||||
// set via the property MessageConverteryObjectName.
|
||||
if (messageConverterObjectName.Equals("__XmlMessageConverter__"))
|
||||
{
|
||||
return converter.ToMessage(result.ToString());
|
||||
|
||||
@@ -86,11 +86,11 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Receiving message with zero timeout for queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Receiving message with zero timeout for queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
BeforeMessageReceived(mq);
|
||||
message = mq.Receive(TimeSpan.Zero);
|
||||
}
|
||||
catch (MessageQueueException ex)
|
||||
@@ -119,7 +119,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsErrorEnabled)
|
||||
{
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.QueueName +
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.Path +
|
||||
"], closing queue and clearing connection cache.");
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -154,7 +154,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.QueueName + "]");
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsInfoEnabled)
|
||||
{
|
||||
LOG.Info("Sending message with id = [" + message.Id + "] to queue [" + mq.QueueName + "].");
|
||||
LOG.Info("Sending message with id = [" + message.Id + "] to queue [" + mq.Path + "].");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -139,7 +139,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsErrorEnabled)
|
||||
{
|
||||
LOG.Error("Could not send message with id = [" + message.Id + "] to queue [" + mq.QueueName + "].", e);
|
||||
LOG.Error("Could not send message with id = [" + message.Id + "] to queue [" + mq.Path + "].", e);
|
||||
LOG.Error("Message will not be processed. Message Body = " + message.Body);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsInfoEnabled)
|
||||
{
|
||||
LOG.Info("Sending message with id = [" + message.Id + "] to queue [" + mq.QueueName + "].");
|
||||
LOG.Info("Sending message with id = [" + message.Id + "] to queue [" + mq.Path + "].");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -169,7 +169,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsErrorEnabled)
|
||||
{
|
||||
LOG.Error("Could not send message with id = [" + message.Id + "] to queue [" + mq.QueueName + "].",e);
|
||||
LOG.Error("Could not send message with id = [" + message.Id + "] to queue [" + mq.Path + "].",e);
|
||||
LOG.Error("Message will not be processed. Message Body = " + message.Body);
|
||||
}
|
||||
|
||||
|
||||
@@ -327,7 +327,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsErrorEnabled)
|
||||
{
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.QueueName +
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.Path +
|
||||
"], closing queue and clearing connection cache.");
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -365,7 +365,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.QueueName + "]");
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -396,7 +396,7 @@ namespace Spring.Messaging.Listener
|
||||
{
|
||||
LOG.Debug(
|
||||
"Exception handler's TransactionAction has rolled back MessageQueueTransaction for queue [" +
|
||||
mq.QueueName + "]");
|
||||
mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -442,7 +442,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Started MessageQueueTransaction for queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Started MessageQueueTransaction for queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -457,7 +457,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Receiving message with zero timeout for queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Receiving message with zero timeout for queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -491,7 +491,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsErrorEnabled)
|
||||
{
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.QueueName +
|
||||
LOG.Error("Error receiving message from DefaultMessageQueue [" + mq.Path +
|
||||
"], closing queue and clearing connection cache.");
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.QueueName + "]");
|
||||
LOG.Trace("Message recieved is null from Queue = [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -529,7 +529,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.QueueName + "]");
|
||||
LOG.Debug("Received message [" + message.Id + "] on queue [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -560,7 +560,7 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
if (LOG.IsTraceEnabled)
|
||||
{
|
||||
LOG.Trace("Committed MessageQueueTransaction for queue [" + mq.QueueName + "]");
|
||||
LOG.Trace("Committed MessageQueueTransaction for queue [" + mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -579,7 +579,7 @@ namespace Spring.Messaging.Listener
|
||||
{
|
||||
LOG.Debug(
|
||||
"Exception handler's TransactionAction has rolled back MessageQueueTransaction for queue [" +
|
||||
mq.QueueName + "]");
|
||||
mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -595,7 +595,7 @@ namespace Spring.Messaging.Listener
|
||||
{
|
||||
LOG.Debug(
|
||||
"Exception handler's TransactionAction has committed MessageQueueTransaction for queue [" +
|
||||
mq.QueueName + "]");
|
||||
mq.Path + "]");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
using System;
|
||||
using System.Messaging;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects.Factory.Config;
|
||||
|
||||
namespace Spring.Messaging.Support
|
||||
@@ -33,7 +34,7 @@ namespace Spring.Messaging.Support
|
||||
/// configuration of the MessageQueue.
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack</author>
|
||||
public class MessageQueueFactoryObject : IConfigurableFactoryObject
|
||||
public class MessageQueueFactoryObject : IConfigurableFactoryObject, IObjectNameAware
|
||||
{
|
||||
// fields used in constructor
|
||||
private string path = string.Empty;
|
||||
@@ -52,6 +53,11 @@ namespace Spring.Messaging.Support
|
||||
|
||||
private MessageQueueCreatorDelegate messageCreatorDelegate;
|
||||
|
||||
private bool remoteQueue = false;
|
||||
|
||||
private bool remoteQueueIsTransactional = false;
|
||||
private string objectName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an instance of the MessageQueueCreator delegate that will be used to create the
|
||||
@@ -71,9 +77,9 @@ namespace Spring.Messaging.Support
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the path used to creat DefaultMessageQueue instance.
|
||||
/// Gets or sets the path used to create a MessageQueue instance.
|
||||
/// </summary>
|
||||
/// <value>The location of the queue referenced by the DefaultMessageQueue.</value>
|
||||
/// <value>The location of the queue.</value>
|
||||
public string Path
|
||||
{
|
||||
get { return path; }
|
||||
@@ -82,7 +88,7 @@ namespace Spring.Messaging.Support
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to create the DefaultMessageQueue instance with
|
||||
/// Gets or sets a value indicating whether to create the MessageQueue instance with
|
||||
/// exclusive read access to the first application that accesses the queue
|
||||
/// </summary>
|
||||
/// <value>
|
||||
@@ -119,7 +125,7 @@ namespace Spring.Messaging.Support
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value indicating whether to enable connection cache. The default is false, which
|
||||
/// is different than the default value when creating a DefaultMessageQueue object.
|
||||
/// is different than the default value when creating a System.Messaging.MessageQueue object.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if enable connection cache; otherwise, <c>false</c>.
|
||||
@@ -154,6 +160,34 @@ namespace Spring.Messaging.Support
|
||||
set { messageReadPropertyFilterSetDefaults = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the queue is a remote queue.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The operations that one can perform on the MessageQueue depend on if it is local or remote, for
|
||||
/// example checking if it is transactional. This is very difficult to determine programmatically.
|
||||
/// The property was made virtual so it can be overridden to take into account custom heuristics you
|
||||
/// may want to use to determine this programmatically.
|
||||
/// </remarks>
|
||||
/// <value><c>true</c> if remote queue; otherwise, <c>false</c>.</value>
|
||||
public virtual bool RemoteQueue
|
||||
{
|
||||
get { return remoteQueue; }
|
||||
set { remoteQueue = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the remote queue is transactional.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the remote queue is transactional; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public virtual bool RemoteQueueIsTransactional
|
||||
{
|
||||
get { return remoteQueueIsTransactional; }
|
||||
set { remoteQueueIsTransactional = value; }
|
||||
}
|
||||
|
||||
#region IFactoryObject Members
|
||||
|
||||
/// <summary>
|
||||
@@ -188,7 +222,7 @@ namespace Spring.Messaging.Support
|
||||
/// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates, or
|
||||
/// <see langword="null"/> if not known in advance.
|
||||
/// </summary>
|
||||
/// <value>The type DefaultMessageQueue</value>
|
||||
/// <value>The type System.Messaging.MessageQueue</value>
|
||||
public Type ObjectType
|
||||
{
|
||||
get { return typeof (MessageQueue); }
|
||||
@@ -219,5 +253,23 @@ namespace Spring.Messaging.Support
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Set the name of the object in the object factory that created this object.
|
||||
/// </summary>
|
||||
/// <value>The name of the object in the factory.</value>
|
||||
/// <remarks>
|
||||
/// <p>
|
||||
/// Invoked after population of normal object properties but before an init
|
||||
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
|
||||
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
|
||||
/// method or a custom init-method.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
public string ObjectName
|
||||
{
|
||||
set { objectName = value; }
|
||||
get { return ObjectName; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Messaging;
|
||||
using Spring.Context;
|
||||
using Spring.Messaging.Core;
|
||||
@@ -78,6 +79,7 @@ namespace Spring.Messaging.Support
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class MessageQueueResourceSynchronization : ITransactionSynchronization
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
<Link>CommonAssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Messaging\Core\MessageQueueMetadata.cs" />
|
||||
<Compile Include="Messaging\Core\MessageQueueMetadataCache.cs" />
|
||||
<Compile Include="Messaging\Support\Converters\MessageConverterCreatorDelegate.cs" />
|
||||
<Compile Include="Messaging\Core\DefaultMessageQueueFactory.cs" />
|
||||
<Compile Include="Messaging\Support\MessageQueueCreatorDelegate.cs" />
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2007 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
|
||||
|
||||
#region Imports
|
||||
|
||||
using NUnit.Framework;
|
||||
using Spring.Testing.NUnit;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Messaging.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains tests for MessageQueueTemplate
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
[TestFixture]
|
||||
public class MessageQueueMetadataCacheTests : AbstractDependencyInjectionSpringContextTests
|
||||
{
|
||||
protected override string[] ConfigLocations
|
||||
{
|
||||
get { return new[] {"assembly://Spring.Messaging.Tests/Spring.Messaging.Core/MessageQueueTemplateTests.xml"}; }
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InitialzeMessageQueueMetadata()
|
||||
{
|
||||
var cache = new MessageQueueMetadataCache(applicationContext);
|
||||
Assert.AreEqual(0, cache.Count);
|
||||
cache.Initialize();
|
||||
Assert.IsTrue(cache.Initalized);
|
||||
Assert.AreEqual(4, cache.Count);
|
||||
MessageQueueMetadata md = cache.Get(@".\Private$\testqueue");
|
||||
cache.Remove(@".\Private$\testqueue");
|
||||
Assert.AreEqual(3, cache.Count);
|
||||
Assert.IsNull(cache.Get(@".\Private$\testqueue"));
|
||||
|
||||
var paths = new[]
|
||||
{
|
||||
@".\Private$\testtxqueue",
|
||||
@"FormatName:Direct=TCP:192.168.1.105\Private$\testtxqueue",
|
||||
@"FormatName:Direct=TCP:192.168.1.105\Private$\testqueue"
|
||||
};
|
||||
|
||||
Assert.That(paths, Is.EquivalentTo(cache.Paths));
|
||||
paths = new[] {@".\Private$\testtxqueue", @"FormatName:Direct=TCP:192.168.1.105\Private$\testtxqueue"};
|
||||
cache.RemoveAll(paths);
|
||||
Assert.AreEqual(1, cache.Count);
|
||||
cache.Clear();
|
||||
Assert.AreEqual(0, cache.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
|
||||
<object id='testqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testqueue'/>
|
||||
<property name='DenySharedReceive' value='true'/>
|
||||
<property name='AccessMode' value='Receive'/>
|
||||
<property name='EnableCache' value='true'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id='testtxqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testtxqueue'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyTxLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
|
||||
<object id='testremotetxqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='FormatName:Direct=TCP:192.168.1.105\Private$\testtxqueue'/>
|
||||
<property name='RemoteQueue' value="true"/>
|
||||
<property name="RemoteQueueIsTransactional" value="true"/>
|
||||
</object>
|
||||
|
||||
<object id='testremotequeue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='FormatName:Direct=TCP:192.168.1.105\Private$\testqueue'/>
|
||||
<property name='RemoteQueue' value="true"/>
|
||||
</object>
|
||||
|
||||
|
||||
|
||||
<object id='msqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testqueue'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
</objects>
|
||||
@@ -37,7 +37,7 @@ using Spring.Util;
|
||||
namespace Spring.Messaging.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains tests for
|
||||
/// This class contains tests for MessageQueueTemplate
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
[TestFixture]
|
||||
@@ -102,6 +102,8 @@ namespace Spring.Messaging.Core
|
||||
mqt.MessageQueueFactory.RegisterMessageQueue("fooQueueDefinition", sc.CreateQueue );
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
public class SimpleCreator
|
||||
{
|
||||
@@ -139,16 +141,6 @@ namespace Spring.Messaging.Core
|
||||
Assert.AreEqual(q.DefaultMessageQueue, q.MessageQueueFactory.CreateMessageQueue(q.DefaultMessageQueueObjectName));
|
||||
}
|
||||
|
||||
[Test, Ignore("obsolete test. If necessary, registers a default message converter on first use")]
|
||||
[ExpectedException(typeof (InvalidOperationException),
|
||||
ExpectedMessage = "No MessageConverter registered. Check configuration of MessageQueueTemplate.")]
|
||||
public void MessageConverterNotRegistered()
|
||||
{
|
||||
MessageQueueTemplate q = applicationContext["queue-noconverter"] as MessageQueueTemplate;
|
||||
Assert.IsNotNull(q);
|
||||
IMessageConverter c = q.MessageConverter;
|
||||
}
|
||||
|
||||
#region Integration Tests - to be moved to another test assembly
|
||||
|
||||
[Test]
|
||||
@@ -160,6 +152,15 @@ namespace Spring.Messaging.Core
|
||||
ReceiveHelloWorld(null,q,1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SendAndReceiveNonTransactionalRemotePrivateQueue()
|
||||
{
|
||||
MessageQueueTemplate q = applicationContext["queueTemplate-remote"] as MessageQueueTemplate;
|
||||
Assert.IsNotNull(q);
|
||||
q.ConvertAndSend("Hello World 1");
|
||||
//ReceiveHelloWorld(null, q, 1);
|
||||
}
|
||||
|
||||
private static void ReceiveHelloWorld(string messageQueueObjectName, MessageQueueTemplate q, int index)
|
||||
{
|
||||
object o = null;
|
||||
@@ -201,6 +202,7 @@ namespace Spring.Messaging.Core
|
||||
Receive(null,q);
|
||||
}
|
||||
|
||||
|
||||
private static void SendAndReceive(MessageQueueTemplate q)
|
||||
{
|
||||
SendAndReceive(null, q);
|
||||
@@ -255,7 +257,31 @@ namespace Spring.Messaging.Core
|
||||
|
||||
#endregion
|
||||
|
||||
[Test, Ignore("What's the purpose of this test?")]
|
||||
protected override string[] ConfigLocations
|
||||
{
|
||||
get { return new string[] { "assembly://Spring.Messaging.Tests/Spring.Messaging.Core/MessageQueueTemplateTests.xml" }; }
|
||||
}
|
||||
|
||||
|
||||
#region Some simple driver code for debugging
|
||||
public void SimpleRemoteConsumption()
|
||||
{
|
||||
string connectionWorking = @"FormatName:Direct=OS:MARKT60\Private$\testqueue";
|
||||
|
||||
//TCP:IP doesn't work...
|
||||
MessageQueue rmQ = new MessageQueue(@"FormatName:Direct=TCP:192.168.1.105\Private$\testqueue");
|
||||
|
||||
rmQ.Send("Hello Simple");
|
||||
|
||||
rmQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });
|
||||
|
||||
Message msg = rmQ.Receive();
|
||||
|
||||
Assert.IsNotNull(msg);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void GetAllFromQueue()
|
||||
{
|
||||
MessageQueueTemplate q = applicationContext["queue"] as MessageQueueTemplate;
|
||||
@@ -265,9 +291,7 @@ namespace Spring.Messaging.Core
|
||||
Console.WriteLine(q.ReceiveAndConvert());
|
||||
}
|
||||
}
|
||||
protected override string[] ConfigLocations
|
||||
{
|
||||
get { return new string[] {"assembly://Spring.Messaging.Tests/Spring.Messaging.Core/MessageQueueTemplateTests.xml"}; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,18 @@
|
||||
</property>
|
||||
</object>
|
||||
|
||||
|
||||
<object id='msqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testqueue'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
<object id='testremotetxqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='FormatName:Direct=OS:MARKT60\Private$\testqueue'/>
|
||||
<property name='RemoteQueue' value="true"/>
|
||||
<property name="RemoteQueueIsTransactional" value="true"/>
|
||||
</object>
|
||||
|
||||
<object id='testremotequeue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='FormatName:Direct=OS:MARKT60\Private$\testqueue'/>
|
||||
<property name='RemoteQueue' value="true"/>
|
||||
</object>
|
||||
|
||||
|
||||
<object id="queue" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="testtxqueue"/>
|
||||
<property name="MessageConverterObjectName" value="messageConverter"/>
|
||||
@@ -49,9 +51,32 @@
|
||||
<property name="MessageConverterObjectName" value="messageConverter"/>
|
||||
</object>
|
||||
|
||||
|
||||
<object id="queueTemplate-remote" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="testremotequeue"/>
|
||||
<property name="MessageConverterObjectName" value="messageConverter"/>
|
||||
</object>
|
||||
|
||||
|
||||
<object id="queueTemplate-remote-tx" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="testremotetxqueue"/>
|
||||
<property name="MessageConverterObjectName" value="messageConverter"/>
|
||||
</object>
|
||||
|
||||
|
||||
<object id="messageConverter" type="Spring.Messaging.Support.Converters.XmlMessageConverter, Spring.Messaging"
|
||||
singleton="false">
|
||||
<property name="TargetTypes" value="System.String"/>
|
||||
</object>
|
||||
|
||||
|
||||
|
||||
<object id='msqueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testqueue'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
</objects>
|
||||
@@ -84,15 +84,19 @@ namespace Spring.Messaging.Listener
|
||||
[Test]
|
||||
public void SendAndAsyncReceive()
|
||||
{
|
||||
MessageQueueTemplate q = applicationContext["testQueueTemplate"] as MessageQueueTemplate;
|
||||
//MessageQueueTemplate q = applicationContext["testQueueTemplate"] as MessageQueueTemplate;
|
||||
MessageQueueTemplate q = applicationContext["testRemoteTemplate"] as MessageQueueTemplate;
|
||||
Assert.IsNotNull(q);
|
||||
|
||||
/*
|
||||
q.ConvertAndSend("Hello World 1");
|
||||
q.ConvertAndSend("Hello World 2");
|
||||
q.ConvertAndSend("Hello World 3");
|
||||
q.ConvertAndSend("Hello World 4");
|
||||
q.ConvertAndSend("Hello World 5");
|
||||
*/
|
||||
|
||||
|
||||
Assert.AreEqual(0, listener.MessageCount);
|
||||
|
||||
container.Start();
|
||||
@@ -104,6 +108,7 @@ namespace Spring.Messaging.Listener
|
||||
container.Stop();
|
||||
container.Shutdown();
|
||||
Thread.Sleep(2500);
|
||||
|
||||
}
|
||||
|
||||
protected override string[] ConfigLocations
|
||||
|
||||
@@ -33,8 +33,18 @@
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id='testremotequeue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='FormatName:Direct=OS:MARKT60\Private$\testqueue'/>
|
||||
<property name='RemoteQueue' value="true"/>
|
||||
</object>
|
||||
|
||||
<object id="testRemoteTemplate" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="testremotequeue"/>
|
||||
<property name="MessageConverterObjectName" value="messageConverter"/>
|
||||
</object>
|
||||
|
||||
<object id="testQueueTemplate" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="MessageQueueObjectName" value="msmqTestQueue"/>
|
||||
<property name="DefaultMessageQueueObjectName" value="msmqTestQueue"/>
|
||||
<property name="MessageConverterObjectName" value="messageConverter"/>
|
||||
</object>
|
||||
|
||||
@@ -44,7 +54,7 @@
|
||||
</object>
|
||||
|
||||
<object id="nonTransactionalMessageListenerContainer" type="Spring.Messaging.Listener.NonTransactionalMessageListenerContainer, Spring.Messaging">
|
||||
<property name="MessageQueueObjectName" value="msmqTestQueue"/>
|
||||
<property name="MessageQueueObjectName" value="testremotequeue"/>
|
||||
<property name="MaxConcurrentListeners" value="2"/>
|
||||
<property name="ListenerTimeLimit" value="20s"/>
|
||||
<property name="MessageListener" ref="messageListenerAdapter"/>
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
private string stateVariable;
|
||||
|
||||
public SimpleHandler()
|
||||
{
|
||||
this.stateVariable = "hello";
|
||||
}
|
||||
public SimpleHandler(string stateVariable)
|
||||
{
|
||||
this.stateVariable = stateVariable;
|
||||
|
||||
@@ -80,11 +80,13 @@
|
||||
<EmbeddedResource Include="Messaging\queue-context.xml" />
|
||||
<EmbeddedResource Include="Messaging\Core\MessageQueueTemplateTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\DistributedTxMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Core\MessageQueueMetadataCacheTests.xml" />
|
||||
<Content Include="Spring.Messaging.Tests.dll.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Messaging\Core\MessageQueueMetadataCacheTests.cs" />
|
||||
<Compile Include="Messaging\Core\ThreadingTests.cs" />
|
||||
<Compile Include="Messaging\Listener\DistributedTxMessageListenerContainerTests.cs" />
|
||||
<Compile Include="Messaging\Listener\LoggingExceptionHandler.cs" />
|
||||
|
||||
Reference in New Issue
Block a user