NMS development
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// MessageProducer decorator that adapts specific settings
|
||||
@@ -31,7 +31,7 @@ namespace Spring.Messaging.Nms.Connection
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class CachedMessageProducer : IMessageProducer
|
||||
{
|
||||
private IMessageProducer target;
|
||||
private readonly IMessageProducer target;
|
||||
|
||||
private bool disableMessageID;
|
||||
|
||||
@@ -51,92 +51,171 @@ namespace Spring.Messaging.Nms.Connection
|
||||
private TimeSpan timeToLive;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CachedMessageProducer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="target">The target.</param>
|
||||
public CachedMessageProducer(IMessageProducer target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target MessageProducer, the procder we are 'wrapping'
|
||||
/// </summary>
|
||||
/// <value>The target MessageProducer.</value>
|
||||
public IMessageProducer Target
|
||||
{
|
||||
get { return target; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public void Send(IMessage message)
|
||||
{
|
||||
target.Send(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to send.</param>
|
||||
/// <param name="persistent">if set to <c>true</c> use persistent QOS.</param>
|
||||
/// <param name="priority">The message priority.</param>
|
||||
/// <param name="timeToLive">The time to live.</param>
|
||||
public void Send(IMessage message, bool persistent, byte priority, TimeSpan timeToLive)
|
||||
{
|
||||
target.Send(message, persistent, priority, timeToLive);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to the specified destination.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
public void Send(IDestination destination, IMessage message)
|
||||
{
|
||||
target.Send(destination, message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message the specified destination.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination.</param>
|
||||
/// <param name="message">The message to send.</param>
|
||||
/// <param name="persistent">if set to <c>true</c> use persistent QOS.</param>
|
||||
/// <param name="priority">The priority.</param>
|
||||
/// <param name="timeToLive">The time to live.</param>
|
||||
public void Send(IDestination destination, IMessage message, bool persistent, byte priority, TimeSpan timeToLive)
|
||||
{
|
||||
target.Send(destination, message, persistent, priority, timeToLive);
|
||||
}
|
||||
|
||||
#region Odd Message Creationg Methods on IMessageProducer - not in-line with JMS APIs.
|
||||
/// <summary>
|
||||
/// Creates the message.
|
||||
/// </summary>
|
||||
/// <returns>A new message</returns>
|
||||
public IMessage CreateMessage()
|
||||
{
|
||||
return target.CreateMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the text message.
|
||||
/// </summary>
|
||||
/// <returns>A new text message.</returns>
|
||||
public ITextMessage CreateTextMessage()
|
||||
{
|
||||
return target.CreateTextMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the text message.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <returns>A texst message with the given text.</returns>
|
||||
public ITextMessage CreateTextMessage(string text)
|
||||
{
|
||||
return target.CreateTextMessage(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the map message.
|
||||
/// </summary>
|
||||
/// <returns>a new map message.</returns>
|
||||
public IMapMessage CreateMapMessage()
|
||||
{
|
||||
return target.CreateMapMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the object message.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <returns>A new object message with the given body.</returns>
|
||||
public IObjectMessage CreateObjectMessage(object body)
|
||||
{
|
||||
return target.CreateObjectMessage(body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the bytes message.
|
||||
/// </summary>
|
||||
/// <returns>A new bytes message.</returns>
|
||||
public IBytesMessage CreateBytesMessage()
|
||||
{
|
||||
return target.CreateBytesMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the bytes message.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <returns>A new bytes message with the given body.</returns>
|
||||
public IBytesMessage CreateBytesMessage(byte[] body)
|
||||
{
|
||||
return target.CreateBytesMessage(body);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="CachedMessageProducer"/> uses a persistent QOS
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if persistent; otherwise, <c>false</c>.</value>
|
||||
public bool Persistent
|
||||
{
|
||||
get { return persistent; }
|
||||
set { persistent = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time to live value for messages sent with this producer.
|
||||
/// </summary>
|
||||
/// <value>The time to live.</value>
|
||||
public TimeSpan TimeToLive
|
||||
{
|
||||
get { return timeToLive; }
|
||||
set { timeToLive = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the priority of messages sent with this producer.
|
||||
/// </summary>
|
||||
/// <value>The priority.</value>
|
||||
public byte Priority
|
||||
{
|
||||
get { return priority; }
|
||||
set { priority = value;}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether disable setting of the message ID property.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if disable message ID setting; otherwise, <c>false</c>.</value>
|
||||
public bool DisableMessageID
|
||||
{
|
||||
get
|
||||
@@ -153,6 +232,12 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether disable setting the message timestamp property.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if disable message timestamp; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool DisableMessageTimestamp
|
||||
{
|
||||
get
|
||||
@@ -169,6 +254,9 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset properties.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// It's a cached MessageProducer... reset properties only.
|
||||
|
||||
@@ -24,10 +24,10 @@ using Common.Logging;
|
||||
using Spring.Collections;
|
||||
using IQueue=Apache.NMS.IQueue;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper for ISession that caches producers and registers itself as available
|
||||
/// Wrapper for Session that caches producers and registers itself as available
|
||||
/// to the session cache when being closed. Generally used for testing purposes or
|
||||
/// if need to get at the wrapped Session object via the TargetSession property (for
|
||||
/// vendor specific methods).
|
||||
@@ -192,101 +192,194 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
|
||||
#region Pass through implementations
|
||||
/// <summary>
|
||||
/// Creates the consumer.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination.</param>
|
||||
/// <returns></returns>
|
||||
public IMessageConsumer CreateConsumer(IDestination destination)
|
||||
{
|
||||
return target.CreateConsumer(destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the consumer.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination.</param>
|
||||
/// <param name="selector">The selector.</param>
|
||||
/// <returns></returns>
|
||||
public IMessageConsumer CreateConsumer(IDestination destination, string selector)
|
||||
{
|
||||
return target.CreateConsumer(destination, selector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the consumer.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination.</param>
|
||||
/// <param name="selector">The selector.</param>
|
||||
/// <param name="noLocal">if set to <c>true</c> [no local].</param>
|
||||
/// <returns></returns>
|
||||
public IMessageConsumer CreateConsumer(IDestination destination, string selector, bool noLocal)
|
||||
{
|
||||
return target.CreateConsumer(destination, selector, noLocal);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the durable consumer.
|
||||
/// </summary>
|
||||
/// <param name="destination">The destination.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="selector">The selector.</param>
|
||||
/// <param name="noLocal">if set to <c>true</c> [no local].</param>
|
||||
/// <returns></returns>
|
||||
public IMessageConsumer CreateDurableConsumer(ITopic destination, string name, string selector, bool noLocal)
|
||||
{
|
||||
return target.CreateDurableConsumer(destination, name, selector, noLocal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the queue.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns></returns>
|
||||
public IQueue GetQueue(string name)
|
||||
{
|
||||
return target.GetQueue(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the topic.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns></returns>
|
||||
public ITopic GetTopic(string name)
|
||||
{
|
||||
return target.GetTopic(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the temporary queue.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ITemporaryQueue CreateTemporaryQueue()
|
||||
{
|
||||
return target.CreateTemporaryQueue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the temporary topic.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ITemporaryTopic CreateTemporaryTopic()
|
||||
{
|
||||
return target.CreateTemporaryTopic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the message.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IMessage CreateMessage()
|
||||
{
|
||||
return target.CreateMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the text message.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ITextMessage CreateTextMessage()
|
||||
{
|
||||
return target.CreateTextMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the text message.
|
||||
/// </summary>
|
||||
/// <param name="text">The text.</param>
|
||||
/// <returns></returns>
|
||||
public ITextMessage CreateTextMessage(string text)
|
||||
{
|
||||
return target.CreateTextMessage(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the map message.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IMapMessage CreateMapMessage()
|
||||
{
|
||||
return target.CreateMapMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the object message.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <returns></returns>
|
||||
public IObjectMessage CreateObjectMessage(object body)
|
||||
{
|
||||
return target.CreateObjectMessage(body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the bytes message.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IBytesMessage CreateBytesMessage()
|
||||
{
|
||||
return target.CreateBytesMessage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the bytes message.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <returns></returns>
|
||||
public IBytesMessage CreateBytesMessage(byte[] body)
|
||||
{
|
||||
return target.CreateBytesMessage(body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commits this instance.
|
||||
/// </summary>
|
||||
public void Commit()
|
||||
{
|
||||
target.Commit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rollbacks this instance.
|
||||
/// </summary>
|
||||
public void Rollback()
|
||||
{
|
||||
target.Rollback();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="CachedSession"/> is transacted.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if transacted; otherwise, <c>false</c>.</value>
|
||||
public bool Transacted
|
||||
{
|
||||
get { return target.Transacted; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the acknowledgement mode.
|
||||
/// </summary>
|
||||
/// <value>The acknowledgement mode.</value>
|
||||
public AcknowledgementMode AcknowledgementMode
|
||||
{
|
||||
get { return target.AcknowledgementMode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call dispose on the target.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
target.Dispose();
|
||||
|
||||
@@ -25,11 +25,11 @@ using Spring.Collections;
|
||||
using Spring.Util;
|
||||
using IQueue=Apache.NMS.IQueue;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="SingleConnectionFactory"/> subclass that adds
|
||||
/// ISession and IMessageProducer caching. This ConnectionFactory
|
||||
/// Session and MessageProducer caching. This ConnectionFactory
|
||||
/// also switches the ReconnectOnException property to true
|
||||
/// by default, allowing for automatic recovery of the underlying
|
||||
/// Connection.
|
||||
@@ -169,6 +169,14 @@ namespace Spring.Messaging.Nms.Connection
|
||||
return session;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the given Session so that it delegates every method call to the target session but
|
||||
/// adapts close calls. This is useful for allowing application code to
|
||||
/// handle a special framework Session just like an ordinary Session.
|
||||
/// </summary>
|
||||
/// <param name="targetSession">The original Session to wrap.</param>
|
||||
/// <param name="sessionList">The List of cached Sessions that the given Session belongs to.</param>
|
||||
/// <returns>The wrapped Session</returns>
|
||||
protected virtual ISession GetCachedSessionWrapper(ISession targetSession, LinkedList sessionList)
|
||||
{
|
||||
return new CachedSession(targetSession, sessionList, SessionCacheSize, CacheProducers);
|
||||
|
||||
@@ -23,7 +23,7 @@ using System;
|
||||
using System.Collections;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of Spring IExceptionListener interface that supports
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
using Common.Logging;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Spring.Transaction.Support;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary> Helper class for obtaining transactional NMS resources
|
||||
/// for a given IConnectionFactory.
|
||||
///
|
||||
/// for a given ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
@@ -40,19 +40,76 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary> Obtain a NMS ISession that is synchronized with the current transaction, if any.</summary>
|
||||
/// <param name="cf">the IConnectionFactory to obtain a ISession for
|
||||
/// <summary>
|
||||
/// Releases the given connection, stopping it (if necessary) and eventually closing it.
|
||||
/// </summary>
|
||||
/// <remarks>Checks <see cref="ISmartConnectionFactory.ShouldStop"/>, if available.
|
||||
/// This is essentially a more sophisticated version of
|
||||
/// <see cref="NmsUtils.CloseConnection(IConnection, bool)"/>
|
||||
/// </remarks>
|
||||
/// <param name="connection">The connection to release. (if this is <code>null</code>, the call will be ignored)</param>
|
||||
/// <param name="cf">The ConnectionFactory that the Connection was obtained from. (may be <code>null</code>)</param>
|
||||
/// <param name="started">whether the Connection might have been started by the application.</param>
|
||||
public static void ReleaseConnection(IConnection connection, IConnectionFactory cf, bool started)
|
||||
{
|
||||
if (connection == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (started && cf is ISmartConnectionFactory && ((ISmartConnectionFactory)cf).ShouldStop(connection))
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Debug("Could not stop NMS Connection before closing it", ex);
|
||||
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
connection.Close();
|
||||
} catch (Exception ex)
|
||||
{
|
||||
LOG.Debug("Could not close NMS Connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given JMS Session is transactional, that is,
|
||||
/// bound to the current thread by Spring's transaction facilities.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to check.</param>
|
||||
/// <param name="cf">The ConnectionFactory that the Session originated from</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if is session transactional, bound to current thread; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public static bool IsSessionTransactional(ISession session, IConnectionFactory cf)
|
||||
{
|
||||
if (session == null || cf == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NmsResourceHolder resourceHolder = (NmsResourceHolder) TransactionSynchronizationManager.GetResource(cf);
|
||||
return (resourceHolder != null && resourceHolder.ContainsSession(session));
|
||||
}
|
||||
|
||||
/// <summary> Obtain a NMS Session that is synchronized with the current transaction, if any.</summary>
|
||||
/// <param name="cf">the ConnectionFactory to obtain a Session for
|
||||
/// </param>
|
||||
/// <param name="existingCon">the existing NMS IConnection to obtain a ISession for
|
||||
/// <param name="existingCon">the existing NMS Connection to obtain a Session for
|
||||
/// (may be <code>null</code>)
|
||||
/// </param>
|
||||
/// <param name="synchedLocalTransactionAllowed">whether to allow for a local NMS transaction
|
||||
/// that is synchronized with a Spring-managed transaction (where the main transaction
|
||||
/// might be a ADO.NET-based one for a specific DataSource, for example), with the NMS
|
||||
/// transaction committing right after the main transaction. If not allowed, the given
|
||||
/// IConnectionFactory needs to handle transaction enlistment underneath the covers.
|
||||
/// ConnectionFactory needs to handle transaction enlistment underneath the covers.
|
||||
/// </param>
|
||||
/// <returns> the transactional ISession, or <code>null</code> if none found
|
||||
/// <returns> the transactional Session, or <code>null</code> if none found
|
||||
/// </returns>
|
||||
/// <throws> NMSException in case of NMS failure </throws>
|
||||
public static ISession GetTransactionalSession(IConnectionFactory cf, IConnection existingCon,
|
||||
@@ -61,20 +118,24 @@ namespace Spring.Messaging.Nms.Connection
|
||||
return
|
||||
DoGetTransactionalSession(cf,
|
||||
new AnonymousClassResourceFactory(existingCon, cf,
|
||||
synchedLocalTransactionAllowed));
|
||||
synchedLocalTransactionAllowed), true);
|
||||
}
|
||||
|
||||
/// <summary> Obtain a NMS ISession that is synchronized with the current transaction, if any.</summary>
|
||||
/// <summary>
|
||||
/// Obtain a NMS Session that is synchronized with the current transaction, if any.
|
||||
/// </summary>
|
||||
/// <param name="resourceKey">the TransactionSynchronizationManager key to bind to
|
||||
/// (usually the IConnectionFactory)
|
||||
/// </param>
|
||||
/// (usually the ConnectionFactory)</param>
|
||||
/// <param name="resourceFactory">the ResourceFactory to use for extracting or creating
|
||||
/// NMS resources
|
||||
/// </param>
|
||||
/// <returns> the transactional ISession, or <code>null</code> if none found
|
||||
/// NMS resources</param>
|
||||
/// <param name="startConnection">whether the underlying Connection approach should be
|
||||
/// started in order to allow for receiving messages. Note that a reused Connection
|
||||
/// may already have been started before, even if this flag is <code>false</code>.</param>
|
||||
/// <returns>
|
||||
/// the transactional Session, or <code>null</code> if none found
|
||||
/// </returns>
|
||||
/// <throws>NMSException in case of NMS failure </throws>
|
||||
public static ISession DoGetTransactionalSession(Object resourceKey, ResourceFactory resourceFactory)
|
||||
public static ISession DoGetTransactionalSession(Object resourceKey, ResourceFactory resourceFactory, bool startConnection)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(resourceKey, "Resource key must not be null");
|
||||
AssertUtils.ArgumentNotNull(resourceKey, "ResourceFactory must not be null");
|
||||
@@ -83,22 +144,31 @@ namespace Spring.Messaging.Nms.Connection
|
||||
(NmsResourceHolder)TransactionSynchronizationManager.GetResource(resourceKey);
|
||||
if (resourceHolder != null)
|
||||
{
|
||||
ISession rssession = resourceFactory.GetSession(resourceHolder);
|
||||
if (rssession != null || resourceHolder.Frozen)
|
||||
ISession rhSession = resourceFactory.GetSession(resourceHolder);
|
||||
if (rhSession != null)
|
||||
{
|
||||
return rssession;
|
||||
if (startConnection)
|
||||
{
|
||||
IConnection conn = resourceFactory.GetConnection(resourceHolder);
|
||||
if (conn != null)
|
||||
{
|
||||
conn.Start();
|
||||
}
|
||||
}
|
||||
return rhSession;
|
||||
}
|
||||
}
|
||||
if (!TransactionSynchronizationManager.SynchronizationActive)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
NmsResourceHolder conHolderToUse = resourceHolder;
|
||||
if (conHolderToUse == null)
|
||||
NmsResourceHolder resourceHolderToUse = resourceHolder;
|
||||
if (resourceHolderToUse == null)
|
||||
{
|
||||
conHolderToUse = new NmsResourceHolder();
|
||||
resourceHolderToUse = new NmsResourceHolder();
|
||||
}
|
||||
IConnection con = resourceFactory.GetConnection(conHolderToUse);
|
||||
|
||||
IConnection con = resourceFactory.GetConnection(resourceHolderToUse);
|
||||
ISession session = null;
|
||||
try
|
||||
{
|
||||
@@ -106,11 +176,11 @@ namespace Spring.Messaging.Nms.Connection
|
||||
if (!isExistingCon)
|
||||
{
|
||||
con = resourceFactory.CreateConnection();
|
||||
conHolderToUse.AddConnection(con);
|
||||
resourceHolderToUse.AddConnection(con);
|
||||
}
|
||||
session = resourceFactory.CreateSession(con);
|
||||
conHolderToUse.AddSession(session, con);
|
||||
if (!isExistingCon)
|
||||
resourceHolderToUse.AddSession(session, con);
|
||||
if (startConnection)
|
||||
{
|
||||
con.Start();
|
||||
}
|
||||
@@ -141,55 +211,17 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
throw;
|
||||
}
|
||||
if (conHolderToUse != resourceHolder)
|
||||
if (resourceHolderToUse != resourceHolder)
|
||||
{
|
||||
TransactionSynchronizationManager.RegisterSynchronization(
|
||||
new NmsResourceSynchronization(resourceKey, conHolderToUse,
|
||||
new NmsResourceSynchronization(resourceKey, resourceHolderToUse,
|
||||
resourceFactory.SynchedLocalTransactionAllowed));
|
||||
conHolderToUse.SynchronizedWithTransaction = true;
|
||||
TransactionSynchronizationManager.BindResource(resourceKey, conHolderToUse);
|
||||
resourceHolderToUse.SynchronizedWithTransaction = true;
|
||||
TransactionSynchronizationManager.BindResource(resourceKey, resourceHolderToUse);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
public static void ReleaseConnection(IConnection connection, IConnectionFactory cf, bool started)
|
||||
{
|
||||
if (connection == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (started && cf is ISmartConnectionFactory && ((ISmartConnectionFactory)cf).ShouldStop(connection))
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.Stop();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Debug("Could not stop NMS IConnection before closing it", ex);
|
||||
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
connection.Close();
|
||||
} catch (Exception ex)
|
||||
{
|
||||
LOG.Debug("Could not close NMS Connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsSessionTransactional(ISession session, IConnectionFactory cf)
|
||||
{
|
||||
if (session == null || cf == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NmsResourceHolder resourceHolder = (NmsResourceHolder) TransactionSynchronizationManager.GetResource(cf);
|
||||
return (resourceHolder != null && resourceHolder.ContainsSession(session));
|
||||
}
|
||||
|
||||
#region ResourceFactory helper classes
|
||||
|
||||
private class AnonymousClassResourceFactory : ResourceFactory
|
||||
@@ -253,32 +285,32 @@ namespace Spring.Messaging.Nms.Connection
|
||||
/// </summary>
|
||||
public interface ResourceFactory
|
||||
{
|
||||
/// <summary> Fetch an appropriate ISession from the given NmsResourceHolder.</summary>
|
||||
/// <summary> Fetch an appropriate Session from the given NmsResourceHolder.</summary>
|
||||
/// <param name="holder">the NmsResourceHolder
|
||||
/// </param>
|
||||
/// <returns> an appropriate ISession fetched from the holder,
|
||||
/// <returns> an appropriate Session fetched from the holder,
|
||||
/// or <code>null</code> if none found
|
||||
/// </returns>
|
||||
ISession GetSession(NmsResourceHolder holder);
|
||||
|
||||
/// <summary> Fetch an appropriate IConnection from the given NmsResourceHolder.</summary>
|
||||
/// <summary> Fetch an appropriate Connection from the given NmsResourceHolder.</summary>
|
||||
/// <param name="holder">the NmsResourceHolder
|
||||
/// </param>
|
||||
/// <returns> an appropriate IConnection fetched from the holder,
|
||||
/// <returns> an appropriate Connection fetched from the holder,
|
||||
/// or <code>null</code> if none found
|
||||
/// </returns>
|
||||
IConnection GetConnection(NmsResourceHolder holder);
|
||||
|
||||
/// <summary> Create a new NMS IConnection for registration with a NmsResourceHolder.</summary>
|
||||
/// <returns> the new NMS IConnection
|
||||
/// <summary> Create a new NMS Connection for registration with a NmsResourceHolder.</summary>
|
||||
/// <returns> the new NMS Connection
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
IConnection CreateConnection();
|
||||
|
||||
/// <summary> Create a new NMS ISession for registration with a NmsResourceHolder.</summary>
|
||||
/// <param name="con">the NMS IConnection to create a ISession for
|
||||
/// <param name="con">the NMS Connection to create a ISession for
|
||||
/// </param>
|
||||
/// <returns> the new NMS ISession
|
||||
/// <returns> the new NMS Session
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
ISession CreateSession(IConnection con);
|
||||
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// Subinterface of ISession to be implemented by
|
||||
/// implementations that wrap an ISession to provide added
|
||||
/// Subinterface of Session to be implemented by
|
||||
/// implementations that wrap an Session to provide added
|
||||
/// functionality. Allows access to the the underlying target Session.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension of the <code>IConnectionFactory</code> interface,
|
||||
/// Extension of the <code>ConnectionFactory</code> interface,
|
||||
/// indicating how to release Connections obtained from it.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
|
||||
@@ -26,11 +26,11 @@ using Spring.Transaction.Support;
|
||||
using Spring.Util;
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary> IConnection holder, wrapping a NMS IConnection and a NMS ISession.
|
||||
/// <summary>Connection holder, wrapping a NMS Connection and a NMS Session.
|
||||
/// NmsTransactionManager binds instances of this class to the thread,
|
||||
/// for a given NMS IConnectionFactory.
|
||||
/// for a given NMS ConnectionFactory.
|
||||
///
|
||||
/// <p>Note: This is an SPI class, not intended to be used by applications.</p>
|
||||
///
|
||||
@@ -92,17 +92,23 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
|
||||
/// <summary> Create a new NmsResourceHolder for the given NMS resources.</summary>
|
||||
/// <param name="connection">the NMS IConnection
|
||||
/// <param name="connection">the NMS Connection
|
||||
/// </param>
|
||||
/// <param name="session">the NMS ISession
|
||||
/// <param name="session">the NMS Session
|
||||
/// </param>
|
||||
public NmsResourceHolder(Apache.NMS.IConnection connection, ISession session)
|
||||
public NmsResourceHolder(IConnection connection, ISession session)
|
||||
{
|
||||
AddConnection(connection);
|
||||
AddSession(session, connection);
|
||||
this.frozen = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NmsResourceHolder"/> class.
|
||||
/// </summary>
|
||||
/// <param name="connectionFactory">The connection factory.</param>
|
||||
/// <param name="connection">The connection.</param>
|
||||
/// <param name="session">The session.</param>
|
||||
public NmsResourceHolder(IConnectionFactory connectionFactory, IConnection connection, ISession session)
|
||||
{
|
||||
this.connectionFactory = connectionFactory;
|
||||
@@ -114,6 +120,12 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="NmsResourceHolder"/> is frozen, namely that
|
||||
/// additional resources can be registered with the holder. If using any of the constructors with
|
||||
/// a Session, the holder will be set to the frozen state.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if frozen; otherwise, <c>false</c>.</value>
|
||||
virtual public bool Frozen
|
||||
{
|
||||
get
|
||||
@@ -125,11 +137,14 @@ namespace Spring.Messaging.Nms.Connection
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public void AddConnection(Apache.NMS.IConnection connection)
|
||||
|
||||
/// <summary>
|
||||
/// Adds the connection to the list of resources managed by this holder.
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection.</param>
|
||||
public void AddConnection(IConnection connection)
|
||||
{
|
||||
//TODO - update Assert utility class...
|
||||
//Assert.isTrue(!this.frozen, "Cannot add IConnection because NmsResourceHolder is frozen");
|
||||
AssertUtils.IsTrue(!frozen, "Cannot add IConnection because NmsResourceHolder is frozen");
|
||||
AssertUtils.ArgumentNotNull(connection, "IConnection must not be null");
|
||||
if (!connections.Contains(connection))
|
||||
{
|
||||
@@ -137,15 +152,23 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the session to the list of resources managed by this holder.
|
||||
/// </summary>
|
||||
/// <param name="session">The session.</param>
|
||||
public void AddSession(ISession session)
|
||||
{
|
||||
AddSession(session, null);
|
||||
}
|
||||
|
||||
public void AddSession(ISession session, Apache.NMS.IConnection connection)
|
||||
/// <summary>
|
||||
/// Adds the session and connection to the list of resources managed by this holder.
|
||||
/// </summary>
|
||||
/// <param name="session">The session.</param>
|
||||
/// <param name="connection">The connection.</param>
|
||||
public void AddSession(ISession session, IConnection connection)
|
||||
{
|
||||
//TOOD update AssertUtils class
|
||||
//Assert.isTrue(!this.frozen, "Cannot add ISession because NmsResourceHolder is frozen");
|
||||
AssertUtils.IsTrue(!frozen, "Cannot add ISession because NmsResourceHolder is frozen");
|
||||
AssertUtils.ArgumentNotNull(session, "ISession must not be null");
|
||||
if (!sessions.Contains(session))
|
||||
{
|
||||
@@ -163,38 +186,60 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Apache.NMS.IConnection GetConnection()
|
||||
/// <summary>
|
||||
/// Gets the connection managed by this resource holder
|
||||
/// </summary>
|
||||
/// <returns>A Connection, or null if no managed connection.</returns>
|
||||
public virtual IConnection GetConnection()
|
||||
{
|
||||
return (!(this.connections.Count == 0) ? (Apache.NMS.IConnection)this.connections[0] : null);
|
||||
return (!(this.connections.Count == 0) ? (IConnection)this.connections[0] : null);
|
||||
}
|
||||
|
||||
public virtual Apache.NMS.IConnection GetConnection(System.Type connectionType)
|
||||
/// <summary>
|
||||
/// Gets the connection of a given type managed by this resource holder. This is used
|
||||
/// when storing Queue or Topic Connections (from the older 1.0.2 API) as compared to the
|
||||
/// 'unified domain' API , just Connection, in the newer 1.2 API.
|
||||
/// </summary>
|
||||
/// <param name="connectionType">Type of the connection.</param>
|
||||
/// <returns>The connection, or null if not found.</returns>
|
||||
public virtual IConnection GetConnection(Type connectionType)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//TODO Updae CollectionUtils...
|
||||
//return (NMS.IConnection)CollectionUtils.FindValueOfType(this.connections, connectionType);
|
||||
return (IConnection)CollectionUtils.FindValueOfType(this.connections, connectionType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the first session manged by this holder or null if not available.
|
||||
/// </summary>
|
||||
/// <returns>The session or null if not available.</returns>
|
||||
public virtual ISession GetSession()
|
||||
{
|
||||
return (!(this.sessions.Count == 0) ? (ISession)this.sessions[0] : null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session managed by this holder by type.
|
||||
/// </summary>
|
||||
/// <param name="sessionType">Type of the session.</param>
|
||||
/// <returns>The session or null if not available.</returns>
|
||||
public virtual ISession GetSession(Type sessionType)
|
||||
{
|
||||
return GetSession(sessionType, null);
|
||||
}
|
||||
|
||||
public virtual ISession GetSession(System.Type sessionType, Apache.NMS.IConnection connection)
|
||||
/// <summary>
|
||||
/// Gets the session of a given type associated with the given connection
|
||||
/// </summary>
|
||||
/// <param name="sessionType">Type of the session.</param>
|
||||
/// <param name="connection">The connection.</param>
|
||||
/// <returns>The sessin or null if not available.</returns>
|
||||
public virtual ISession GetSession(Type sessionType, IConnection connection)
|
||||
{
|
||||
IList sessions = this.sessions;
|
||||
if (connection != null)
|
||||
{
|
||||
sessions = (IList)sessionsPerIConnection[connection];
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
//TODO update collection utils
|
||||
//return (ISession)CollectionUtils.FindValueOfType(sessions, sessionType);
|
||||
return (ISession)CollectionUtils.FindValueOfType(sessions, sessionType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -230,6 +275,13 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the holder contains the specified session.
|
||||
/// </summary>
|
||||
/// <param name="session">The session.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the holder contains the specified session; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
public bool ContainsSession(ISession session)
|
||||
{
|
||||
return this.sessions.Contains(session);
|
||||
|
||||
@@ -1,3 +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;
|
||||
@@ -8,11 +27,11 @@ using Spring.Objects.Factory;
|
||||
using Spring.Transaction;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="AbstractPlatformTransactionManager"/> implementation
|
||||
/// for a single NMS <code>Apache.NMS.IConnectionFactory</code>. Binds a
|
||||
/// for a single NMS <code>ConnectionFactory</code>. Binds a
|
||||
/// Connection/Session pair from the specified ConnecctionFactory to the thread,
|
||||
/// potentially allowing for one thread-bound Session per ConnectionFactory.
|
||||
/// </summary>
|
||||
@@ -91,7 +110,6 @@ namespace Spring.Messaging.Nms.Connection
|
||||
get { return connectionFactory; }
|
||||
set
|
||||
{
|
||||
//TODO if create TransactionAwareConnectionFactoryProxy need to check for it here.
|
||||
connectionFactory = value;
|
||||
}
|
||||
}
|
||||
@@ -126,6 +144,10 @@ namespace Spring.Messaging.Nms.Connection
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the NmsTransactionObject.
|
||||
/// </summary>
|
||||
/// <returns>he NmsTransactionObject.</returns>
|
||||
protected override object DoGetTransaction()
|
||||
{
|
||||
NmsTransactionObject txObject = new NmsTransactionObject();
|
||||
@@ -135,6 +157,21 @@ namespace Spring.Messaging.Nms.Connection
|
||||
return txObject;
|
||||
}
|
||||
|
||||
|
||||
/// <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>
|
||||
/// <remarks>
|
||||
/// Does not have to care about applying the propagation behavior,
|
||||
/// as this has already been handled by this abstract manager.
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of creation or system errors.
|
||||
/// </exception>
|
||||
protected override void DoBegin(object transaction, ITransactionDefinition definition)
|
||||
{
|
||||
//This is the default value defined in DefaultTransactionDefinition
|
||||
@@ -186,6 +223,21 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <remarks>
|
||||
/// Transaction synchronization will already have been suspended.
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// in case of system errors.
|
||||
/// </exception>
|
||||
protected override object DoSuspend(object transaction)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject) transaction;
|
||||
@@ -193,12 +245,31 @@ namespace Spring.Messaging.Nms.Connection
|
||||
return TransactionSynchronizationManager.UnbindResource(ConnectionFactory);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <remarks>Transaction synchronization will be resumed afterwards.
|
||||
/// </remarks>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of system errors.
|
||||
/// </exception>
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
NmsResourceHolder conHolder = (NmsResourceHolder) suspendedResources;
|
||||
TransactionSynchronizationManager.BindResource(ConnectionFactory, conHolder);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an actual commit on the given transaction.
|
||||
/// </summary>
|
||||
/// <param name="status">The status representation of the transaction.</param>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of system errors.
|
||||
/// </exception>
|
||||
protected override void DoCommit(DefaultTransactionStatus status)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
|
||||
@@ -210,19 +281,22 @@ namespace Spring.Messaging.Nms.Connection
|
||||
LOG.Debug("Committing NMS transaction on Session [" + session + "]");
|
||||
}
|
||||
session.Commit();
|
||||
/** https://issues.apache.org/activemq/browse/AMQNET-93
|
||||
TODO - need to mirror JMS exception classes in NMS API.
|
||||
} catch (TransactionRolledBackException ex)
|
||||
{
|
||||
*/
|
||||
|
||||
//Note that NMS does not have, TransactionRolledBackException
|
||||
//See https://issues.apache.org/activemq/browse/AMQNET-93
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
{
|
||||
throw new TransactionSystemException("Could not commit NMS transaction.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an actual rollback on the given transaction.
|
||||
/// </summary>
|
||||
/// <param name="status">The status representation of the transaction.</param>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of system errors.
|
||||
/// </exception>
|
||||
protected override void DoRollback(DefaultTransactionStatus status)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
|
||||
@@ -242,12 +316,33 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
|
||||
|
||||
/// <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>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of system errors.
|
||||
/// </exception>
|
||||
protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)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)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)transaction;
|
||||
@@ -256,6 +351,18 @@ namespace Spring.Messaging.Nms.Connection
|
||||
txObject.ResourceHolder.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the given transaction object indicates an existing transaction
|
||||
/// (that is, a transaction which has already started).
|
||||
/// </summary>
|
||||
/// <param name="transaction">Transaction object returned by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>.</param>
|
||||
/// <returns>
|
||||
/// True if there is an existing transaction.
|
||||
/// </returns>
|
||||
/// <exception cref="Spring.Transaction.TransactionException">
|
||||
/// In the case of system errors.
|
||||
/// </exception>
|
||||
protected override bool IsExistingTransaction(object transaction)
|
||||
{
|
||||
NmsTransactionObject txObject = transaction as NmsTransactionObject;
|
||||
|
||||
@@ -21,11 +21,36 @@
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
using Common.Logging;
|
||||
using Spring.Messaging.Nms;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// A ConnectionFactory adapter that returns the same Connection
|
||||
/// from all CreateConnection() calls, and ignores calls to
|
||||
/// Connection.Close(). According to the JMS Connection
|
||||
/// model, this is perfectly thread-safe, check your vendor implmenetation for
|
||||
/// details.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You can either pass in a specific Connection directly or let this
|
||||
/// factory lazily create a Connection via a given target ConnectionFactory.
|
||||
/// <para>Useful in order to keep using the same Connection for multiple
|
||||
/// <see cref="NmsTemplate"/> calls, without having a pooling ConnectionFactory
|
||||
/// underneath. This may span any number of transactions, even concurrently executing transactions.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note that Spring's message listener containers support the use of
|
||||
/// a shared Connection within each listener container instance. Using
|
||||
/// SingleConnectionFactory with a MessageListenerContainer only really makes sense for
|
||||
/// sharing a single Connection across multiple listener containers.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class SingleConnectionFactory : IConnectionFactory, IExceptionListener, IInitializingObject, IDisposable
|
||||
{
|
||||
#region Logging Definition
|
||||
@@ -80,7 +105,7 @@ namespace Spring.Messaging.Nms.Connection
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(target, "connection", "TargetSession Connection must not be null");
|
||||
this.target = target;
|
||||
connection = GetSharedConnection(this, target);
|
||||
connection = GetSharedConnection(target);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +152,11 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exception listener implementation that should be registered
|
||||
/// with with the single Connection created by this factory, if any.
|
||||
/// </summary>
|
||||
/// <value>The exception listener.</value>
|
||||
public IExceptionListener ExceptionListener
|
||||
{
|
||||
get { return exceptionListener; }
|
||||
@@ -162,6 +192,10 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
#region IConnectionFactory Members
|
||||
|
||||
/// <summary>
|
||||
/// Creates the connection.
|
||||
/// </summary>
|
||||
/// <returns>A single shared connection</returns>
|
||||
public IConnection CreateConnection()
|
||||
{
|
||||
lock (connectionMonitor)
|
||||
@@ -174,6 +208,12 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the connection.
|
||||
/// </summary>
|
||||
/// <param name="userName">Name of the user.</param>
|
||||
/// <param name="password">The password.</param>
|
||||
/// <returns></returns>
|
||||
public IConnection CreateConnection(string userName, string password)
|
||||
{
|
||||
throw new InvalidOperationException("SingleConnectionFactory does not support custom username and password.");
|
||||
@@ -181,6 +221,10 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the underlying shared Connection. Closes and reinitializes the Connection if an underlying
|
||||
/// Connection is present already.
|
||||
/// </summary>
|
||||
public void InitConnection()
|
||||
{
|
||||
if (TargetConnectionFactory == null)
|
||||
@@ -200,7 +244,7 @@ namespace Spring.Messaging.Nms.Connection
|
||||
{
|
||||
LOG.Info("Established shared NMS Connection: " + this.target);
|
||||
}
|
||||
this.connection = GetSharedConnection(this, target);
|
||||
this.connection = GetSharedConnection(target);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,6 +257,13 @@ namespace Spring.Messaging.Nms.Connection
|
||||
ResetConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the connection before it is exposed.
|
||||
/// The default implementation applies ExceptionListener and client id.
|
||||
/// Can be overridden in subclasses.
|
||||
/// </summary>
|
||||
/// <param name="con">The Connection to prepare.</param>
|
||||
/// <exception cref="NMSException">if thrown by any NMS API methods.</exception>
|
||||
protected virtual void PrepareConnection(IConnection con)
|
||||
{
|
||||
if (ClientId != null)
|
||||
@@ -249,11 +300,19 @@ namespace Spring.Messaging.Nms.Connection
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// reate a JMS Connection via this template's ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual IConnection DoCreateConnection()
|
||||
{
|
||||
return TargetConnectionFactory.CreateConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the given connection.
|
||||
/// </summary>
|
||||
/// <param name="con">The connection.</param>
|
||||
protected virtual void CloseConnection(IConnection con)
|
||||
{
|
||||
try
|
||||
@@ -273,6 +332,9 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// Ensure that the connection or TargetConnectionFactory are specified.
|
||||
/// </summary>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
if (connection == null && TargetConnectionFactory == null)
|
||||
@@ -283,11 +345,20 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Close the underlying shared connection. The provider of this ConnectionFactory needs to care for proper shutdown.
|
||||
/// As this object implements <see cref="IDisposable"/> an application context will automatically
|
||||
/// invoke this on distruction o
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
ResetConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the underlying shared Connection, to be reinitialized on next access.
|
||||
/// </summary>
|
||||
public virtual void ResetConnection()
|
||||
{
|
||||
lock (connectionMonitor)
|
||||
@@ -301,11 +372,19 @@ namespace Spring.Messaging.Nms.Connection
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IConnection GetSharedConnection(SingleConnectionFactory singleConnectionFactory, IConnection target)
|
||||
/// <summary>
|
||||
/// Wrap the given Connection with a proxy that delegates every method call to it
|
||||
/// but suppresses close calls. This is useful for allowing application code to
|
||||
/// handle a special framework Connection just like an ordinary Connection from a
|
||||
/// ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <param name="target">The original connection to wrap.</param>
|
||||
/// <returns>the wrapped connection</returns>
|
||||
protected virtual IConnection GetSharedConnection(IConnection target)
|
||||
{
|
||||
lock (connectionMonitor)
|
||||
{
|
||||
return new CloseSupressingConnection(singleConnectionFactory, target);
|
||||
return new CloseSupressingConnection(this, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,6 +419,26 @@ namespace Spring.Messaging.Nms.Connection
|
||||
this.singleConnectionFactory = singleConnectionFactory;
|
||||
}
|
||||
|
||||
public string ClientId
|
||||
{
|
||||
get { return target.ClientId; }
|
||||
set
|
||||
{
|
||||
string currentClientId = target.ClientId;
|
||||
if (currentClientId != null && currentClientId.Equals(value))
|
||||
{
|
||||
//ok, the values are consistent.
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Setting of 'ClientID' property not supported on wrapper for shared Connection." +
|
||||
"Set the 'ClientId' property on the SingleConnectionFactory instead.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
// don't pass the call to the target.
|
||||
@@ -370,7 +469,10 @@ namespace Spring.Messaging.Nms.Connection
|
||||
|
||||
public event ExceptionListener ExceptionListener
|
||||
{
|
||||
add { target.ExceptionListener += value; }
|
||||
add
|
||||
{
|
||||
target.ExceptionListener += value;
|
||||
}
|
||||
remove { target.ExceptionListener -= value; }
|
||||
}
|
||||
|
||||
@@ -381,26 +483,6 @@ namespace Spring.Messaging.Nms.Connection
|
||||
set { target.AcknowledgementMode = value; }
|
||||
}
|
||||
|
||||
public string ClientId
|
||||
{
|
||||
get { return target.ClientId; }
|
||||
set
|
||||
{
|
||||
string currentClientId = target.ClientId;
|
||||
if (currentClientId != null && currentClientId.Equals(value))
|
||||
{
|
||||
//ok
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Setting of 'ClientID' property not supported on wrapper for shared Connection." +
|
||||
"Set the 'ClientId' property on the SingleConnectionFactory instead.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
target.Dispose();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Connection
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary> Exception thrown when a synchronized local transaction failed to complete
|
||||
/// (after the main transaction has already completed).
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace Spring.Messaging.Nms
|
||||
/// <author>Mark Pollack</author>
|
||||
public interface IExceptionListener
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when there is an exception in message processing.
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception.</param>
|
||||
void OnException(Exception exception);
|
||||
}
|
||||
}
|
||||
@@ -22,19 +22,19 @@ using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms
|
||||
{
|
||||
/// <summary> Creates a NMS message given a ISession</summary>
|
||||
/// <summary> Creates a NMS message given a Session</summary>
|
||||
/// <remarks>
|
||||
/// <p>The <code>ISession</code> typically is provided by an instance
|
||||
/// <p>The Session typically is provided by an instance
|
||||
/// of the NmsTemplate class.</p>
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack</author>
|
||||
public interface IMessageCreator
|
||||
{
|
||||
/// <summary> Create a IMessage to be sent.</summary>
|
||||
/// <param name="session">the NMS ISession to be used to create the
|
||||
/// <summary> Create a Message to be sent.</summary>
|
||||
/// <param name="session">the NMS Session to be used to create the
|
||||
/// <code>IMessage</code> (never <code>null</code>)
|
||||
/// </param>
|
||||
/// <returns> the <code>IMessage</code> to be sent
|
||||
/// <returns> the <code>Message</code> to be sent
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
IMessage CreateMessage(ISession session);
|
||||
|
||||
@@ -22,8 +22,15 @@ using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms
|
||||
{
|
||||
/// <summary>
|
||||
/// Interfaced based approach to listen to messaging events.
|
||||
/// </summary>
|
||||
public interface IMessageListener
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when a message is delivered.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
void OnMessage(IMessage message);
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace Spring.Messaging.Nms
|
||||
/// </summary>
|
||||
/// <param name="message">the NMS message from the IMessageConverter
|
||||
/// </param>
|
||||
/// <returns> the modified version of the IMessage
|
||||
/// <returns> the modified version of the Message
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
IMessage PostProcessMessage(IMessage message);
|
||||
|
||||
@@ -39,11 +39,13 @@ namespace Spring.Messaging.Nms
|
||||
public interface INmsOperations
|
||||
{
|
||||
/// <summary> Execute the action specified by the given action object within
|
||||
/// a NMS ISession.
|
||||
/// <p>Note: The value of isPubSubDomain affects the behavior of this method.
|
||||
/// If isPubSubDomain equals true, then a ISession is passed to the callback.
|
||||
/// If false, then a ISession is passed to the callback.</p>
|
||||
/// a NMS Session.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Note that the value of PubSubDomain affects the behavior of this method.
|
||||
/// If PubSubDomain equals true, then a Session is passed to the callback.
|
||||
/// If false, then a ISession is passed to the callback.</para>b
|
||||
/// </remarks>
|
||||
/// <param name="action">callback object that exposes the session
|
||||
/// </param>
|
||||
/// <returns> the result object from working with the session
|
||||
@@ -52,7 +54,7 @@ namespace Spring.Messaging.Nms
|
||||
object Execute(ISessionCallback action);
|
||||
|
||||
/// <summary> Send a message to a NMS destination. The callback gives access to
|
||||
/// the NMS session and IMessageProducer in order to do more complex
|
||||
/// the NMS session and MessageProducer in order to do more complex
|
||||
/// send operations.
|
||||
/// </summary>
|
||||
/// <param name="action">callback object that exposes the session/producer pair
|
||||
@@ -76,7 +78,7 @@ namespace Spring.Messaging.Nms
|
||||
void Send(IMessageCreator messageCreator);
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The IMessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination to send this message to
|
||||
/// </param>
|
||||
@@ -86,7 +88,7 @@ namespace Spring.Messaging.Nms
|
||||
void Send(IDestination destination, IMessageCreator messageCreator);
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The IMessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destinationName">the name of the destination to send this message to
|
||||
/// (to be resolved to an actual destination by a DestinationResolver)
|
||||
@@ -109,7 +111,7 @@ namespace Spring.Messaging.Nms
|
||||
void SendWithDelegate(IMessageCreatorDelegate messageCreatorDelegate);
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The IMessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination to send this message to
|
||||
/// </param>
|
||||
@@ -119,7 +121,7 @@ namespace Spring.Messaging.Nms
|
||||
void SendWithDelegate(IDestination destination, IMessageCreatorDelegate messageCreatorDelegate);
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The IMessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destinationName">the name of the destination to send this message to
|
||||
/// (to be resolved to an actual destination by a DestinationResolver)
|
||||
|
||||
@@ -28,19 +28,19 @@ namespace Spring.Messaging.Nms
|
||||
/// method, often implemented as an anonymous inner class.</p>
|
||||
///
|
||||
/// <p>The typical implementation will perform multiple operations on the
|
||||
/// supplied NMS ISession and IMessageProducer. </p>
|
||||
/// supplied NMS Session and MessageProducer. </p>
|
||||
/// </remarks>
|
||||
/// <author>Mark Pollack</author>
|
||||
public interface IProducerCallback
|
||||
{
|
||||
/// <summary> Perform operations on the given ISession and IMessageProducer.
|
||||
/// <summary> Perform operations on the given Session and MessageProducer.
|
||||
/// The message producer is not associated with any destination.
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS <code>ISession</code> object to use
|
||||
/// <param name="session">the NMS <code>Session</code> object to use
|
||||
/// </param>
|
||||
/// <param name="producer">the NMS <code>IMessageProducer</code> object to use
|
||||
/// <param name="producer">the NMS <code>MessageProducer</code> object to use
|
||||
/// </param>
|
||||
/// <returns> a result object from working with the <code>ISession</code>, if any (can be <code>null</code>)
|
||||
/// <returns> a result object from working with the <code>Session</code>, if any (can be <code>null</code>)
|
||||
/// </returns>
|
||||
object DoInNms(ISession session, IMessageProducer producer);
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ using Apache.NMS;
|
||||
namespace Spring.Messaging.Nms
|
||||
{
|
||||
/// <summary> Callback for executing any number of operations on a provided
|
||||
/// ISession
|
||||
/// Session
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>To be used with the NmsTemplate.Execute(ISessionCallback)}
|
||||
@@ -35,11 +35,11 @@ namespace Spring.Messaging.Nms
|
||||
public interface ISessionCallback
|
||||
{
|
||||
/// <summary> Execute any number of operations against the supplied NMS
|
||||
/// ISession, possibly returning a result.
|
||||
/// Session, possibly returning a result.
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS <code>ISession</code>
|
||||
/// <param name="session">the NMS <code>Session</code>
|
||||
/// </param>
|
||||
/// <returns> a result object from working with the <code>ISession</code>, if any (so can be <code>null</code>)
|
||||
/// <returns> a result object from working with the <code>Session</code>, if any (so can be <code>null</code>)
|
||||
/// </returns>
|
||||
/// <throws>NMSException if there is any problem </throws>
|
||||
object DoInNms(ISession session);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
using System;
|
||||
using Common.Logging;
|
||||
using Spring.Messaging.Nms;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Spring.Util;
|
||||
using Apache.NMS;
|
||||
@@ -28,7 +29,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base class for message listener containers. Can either host
|
||||
/// a standard NMS <see cref="IMessageListener"/> or a Spring-specific
|
||||
/// a standard NMS MessageListener or a Spring-specific
|
||||
/// <see cref="ISessionAwareMessageListener"/>
|
||||
/// </summary>
|
||||
public abstract class AbstractMessageListenerContainer : AbstractNmsListeningContainer
|
||||
@@ -61,6 +62,12 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the destination to receive messages from. Will be <code>null</code>
|
||||
/// if the configured destination is not an actual Destination type;
|
||||
/// c.f. <see cref="DestinationName"/> when the destination is a String.
|
||||
/// </summary>
|
||||
/// <value>The destination.</value>
|
||||
public IDestination Destination
|
||||
{
|
||||
get
|
||||
@@ -80,6 +87,12 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the destination to receive messages from.
|
||||
/// Will be <code>null</code> if the configured destination is not a
|
||||
/// string type; c.f. <see cref="Destination"/> when it is an actual Destination object.
|
||||
/// </summary>
|
||||
/// <value>The name of the destination.</value>
|
||||
public string DestinationName
|
||||
{
|
||||
get
|
||||
@@ -95,6 +108,10 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message selector.
|
||||
/// </summary>
|
||||
/// <value>The message selector expression (or <code>null</code> if none)..</value>
|
||||
public string MessageSelector
|
||||
{
|
||||
get { return messageSelector; }
|
||||
@@ -108,7 +125,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
///
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This can be either a standard NMS <see cref="IMessageListener"/> object or a
|
||||
/// This can be either a standard NMS MessageListener object or a
|
||||
/// Spring <see cref="ISessionAwareMessageListener"/> object.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
@@ -132,6 +149,19 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the subscription is durable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Set whether to make the subscription durable. The durable subscription name
|
||||
/// to be used can be specified through the "DurableSubscriptionName" property.
|
||||
/// <para>Default is "false". Set this to "true" to register a durable subscription,
|
||||
/// typically in combination with a "DurableSubscriptionName" value (unless
|
||||
/// your message listener class name is good enough as subscription name).
|
||||
/// </para>
|
||||
/// <para>Only makes sense when listening to a topic (pub-sub domain).</para>
|
||||
/// </remarks>
|
||||
/// <value><c>true</c> if the subscription is durable; otherwise, <c>false</c>.</value>
|
||||
public bool SubscriptionDurable
|
||||
{
|
||||
get { return subscriptionDurable; }
|
||||
@@ -139,6 +169,18 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the durable subscription to create.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To be applied in case of a topic (pub-sub domain) with subscription durability activated.
|
||||
/// The durable subscription name needs to be unique within this client's
|
||||
/// client id. Default is the class name of the specified message listener.
|
||||
/// <para>Note: Only 1 concurrent consumer (which is the default of this
|
||||
/// message listener container) is allowed for each durable subscription.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>The name of the durable subscription.</value>
|
||||
public string DurableSubscriptionName
|
||||
{
|
||||
get
|
||||
@@ -153,6 +195,11 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exception listener to notify in case of a NMSException thrown
|
||||
/// by the registered message listener or the invocation infrastructure.
|
||||
/// </summary>
|
||||
/// <value>The exception listener.</value>
|
||||
public IExceptionListener ExceptionListener
|
||||
{
|
||||
get { return exceptionListener; }
|
||||
@@ -160,6 +207,24 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to expose listener session to a registered
|
||||
/// <see cref="ISessionAwareMessageListener"/> as well as to <see cref="NmsTemplate"/> calls.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Default is "true", reusing the listener's Session.
|
||||
/// Turn this off to expose a fresh Session fetched from the same
|
||||
/// underlying Connection instead, which might be necessary
|
||||
/// on some messaging providers.
|
||||
/// <para>Note that Sessions managed by an external transaction manager will
|
||||
/// always get exposed to <see cref="NmsTemplate"/>
|
||||
/// calls. So in terms of NmsTemplate exposure, this setting only affects
|
||||
/// locally transacted Sessions.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// <c>true</c> if expose listener session; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool ExposeListenerSession
|
||||
{
|
||||
get { return exposeListenerISession; }
|
||||
@@ -196,18 +261,15 @@ namespace Spring.Messaging.Nms.Listener
|
||||
set { acceptMessagesWhileStopping = value; }
|
||||
}
|
||||
|
||||
public object LifecycleMonitor
|
||||
{
|
||||
get { return lifecycleMonitor; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Validate that the destination is not null and that if the subscription is durable, then we are not
|
||||
/// using the Pub/Sub domain.
|
||||
/// </summary>
|
||||
protected override void ValidateConfiguration()
|
||||
{
|
||||
if (this.destination == null)
|
||||
@@ -284,7 +346,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified listener: either as standard NMS IMessageListener
|
||||
/// Invokes the specified listener: either as standard NMS MessageListener
|
||||
/// or (preferably) as Spring SessionAwareMessageListener.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
@@ -384,17 +446,38 @@ namespace Spring.Messaging.Nms.Listener
|
||||
// Commit session or acknowledge message
|
||||
if (session.Transacted)
|
||||
{
|
||||
if (SessionTransacted)
|
||||
// Commit necessary - but avoid commit call is Session transaction is externally coordinated.
|
||||
if (IsSessionLocallyTransacted(session))
|
||||
{
|
||||
NmsUtils.CommitIfNecessary(session);
|
||||
}
|
||||
}
|
||||
else if (ClientAcknowledge(session))
|
||||
else if (IsClientAcknowledge(session))
|
||||
{
|
||||
message.Acknowledge();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given Session is locally transacted, that is, whether
|
||||
/// its transaction is managed by this listener container's Session handling
|
||||
/// and not by an external transaction coordinator.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Session's own transacted flag will already have been checked
|
||||
/// before. This method is about finding out whether the Session's transaction
|
||||
/// is local or externally coordinated.
|
||||
/// </remarks>
|
||||
/// <param name="session">The session to check.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the is session locally transacted; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
/// <see cref="NmsAccessor.SessionTransacted"/>
|
||||
protected virtual bool IsSessionLocallyTransacted(ISession session)
|
||||
{
|
||||
return SessionTransacted;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Perform a rollback, if appropriate.
|
||||
@@ -403,7 +486,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
/// <exception cref="NMSException">In case of a rollback error</exception>
|
||||
protected virtual void RollbackIfNecessary(ISession session)
|
||||
{
|
||||
if (session.Transacted && SessionTransacted)
|
||||
if (session.Transacted && IsSessionLocallyTransacted(session))
|
||||
{
|
||||
// Transacted session created by this container -> rollback
|
||||
NmsUtils.RollbackIfNecessary(session);
|
||||
@@ -419,7 +502,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
try
|
||||
{
|
||||
if (session.Transacted && SessionTransacted)
|
||||
if (session.Transacted && IsSessionLocallyTransacted(session))
|
||||
{
|
||||
// Transacted session created by this container -> rollback
|
||||
if (logger.IsDebugEnabled)
|
||||
@@ -428,7 +511,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
NmsUtils.RollbackIfNecessary(session);
|
||||
}
|
||||
} catch (NMSException ex2)
|
||||
} catch (NMSException)
|
||||
{
|
||||
logger.Error("Application exception overriden by rollback exception", ex);
|
||||
throw;
|
||||
@@ -487,12 +570,19 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
#endregion
|
||||
|
||||
protected virtual void CheckMessageListener(System.Object messageListener)
|
||||
/// <summary>
|
||||
/// Checks the message listener, throwing an exception
|
||||
/// if it does not correspond to a supported listener type.
|
||||
/// By default, only a standard JMS MessageListener object or a
|
||||
/// Spring <see cref="ISessionAwareMessageListener"/> object will be accepted.
|
||||
/// </summary>
|
||||
/// <param name="messageListener">The message listener.</param>
|
||||
protected virtual void CheckMessageListener(object messageListener)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(messageListener, "IMessage Listener can not be null");
|
||||
if (!(messageListener is IMessageListener || messageListener is ISessionAwareMessageListener))
|
||||
{
|
||||
throw new System.ArgumentException("messageListener needs to be of type [" + typeof(IMessageListener).FullName + "] or [" + typeof(ISessionAwareMessageListener).FullName + "]");
|
||||
throw new ArgumentException("messageListener needs to be of type [" + typeof(IMessageListener).FullName + "] or [" + typeof(ISessionAwareMessageListener).FullName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ using System;
|
||||
using Apache.NMS;
|
||||
using Common.Logging;
|
||||
using Spring.Context;
|
||||
using Spring.Messaging.Nms.Connection;
|
||||
using Spring.Messaging.Nms.Connections;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Spring.Messaging.Nms.Support.IDestinations;
|
||||
using Spring.Objects.Factory;
|
||||
@@ -57,24 +57,39 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
private String clientId;
|
||||
|
||||
protected bool autoStartup = true;
|
||||
private bool autoStartup = true;
|
||||
|
||||
private string objectName;
|
||||
|
||||
private IConnection sharedConnection;
|
||||
|
||||
private bool sharedConnectionStarted = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The monitor object to lock on when performing operations on the connection.
|
||||
/// </summary>
|
||||
protected object sharedConnectionMonitor = new object();
|
||||
|
||||
private volatile bool active = false;
|
||||
|
||||
private bool running = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The monitor object to lock on when performing operations that update the lifecycle of the container.
|
||||
/// </summary>
|
||||
protected object lifecycleMonitor = new object();
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the client id for a shared Connection created and used by this container.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that client ids need to be unique among all active Connections
|
||||
/// of the underlying JMS provider. Furthermore, a client id can only be
|
||||
/// assigned if the original ConnectionFactory hasn't already assigned one.
|
||||
/// </remarks>
|
||||
/// <value>The client id.</value>
|
||||
public string ClientId
|
||||
{
|
||||
set { clientId = value; }
|
||||
@@ -89,6 +104,18 @@ namespace Spring.Messaging.Nms.Listener
|
||||
set { this.autoStartup = value; }
|
||||
}
|
||||
|
||||
/// <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; }
|
||||
@@ -134,6 +161,11 @@ namespace Spring.Messaging.Nms.Listener
|
||||
return true; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this container is currently active,
|
||||
/// that is, whether it has been set up but not shut down yet.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if active; otherwise, <c>false</c>.</value>
|
||||
public virtual bool Active
|
||||
{
|
||||
get
|
||||
@@ -146,11 +178,10 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Return whether a shared NMS IConnection should be maintained
|
||||
/// <summary> Return whether a shared NMS Connection should be maintained
|
||||
/// by this listener container base class.
|
||||
/// </summary>
|
||||
/// <seealso cref="AbstractMessageListenerContainer.SharedConnection">
|
||||
/// </seealso>
|
||||
/// </summary>
|
||||
/// <seealso cref="SharedConnection"/>
|
||||
protected abstract bool SharedConnectionEnabled { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -180,7 +211,10 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Call base class method, then <see cref="ValidateConfiguration"/> and then <see cref="Initialize"/>
|
||||
/// </summary>
|
||||
public override void AfterPropertiesSet()
|
||||
{
|
||||
base.AfterPropertiesSet();
|
||||
@@ -197,6 +231,9 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="Shutdown"/> when the application context destroys the container instance.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Shutdown();
|
||||
@@ -237,6 +274,9 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the shared connection, call <see cref="DoShutdown"/>, and close this container.
|
||||
/// </summary>
|
||||
public virtual void Shutdown()
|
||||
{
|
||||
logger.Debug("Shutting down message listener container");
|
||||
@@ -283,6 +323,9 @@ namespace Spring.Messaging.Nms.Listener
|
||||
DoStart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start the shared Connection, if any, and notify all invoker tasks.
|
||||
/// </summary>
|
||||
protected virtual void DoStart()
|
||||
{
|
||||
// Lazily establish a shared Connection, if necessary.
|
||||
@@ -428,7 +471,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
PrepareSharedConnection(con);
|
||||
return con;
|
||||
} catch (NMSException ex)
|
||||
} catch (NMSException)
|
||||
{
|
||||
NmsUtils.CloseConnection(con);
|
||||
throw;
|
||||
@@ -478,6 +521,10 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the shared connection.
|
||||
/// </summary>
|
||||
/// <exception cref="NMSException">if thrown by NMS API methods.</exception>
|
||||
protected virtual void StopSharedConnection()
|
||||
{
|
||||
lock (this.sharedConnectionMonitor)
|
||||
@@ -504,7 +551,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
/// shared Connection failed. This is indicating to invokers that they need
|
||||
/// to establish the shared Connection themselves on first access.
|
||||
/// </summary>
|
||||
public class SharedConnectionNotInitializedException : ApplicationException
|
||||
public class SharedConnectionNotInitializedException : NMSException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SharedConnectionNotInitializedException"/> class.
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections;
|
||||
using Common.Logging;
|
||||
using Spring.Expressions;
|
||||
using Spring.Messaging.Nms.Listener;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Spring.Messaging.Nms.Support.Converter;
|
||||
using Spring.Messaging.Nms.Support.IDestinations;
|
||||
@@ -10,6 +11,40 @@ using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Message listener adapter that delegates the handling of messages to target
|
||||
/// listener methods via reflection, with flexible message type conversion.
|
||||
/// Allows listener methods to operate on message content types, completely
|
||||
/// independent from the NMS API.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>By default, the content of incoming messages gets extracted before
|
||||
/// being passed into the target listener method, to let the target method
|
||||
/// operate on message content types such as String or byte array instead of
|
||||
/// the raw Message. Message type conversion is delegated to a Spring
|
||||
/// <see cref="IMessageConverter"/>. By default, a <see cref="SimpleMessageConverter"/>
|
||||
/// will be used. (If you do not want such automatic message conversion taking
|
||||
/// place, then be sure to set the <see cref="MessageConverter"/> property
|
||||
/// to <code>null</code>.)
|
||||
/// </para>
|
||||
/// <para>If a target listener method returns a non-null object (typically of a
|
||||
/// message content type such as <code>String</code> or byte array), it will get
|
||||
/// wrapped in a NMS <code>Message</code> and sent to the response destination
|
||||
/// (either the NMS "reply-to" destination or the <see cref="defaultResponseDestination"/>
|
||||
/// specified.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The sending of response messages is only available when
|
||||
/// using the <see cref="ISessionAwareMessageListener"/> entry point (typically through a
|
||||
/// Spring message listener container). Usage as standard NMS MessageListener
|
||||
/// does <i>not</i> support the generation of response messages.
|
||||
/// </para>
|
||||
/// <para>Consult the reference documentation for examples of method signatures compliant with this
|
||||
/// adapter class.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class MessageListenerAdapter : IMessageListener
|
||||
{
|
||||
#region Logging
|
||||
@@ -18,9 +53,14 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
|
||||
#endregion
|
||||
|
||||
private object delegateObject;
|
||||
/// <summary>
|
||||
/// The default handler method name.
|
||||
/// </summary>
|
||||
public static string ORIGINAL_DEFAULT_HANDLER_METHOD = "HandleMessage";
|
||||
|
||||
private string defaultListenerMethod = "HandleMessage";
|
||||
private object handlerObject;
|
||||
|
||||
private string defaultHandlerMethod = ORIGINAL_DEFAULT_HANDLER_METHOD;
|
||||
|
||||
private IExpression processingExpression;
|
||||
|
||||
@@ -30,53 +70,107 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
|
||||
private IMessageConverter messageConverter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MessageListenerAdapter"/> class with default settings.
|
||||
/// </summary>
|
||||
public MessageListenerAdapter()
|
||||
{
|
||||
InitDefaultStrategies();
|
||||
delegateObject = this;
|
||||
processingExpression = Spring.Expressions.Expression.Parse(defaultListenerMethod + "(#convertedObject)");
|
||||
handlerObject = this;
|
||||
processingExpression = Expression.Parse(defaultHandlerMethod + "(#convertedObject)");
|
||||
}
|
||||
|
||||
public MessageListenerAdapter(object delegateObject)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MessageListenerAdapter"/> class for the given handler object
|
||||
/// </summary>
|
||||
/// <param name="handlerObject">The delegate object.</param>
|
||||
public MessageListenerAdapter(object handlerObject)
|
||||
{
|
||||
InitDefaultStrategies();
|
||||
this.delegateObject = delegateObject;
|
||||
this.handlerObject = handlerObject;
|
||||
}
|
||||
|
||||
// TODO name change?
|
||||
|
||||
public object DelegateObject
|
||||
/// <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 delegateObject; }
|
||||
set { delegateObject = value; }
|
||||
get { return handlerObject; }
|
||||
set { handlerObject = value; }
|
||||
}
|
||||
|
||||
public string DefaultListenerMethod
|
||||
/// <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 <see cref="ORIGINAL_DEFAULT_HANDLER_METHOD"/> ("HandleMessage"}.
|
||||
/// </summary>
|
||||
/// <value>The default handler method.</value>
|
||||
public string DefaultHandlerMethod
|
||||
{
|
||||
get { return defaultListenerMethod; }
|
||||
get { return defaultHandlerMethod; }
|
||||
set
|
||||
{
|
||||
defaultListenerMethod = value;
|
||||
defaultHandlerMethod = 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 "JMSReplyTo" field.
|
||||
/// 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" or "DefaultResponseTopicName",
|
||||
/// to be dynamically resolved via the DestinationResolver.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <value>The default response destination.</value>
|
||||
public object DefaultResponseDestination
|
||||
{
|
||||
set { defaultResponseDestination = 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
|
||||
/// "NMSReplyTo" field.
|
||||
/// <para>Alternatively, specify a JMS Destination object as "defaultResponseDestination".</para>
|
||||
/// </summary>
|
||||
/// <value>The name of the default response destination queue.</value>
|
||||
public string DefaultResponseDestinationQueueName
|
||||
{
|
||||
set { defaultResponseDestination = new DestinationNameHolder(value, false); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the name of the default response topic to send response messages to.
|
||||
/// This will be applied in case of a request message that does not carry a
|
||||
/// "NMSReplyTo" field.
|
||||
/// <para>Alternatively, specify a JMS Destination object as "defaultResponseDestination".</para>
|
||||
/// </summary>
|
||||
/// <value>The name of the default response destination topic.</value>
|
||||
public string DefaultResponseDestinationTopicName
|
||||
{
|
||||
set { defaultResponseDestination = new DestinationNameHolder(value, true); }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the destination resolver that should be used to resolve response
|
||||
/// destination names for this adapter.
|
||||
/// <para>The default resolver is a <see cref="DynamicDestinationResolver"/>.
|
||||
/// Specify another implementation, for other strategies, perhaps from a directory service.</para>
|
||||
/// </summary>
|
||||
/// <value>The destination resolver.</value>
|
||||
public IDestinationResolver DestinationResolver
|
||||
{
|
||||
get { return destinationResolver; }
|
||||
@@ -87,28 +181,39 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message converter that will convert incoming JMS messages to
|
||||
/// listener method arguments, and objects returned from listener
|
||||
/// methods back to NMS messages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The default converter is a {@link SimpleMessageConverter}, which is able
|
||||
/// to handle BytesMessages}, TextMessages, MapMessages, and ObjectMessages.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>The message converter.</value>
|
||||
public IMessageConverter MessageConverter
|
||||
{
|
||||
get { return messageConverter; }
|
||||
set { messageConverter = value; }
|
||||
}
|
||||
|
||||
private void InitDefaultStrategies()
|
||||
{
|
||||
MessageConverter = new SimpleMessageConverter();
|
||||
}
|
||||
|
||||
protected virtual void HandleListenerException(Exception e)
|
||||
{
|
||||
logger.Error("Listener execution failed", e);
|
||||
}
|
||||
|
||||
protected virtual string GetListenerMethodName(IMessage originalIMessage, object extractedMessage)
|
||||
{
|
||||
return DefaultListenerMethod;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Standard JMS {@link MessageListener} entry point.
|
||||
/// <para>Delegates the message to the target listener method, with appropriate
|
||||
/// conversion of the message arguments
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In case of an exception, the <see cref="HandleListenerException"/> method will be invoked.
|
||||
/// <b>Note</b>
|
||||
/// Does not support sending response messages based on
|
||||
/// result objects returned from listener methods. Use the
|
||||
/// <see cref="ISessionAwareMessageListener"/> entry point (typically through a Spring
|
||||
/// message listener container) for handling result objects as well.
|
||||
/// </remarks>
|
||||
/// <param name="message">The incoming message.</param>
|
||||
public void OnMessage(IMessage message)
|
||||
{
|
||||
try
|
||||
@@ -121,9 +226,19 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spring <see cref="ISessionAwareMessageListener"/> entry point.
|
||||
/// <para>
|
||||
/// Delegates the message to the target listener method, with appropriate
|
||||
/// conversion of the message argument. If the target method returns a
|
||||
/// non-null object, wrap in a NMS message and send it back.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="message">The incoming message.</param>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
public void OnMessage(IMessage message, ISession session)
|
||||
{
|
||||
object convertedMessage = ExtractIMessage(message);
|
||||
object convertedMessage = ExtractMessage(message);
|
||||
|
||||
|
||||
IDictionary vars = new Hashtable();
|
||||
@@ -131,11 +246,11 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
|
||||
//Need to parse each time since have overloaded methods and
|
||||
//expression processor caches target of first invocation.
|
||||
//TODO - use regular reflection.
|
||||
processingExpression = Expression.Parse(defaultListenerMethod + "(#convertedObject)");
|
||||
//TODO - check JIRA as I believe this has been fixed, otherwise, use regular reflection. -MLP
|
||||
processingExpression = Expression.Parse(defaultHandlerMethod + "(#convertedObject)");
|
||||
|
||||
//Invoke message handler method and get result.
|
||||
object result = processingExpression.GetValue(delegateObject, vars);
|
||||
object result = processingExpression.GetValue(handlerObject, vars);
|
||||
if (result != null)
|
||||
{
|
||||
HandleResult(result, message, session);
|
||||
@@ -146,7 +261,68 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleResult(object result, IMessage request, ISession session)
|
||||
/// <summary>
|
||||
/// Initialize the default implementations for the adapter's strategies.
|
||||
/// </summary>
|
||||
protected virtual void InitDefaultStrategies()
|
||||
{
|
||||
MessageConverter = new SimpleMessageConverter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the given exception that arose during listener execution.
|
||||
/// The default implementation logs the exception at error level.
|
||||
/// <para>This method only applies when used as standard NMS MessageListener.
|
||||
/// In case of the Spring <see cref="ISessionAwareMessageListener"/> mechanism,
|
||||
/// exceptions get handled by the caller instead.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception to handle.</param>
|
||||
protected virtual void HandleListenerException(Exception ex)
|
||||
{
|
||||
logger.Error("Listener execution failed", ex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract 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>
|
||||
/// <exception cref="NMSException">if thrown by NMS API methods</exception>
|
||||
private object ExtractMessage(IMessage message)
|
||||
{
|
||||
IMessageConverter converter = MessageConverter;
|
||||
if (converter != null)
|
||||
{
|
||||
return converter.FromMessage(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the listener method that is supposed to
|
||||
/// handle the given message.
|
||||
/// The default implementation simply returns the configured
|
||||
/// default listener method, if any.
|
||||
/// </summary>
|
||||
/// <param name="originalIMessage">The NMS request message.</param>
|
||||
/// <param name="extractedMessage">The converted JMS request message,
|
||||
/// to be passed into the listener method as argument.</param>
|
||||
/// <returns>the name of the listener method (never <code>null</code>)</returns>
|
||||
/// <exception cref="NMSException">if thrown by NMS API methods</exception>
|
||||
protected virtual string GetHandlerMethodName(IMessage originalIMessage, object extractedMessage)
|
||||
{
|
||||
return DefaultHandlerMethod;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the given result object returned from the listener method, sending a response message back.
|
||||
/// </summary>
|
||||
/// <param name="result">The result object to handle (never <code>null</code>).</param>
|
||||
/// <param name="request">The original request message.</param>
|
||||
/// <param name="session">The session to operate on (may be <code>null</code>).</param>
|
||||
protected virtual void HandleResult(object result, IMessage request, ISession session)
|
||||
{
|
||||
if (session != null)
|
||||
{
|
||||
@@ -170,6 +346,14 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a JMS message to be sent as response based on the given result object.
|
||||
/// </summary>
|
||||
/// <param name="session">The JMS Session to operate on.</param>
|
||||
/// <param name="result">The content of the message, as returned from the listener method.</param>
|
||||
/// <returns>the JMS <code>Message</code> (never <code>null</code>)</returns>
|
||||
/// <exception cref="MessageConversionException">If there was an error in message conversion</exception>
|
||||
/// <exception cref="NMSException">if thrown by NMS API methods</exception>
|
||||
protected virtual IMessage BuildMessage(ISession session, Object result)
|
||||
{
|
||||
IMessageConverter converter = MessageConverter;
|
||||
@@ -182,18 +366,43 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
IMessage msg = result as IMessage;
|
||||
if (msg == null)
|
||||
{
|
||||
throw new IMessageConversionException(
|
||||
throw new MessageConversionException(
|
||||
"No IMessageConverter specified - cannot handle message [" + result + "]");
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 JMS message about to be sent.</param>
|
||||
/// <exception cref="NMSException">if thrown by NMS API methods</exception>
|
||||
protected virtual void PostProcessResponse(IMessage request, IMessage response)
|
||||
{
|
||||
response.NMSCorrelationID = request.NMSCorrelationID;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determine a response destination for the given message.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The default implementation first checks the JMS Reply-To
|
||||
/// Destination 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="ResolveDefaultResponseDestination"/> default response destination}
|
||||
/// is returned; if this too is <code>null</code>, then an
|
||||
/// <see cref="InvalidDestinationException"/>is thrown.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="request">The original incoming message.</param>
|
||||
/// <param name="response">Tthe outgoing message about to be sent.</param>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <returns>the response destination (never <code>null</code>)</returns>
|
||||
/// <exception cref="NMSException">if thrown by NMS API methods</exception>
|
||||
/// <exception cref="InvalidDestinationException">if no destination can be determined.</exception>
|
||||
protected virtual IDestination GetResponseDestination(IMessage request, IMessage response, ISession session)
|
||||
{
|
||||
IDestination replyTo = request.NMSReplyTo;
|
||||
@@ -208,7 +417,13 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
}
|
||||
return replyTo;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the default response destination into a Destination, using this
|
||||
/// accessor's <see cref="IDestinationResolver"/> in case of a destination name.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <returns>The located destination</returns>
|
||||
protected virtual IDestination ResolveDefaultResponseDestination(ISession session)
|
||||
{
|
||||
IDestination dest = defaultResponseDestination as IDestination;
|
||||
@@ -225,7 +440,13 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends the given response message to the given destination.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <param name="destination">The destination to send to.</param>
|
||||
/// <param name="response">The outgoing message about to be sent.</param>
|
||||
protected virtual void SendResponse(ISession session, IDestination destination, IMessage response)
|
||||
{
|
||||
IMessageProducer producer = session.CreateProducer(destination);
|
||||
@@ -239,24 +460,22 @@ namespace Spring.Messaging.Nms.Listener.Adapter
|
||||
NmsUtils.CloseMessageProducer(producer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Post-process the given message producer before using it to send the response.
|
||||
/// The default implementation is empty.
|
||||
/// </summary>
|
||||
/// <param name="producer">The producer that will be used to send the message.</param>
|
||||
/// <param name="response">The outgoing message about to be sent.</param>
|
||||
protected virtual void PostProcessProducer(IMessageProducer producer, IMessage response)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
private object ExtractIMessage(IMessage message)
|
||||
{
|
||||
IMessageConverter converter = MessageConverter;
|
||||
if (converter != null)
|
||||
{
|
||||
return converter.FromMessage(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal class combining a destination name and its target destination type (queue or topic).
|
||||
/// </summary>
|
||||
internal class DestinationNameHolder
|
||||
{
|
||||
private string name;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
public class DefaultMessageListenerContainer
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,49 @@
|
||||
#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 Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// Variant of the standard NMS MessageListener interface,
|
||||
/// offering not only the received Message but also the underlying
|
||||
/// Session object. The latter can be used to send reply messages,
|
||||
/// without the need to access an external Connection/Session,
|
||||
/// i.e. without the need to access the underlying ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Supported by Spring's <see cref="SimpleMessageListenerContainer"/>
|
||||
/// as direct alternative to the standard MessageListener interface.
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public interface ISessionAwareMessageListener
|
||||
{
|
||||
|
||||
/// <summary> Callback for processing a received NMS message.
|
||||
/// Implementors are supposed to process the given IMessage,
|
||||
/// typically sending reply messages through the given ISession.
|
||||
/// Implementors are supposed to process the given Message,
|
||||
/// typically sending reply messages through the given Session.
|
||||
/// </summary>
|
||||
/// <param name="message">the received NMS message
|
||||
/// </param>
|
||||
/// <param name="session">the underlying NMS ISession
|
||||
/// <param name="session">the underlying NMS Session
|
||||
/// </param>
|
||||
/// <throws> NMSException if thrown by NMS methods </throws>
|
||||
void OnMessage(IMessage message, ISession session);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#endregion
|
||||
|
||||
using Apache.NMS;
|
||||
using Spring.Messaging.Nms.Connection;
|
||||
using Spring.Messaging.Nms.Connections;
|
||||
|
||||
namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
using System;
|
||||
using Common.Logging;
|
||||
using Spring.Collections;
|
||||
using Spring.Messaging.Nms;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Apache.NMS;
|
||||
using Spring.Transaction.Support;
|
||||
@@ -30,7 +31,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// Message listener container that uses the plain NMS client API's
|
||||
/// <see cref="IMessageConsumer.Listener"/> method to create concurrent
|
||||
/// MessageConsumer.Listener method to create concurrent
|
||||
/// MessageConsumers for the specified listeners.
|
||||
/// </summary>
|
||||
public class SimpleMessageListenerContainer : AbstractMessageListenerContainer, IExceptionListener
|
||||
@@ -57,12 +58,31 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to inhibit the delivery of messages published by its own connection.
|
||||
/// Default is "false".
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if should inhibit the delivery of messages published by its own connection; otherwise, <c>false</c>.</value>
|
||||
public bool PubSubNoLocal
|
||||
{
|
||||
get { return pubSubNoLocal; }
|
||||
set { pubSubNoLocal = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specify the number of concurrent consumers to create. Default is 1.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Raising the number of concurrent consumers is recommendable in order
|
||||
/// to scale the consumption of messages coming in from a queue. However,
|
||||
/// note that any ordering guarantees are lost once multiple consumers are
|
||||
/// registered. In general, stick with 1 consumer for low-volume queues.
|
||||
/// <para>Do not raise the number of concurrent consumers for a topic.
|
||||
/// This would lead to concurrent consumption of the same message,
|
||||
/// which is hardly ever desirable.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>The concurrent consumers.</value>
|
||||
public int ConcurrentConsumers
|
||||
{
|
||||
set
|
||||
@@ -82,6 +102,10 @@ namespace Spring.Messaging.Nms.Listener
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Call base class for valdation and then check that if the subscription is durable that the number of
|
||||
/// concurrent consumers is equal to one.
|
||||
/// </summary>
|
||||
protected override void ValidateConfiguration()
|
||||
{
|
||||
base.ValidateConfiguration();
|
||||
@@ -120,10 +144,18 @@ namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
base.PrepareSharedConnection(connection);
|
||||
connection.ExceptionListener += OnException;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IExceptionListener"/> implementation, invoked by the NMS provider in
|
||||
/// case of connection failures. Re-initializes this listener container's
|
||||
/// shared connection and its sessions and consumers.
|
||||
/// </summary>
|
||||
/// <param name="exception">The reported connection exception.</param>
|
||||
public void OnException(Exception exception)
|
||||
{
|
||||
// First invoke the user-specific ExceptionListener, if any.
|
||||
InvokeExceptionListener(exception);
|
||||
// now try to recover the shared Connection and all consumers...
|
||||
if (logger.IsInfoEnabled)
|
||||
@@ -178,7 +210,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
/// registering a MessageListener for the specified listener
|
||||
/// </summary>
|
||||
/// <param name="session">The session to work on.</param>
|
||||
/// <param name="session">The session to work on.</param>
|
||||
/// <returns>the MessageConsumer"/></returns>
|
||||
/// <exception cref="NMSException">if thrown by NMS methods</exception>
|
||||
private IMessageConsumer CreateListenerConsumer(ISession session)
|
||||
{
|
||||
@@ -216,6 +248,12 @@ namespace Spring.Messaging.Nms.Listener
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a MessageConsumer for the given Session and Destination.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to create a MessageConsumer for.</param>
|
||||
/// <param name="destination">The destination to create a MessageConsumer for.</param>
|
||||
/// <returns>The new MessageConsumer</returns>
|
||||
protected IMessageConsumer CreateConsumer(ISession session, IDestination destination)
|
||||
{
|
||||
// Only pass in the NoLocal flag in case of a Topic:
|
||||
|
||||
@@ -25,10 +25,10 @@ namespace Spring.Messaging.Nms
|
||||
/// <summary>
|
||||
/// Delegate that creates a NMS message given a ISession
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS ISession to be used to create the
|
||||
/// <code>IMessage</code> (never <code>null</code>)
|
||||
/// <param name="session">the NMS Session to be used to create the
|
||||
/// <code>Message</code> (never <code>null</code>)
|
||||
/// </param>
|
||||
/// <returns> the <code>IMessage</code> to be sent
|
||||
/// <returns> the <code>Message</code> to be sent
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
public delegate IMessage IMessageCreatorDelegate(ISession session);
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace Spring.Messaging.Nms
|
||||
/// Convenient super class for application classes that need NMS access.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Requires a IConnectionFactory or a NmsTemplate instance to be set.
|
||||
/// It will create its own NmsTemplate if a IConnectionFactory is passed in.
|
||||
/// A custom NmsTemplate instance can be created for a given IConnectionFactory
|
||||
/// Requires a ConnectionFactory or a NmsTemplate instance to be set.
|
||||
/// It will create its own NmsTemplate if a ConnectionFactory is passed in.
|
||||
/// A custom NmsTemplate instance can be created for a given ConnectionFactory
|
||||
/// through overriding the <code>createNmsTemplate</code> method.
|
||||
///
|
||||
/// </remarks>
|
||||
@@ -40,7 +40,7 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
#region Logging
|
||||
|
||||
protected readonly ILog logger = LogManager.GetLogger(typeof(NmsGatewaySupport));
|
||||
private readonly ILog logger = LogManager.GetLogger(typeof(NmsGatewaySupport));
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets he NMS connection factory to be used by the gateway.
|
||||
/// Will automatically create a NmsTemplate for the given IConnectionFactory.
|
||||
/// Will automatically create a NmsTemplate for the given ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <value>The connection factory.</value>
|
||||
public IConnectionFactory ConnectionFactory
|
||||
@@ -75,9 +75,9 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NmsTemplate for the given IConnectionFactory.
|
||||
/// Creates a NmsTemplate for the given ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <remarks>Only invoked if populating the gateway with a IConnectionFactory reference.
|
||||
/// <remarks>Only invoked if populating the gateway with a ConnectionFactory reference.
|
||||
/// Can be overridden in subclasses to provide a different NmsTemplate instance
|
||||
/// </remarks>
|
||||
///
|
||||
@@ -88,6 +88,9 @@ namespace Spring.Messaging.Nms
|
||||
return new NmsTemplate(connectionFactory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the JmsTemplate is specified and calls <see cref="InitGateway"/>.
|
||||
/// </summary>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
if (jmsTemplate == null)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
using System;
|
||||
using Common.Logging;
|
||||
using Spring.Messaging.Nms.Connection;
|
||||
using Spring.Messaging.Nms.Connections;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Spring.Messaging.Nms.Support.Converter;
|
||||
using Spring.Messaging.Nms.Support.IDestinations;
|
||||
@@ -37,7 +37,7 @@ namespace Spring.Messaging.Nms
|
||||
/// For other operations, this is not necessary.
|
||||
/// Point-to-Point (Queues) is the default domain.</para>
|
||||
///
|
||||
/// <para>Default settings for NMS ISessions are "not transacted" and "auto-acknowledge".</para>
|
||||
/// <para>Default settings for NMS Sessions is "auto-acknowledge".</para>
|
||||
///
|
||||
/// <para>This template uses a DynamicDestinationResolver and a SimpleMessageConverter
|
||||
/// as default strategies for resolving a destination name or converting a message,
|
||||
@@ -57,12 +57,14 @@ namespace Spring.Messaging.Nms
|
||||
#endregion
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Timeout value indicating that a receive operation should
|
||||
/// check if a message is immediately available without blocking.
|
||||
/// </summary>
|
||||
public static readonly long DEFAULT_RECEIVE_TIMEOUT = -1;
|
||||
|
||||
|
||||
private NmsTemplateResourceFactory transactionalResourceFactory;
|
||||
|
||||
|
||||
private object defaultDestination;
|
||||
|
||||
private IMessageConverter messageConverter;
|
||||
@@ -92,9 +94,9 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
/// <summary> Create a new NmsTemplate.</summary>
|
||||
/// <remarks>
|
||||
/// <para>Note: The IConnectionFactory has to be set before using the instance.
|
||||
/// <para>Note: The ConnectionFactory has to be set before using the instance.
|
||||
/// This constructor can be used to prepare a NmsTemplate via an ObjectFactory,
|
||||
/// typically setting the IConnectionFactory.</para>
|
||||
/// typically setting the ConnectionFactory.</para>
|
||||
/// </remarks>
|
||||
public NmsTemplate()
|
||||
{
|
||||
@@ -103,8 +105,8 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Create a new NmsTemplate, given a IConnectionFactory.</summary>
|
||||
/// <param name="connectionFactory">the IConnectionFactory to obtain IConnections from
|
||||
/// <summary> Create a new NmsTemplate, given a ConnectionFactory.</summary>
|
||||
/// <param name="connectionFactory">the ConnectionFactory to obtain IConnections from
|
||||
/// </param>
|
||||
public NmsTemplate(IConnectionFactory connectionFactory)
|
||||
: this()
|
||||
@@ -134,6 +136,7 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CheckMessageConverter()
|
||||
{
|
||||
if (MessageConverter == null)
|
||||
@@ -143,12 +146,12 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Execute the action specified by the given action object within a
|
||||
/// NMS ISession.
|
||||
/// NMS Session.
|
||||
/// </summary>
|
||||
/// <remarks> Generalized version of <code>execute(ISessionCallback)</code>,
|
||||
/// allowing the NMS IConnection to be started on the fly.
|
||||
/// allowing the NMS Connection to be started on the fly.
|
||||
/// <p>Use <code>execute(ISessionCallback)</code> for the general case.
|
||||
/// Starting the NMS IConnection is just necessary for receiving messages,
|
||||
/// Starting the NMS Connection is just necessary for receiving messages,
|
||||
/// which is preferably achieved through the <code>receive</code> methods.</p>
|
||||
/// </remarks>
|
||||
/// <param name="action">callback object that exposes the session
|
||||
@@ -167,7 +170,8 @@ namespace Spring.Messaging.Nms
|
||||
try
|
||||
{
|
||||
ISession sessionToUse =
|
||||
ConnectionFactoryUtils.DoGetTransactionalSession(ConnectionFactory, transactionalResourceFactory);
|
||||
ConnectionFactoryUtils.DoGetTransactionalSession(ConnectionFactory, transactionalResourceFactory,
|
||||
startConnection);
|
||||
if (sessionToUse == null)
|
||||
{
|
||||
conToClose = CreateConnection();
|
||||
@@ -184,11 +188,10 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
return action.DoInNms(sessionToUse);
|
||||
}
|
||||
//TODO make sure don't want to do exception translation.
|
||||
finally
|
||||
{
|
||||
NmsUtils.CloseSession(sessionToClose);
|
||||
ConnectionFactoryUtils.ReleaseConnection(conToClose, ConnectionFactory, startConnection);
|
||||
ConnectionFactoryUtils.ReleaseConnection(conToClose, ConnectionFactory, startConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,12 +248,10 @@ namespace Spring.Messaging.Nms
|
||||
set { messageConverter = value; }
|
||||
}
|
||||
|
||||
|
||||
//TODO check tibco support for message id...prob yes..
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether IMessageIds are.
|
||||
/// Gets or sets a value indicating whether Message Ids are enabled.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if [message id enabled]; otherwise, <c>false</c>.</value>
|
||||
/// <value><c>true</c> if message id enabled; otherwise, <c>false</c>.</value>
|
||||
virtual public bool MessageIdEnabled
|
||||
{
|
||||
get { return messageIdEnabled; }
|
||||
@@ -258,7 +259,6 @@ namespace Spring.Messaging.Nms
|
||||
set { messageIdEnabled = value; }
|
||||
}
|
||||
|
||||
//TODO check tibco support for message id...prob yes.., so don't really need it then.
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether message timestamps are enabled.
|
||||
/// </summary>
|
||||
@@ -326,9 +326,6 @@ namespace Spring.Messaging.Nms
|
||||
set { persistent = value; }
|
||||
}
|
||||
|
||||
|
||||
//TODO verify admin...
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the priority when sending.
|
||||
/// </summary>
|
||||
@@ -358,6 +355,11 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Extract the content from the given JMS message.
|
||||
/// </summary>
|
||||
/// <param name="message">The Message to convert (can be <code>null</code>).</param>
|
||||
/// <returns>The content of the message, or <code>null</code> if none</returns>
|
||||
protected virtual object DoConvertFromMessage(IMessage message)
|
||||
{
|
||||
if (message != null)
|
||||
@@ -369,7 +371,7 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
#region NMS Factory Methods
|
||||
|
||||
/// <summary> Fetch an appropriate IConnection from the given NmsResourceHolder.
|
||||
/// <summary> Fetch an appropriate Connection from the given NmsResourceHolder.
|
||||
/// </summary>
|
||||
/// <param name="holder">the NmsResourceHolder
|
||||
/// </param>
|
||||
@@ -381,7 +383,7 @@ namespace Spring.Messaging.Nms
|
||||
return holder.GetConnection();
|
||||
}
|
||||
|
||||
/// <summary> Fetch an appropriate ISession from the given NmsResourceHolder.
|
||||
/// <summary> Fetch an appropriate Session from the given NmsResourceHolder.
|
||||
/// </summary>
|
||||
/// <param name="holder">the NmsResourceHolder
|
||||
/// </param>
|
||||
@@ -393,16 +395,16 @@ namespace Spring.Messaging.Nms
|
||||
return holder.GetSession();
|
||||
}
|
||||
|
||||
/// <summary> Create a NMS IMessageProducer for the given ISession and IDestination,
|
||||
/// <summary> Create a NMS MessageProducer for the given Session and Destination,
|
||||
/// configuring it to disable message ids and/or timestamps (if necessary).
|
||||
/// <p>Delegates to <code>doCreateProducer</code> for creation of the raw
|
||||
/// NMS IMessageProducer, which needs to be specific to NMS 1.1 or 1.0.2.</p>
|
||||
/// NMS MessageProducer</p>
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS ISession to create a IMessageProducer for
|
||||
/// <param name="session">the NMS Session to create a MessageProducer for
|
||||
/// </param>
|
||||
/// <param name="destination">the NMS IDestination to create a IMessageProducer for
|
||||
/// <param name="destination">the NMS Destination to create a MessageProducer for
|
||||
/// </param>
|
||||
/// <returns> the new NMS IMessageProducer
|
||||
/// <returns> the new NMS MessageProducer
|
||||
/// </returns>
|
||||
/// <throws> NMSException if thrown by NMS API methods </throws>
|
||||
/// <seealso cref="DoCreateProducer">
|
||||
@@ -426,14 +428,33 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Create a raw NMS IMessageProducer for the given ISession and IDestination.
|
||||
/// <p>This implementation uses NMS 1.1 API.</p>
|
||||
/// <summary>
|
||||
/// Determines whether the given Session is locally transacted, that is, whether
|
||||
/// its transaction is managed by this template class's Session handling
|
||||
/// and not by an external transaction coordinator.
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS ISession to create a IMessageProducer for
|
||||
/// <remarks>
|
||||
/// The Session's own transacted flag will already have been checked
|
||||
/// before. This method is about finding out whether the Session's transaction
|
||||
/// is local or externally coordinated.
|
||||
/// </remarks>
|
||||
/// <param name="session">The session to check.</param>
|
||||
/// <returns>
|
||||
/// <c>true</c> if the session is locally transacted; otherwise, <c>false</c>.
|
||||
/// </returns>
|
||||
protected virtual bool IsSessionLocallyTransacted(ISession session)
|
||||
{
|
||||
return SessionTransacted &&
|
||||
!ConnectionFactoryUtils.IsSessionTransactional(session, ConnectionFactory);
|
||||
}
|
||||
|
||||
/// <summary> Create a raw NMS MessageProducer for the given Session and Destination.
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS Session to create a MessageProducer for
|
||||
/// </param>
|
||||
/// <param name="destination">the NMS IDestination to create a IMessageProducer for
|
||||
/// <param name="destination">the NMS IDestination to create a MessageProducer for
|
||||
/// </param>
|
||||
/// <returns> the new NMS IMessageProducer
|
||||
/// <returns> the new NMS MessageProducer
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
protected virtual IMessageProducer DoCreateProducer(ISession session, IDestination destination)
|
||||
@@ -441,12 +462,11 @@ namespace Spring.Messaging.Nms
|
||||
return session.CreateProducer(destination);
|
||||
}
|
||||
|
||||
/// <summary> Create a NMS IMessageConsumer for the given ISession and IDestination.
|
||||
/// <p>This implementation uses NMS 1.1 API.</p>
|
||||
/// <summary> Create a NMS MessageConsumer for the given Session and Destination.
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS ISession to create a IMessageConsumer for
|
||||
/// <param name="session">the NMS Session to create a MessageConsumer for
|
||||
/// </param>
|
||||
/// <param name="destination">the NMS IDestination to create a IMessageConsumer for
|
||||
/// <param name="destination">the NMS Destination to create a MessageConsumer for
|
||||
/// </param>
|
||||
/// <param name="messageSelector">the message selector for this consumer (can be <code>null</code>)
|
||||
/// </param>
|
||||
@@ -469,14 +489,24 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
}
|
||||
|
||||
//TODO refactor to not pass null as a 'switch' for behavior.
|
||||
|
||||
/// <summary>
|
||||
/// Send the given message.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <param name="destination">The destination to send to.</param>
|
||||
/// <param name="messageCreatorDelegate">The message creator delegate callback to create a Message.</param>
|
||||
protected internal virtual void DoSend(ISession session, IDestination destination, IMessageCreatorDelegate messageCreatorDelegate)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(messageCreatorDelegate, "IMessageCreatorDelegate must not be null");
|
||||
DoSend(session, destination, null, messageCreatorDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send the given message.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <param name="destination">The destination to send to.</param>
|
||||
/// <param name="messageCreator">The message creator callback to create a Message.</param>
|
||||
protected internal virtual void DoSend(ISession session, IDestination destination, IMessageCreator messageCreator)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(messageCreator, "IMessageCreator must not be null");
|
||||
@@ -484,13 +514,13 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Send the given NMS message.</summary>
|
||||
/// <param name="session">the NMS ISession to operate on
|
||||
/// <param name="session">the NMS Session to operate on
|
||||
/// </param>
|
||||
/// <param name="destination">the NMS IDestination to send to
|
||||
/// <param name="destination">the NMS Destination to send to
|
||||
/// </param>
|
||||
/// <param name="messageCreator">callback to create a NMS IMessage
|
||||
/// <param name="messageCreator">callback to create a NMS Message
|
||||
/// </param>
|
||||
/// <param name="messageCreatorDelegate">delegate callback to create a NMS IMessage
|
||||
/// <param name="messageCreatorDelegate">delegate callback to create a NMS Message
|
||||
/// </param>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
protected internal virtual void DoSend(ISession session, IDestination destination, IMessageCreator messageCreator,
|
||||
@@ -516,8 +546,8 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
DoSend(producer, message);
|
||||
|
||||
// Check commit - avoid commit call within a JTA transaction.
|
||||
if (session.Transacted && !TransactionSynchronizationManager.HasResource(ConnectionFactory))
|
||||
// Check commit, avoid commit call is Session transaction is externally coordinated.
|
||||
if (session.Transacted && IsSessionLocallyTransacted(session))
|
||||
{
|
||||
// Transacted session created by this template -> commit.
|
||||
NmsUtils.CommitIfNecessary(session);
|
||||
@@ -531,9 +561,9 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
|
||||
/// <summary> Actually send the given NMS message.</summary>
|
||||
/// <param name="producer">the NMS IMessageProducer to send with
|
||||
/// <param name="producer">the NMS MessageProducer to send with
|
||||
/// </param>
|
||||
/// <param name="message">the NMS IMessage to send
|
||||
/// <param name="message">the NMS Message to send
|
||||
/// </param>
|
||||
/// <throws> NMSException if thrown by NMS API methods </throws>
|
||||
protected virtual void DoSend(IMessageProducer producer, IMessage message)
|
||||
@@ -554,10 +584,10 @@ namespace Spring.Messaging.Nms
|
||||
#region INmsOperations Implementation
|
||||
|
||||
/// <summary> Execute the action specified by the given action object within
|
||||
/// a NMS ISession.
|
||||
/// <p>Note: The value of isPubSubDomain affects the behavior of this method.
|
||||
/// If isPubSubDomain equals true, then a ISession is passed to the callback.
|
||||
/// If false, then a ISession is passed to the callback.</p>
|
||||
/// a NMS Session.
|
||||
/// <p>Note: The value of PubSubDomain affects the behavior of this method.
|
||||
/// If PubSubDomain equals true, then a Session is passed to the callback.
|
||||
/// If false, then a Session is passed to the callback.</p>
|
||||
/// </summary>
|
||||
/// <param name="action">callback object that exposes the session
|
||||
/// </param>
|
||||
@@ -570,7 +600,7 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Send a message to a NMS destination. The callback gives access to
|
||||
/// the NMS session and IMessageProducer in order to do more complex
|
||||
/// the NMS session and MessageProducer in order to do more complex
|
||||
/// send operations.
|
||||
/// </summary>
|
||||
/// <param name="action">callback object that exposes the session/producer pair
|
||||
@@ -603,7 +633,7 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The MessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination to send this message to
|
||||
/// </param>
|
||||
@@ -616,7 +646,7 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The MessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destinationName">the name of the destination to send this message to
|
||||
/// (to be resolved to an actual destination by a DestinationResolver)
|
||||
@@ -649,7 +679,7 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The MessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destination">the destination to send this message to
|
||||
/// </param>
|
||||
@@ -663,7 +693,7 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
/// <summary> Send a message to the specified destination.
|
||||
/// The IMessageCreator callback creates the message given a ISession.
|
||||
/// The MessageCreator callback creates the message given a Session.
|
||||
/// </summary>
|
||||
/// <param name="destinationName">the destination to send this message to
|
||||
/// </param>
|
||||
@@ -898,12 +928,25 @@ namespace Spring.Messaging.Nms
|
||||
return Execute(new ReceiveSelectedCallback(this, destinationName, messageSelector), true) as IMessage;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Receive a message.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <param name="destination">The destination to receive from.</param>
|
||||
/// <param name="messageSelector">The message selector for this consumer (can be <code>null</code></param>
|
||||
/// <returns>The Message received, or <code>null</code> if none.</returns>
|
||||
protected virtual IMessage DoReceive(ISession session, IDestination destination, string messageSelector)
|
||||
{
|
||||
return DoReceive(session, CreateConsumer(session, destination, messageSelector));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Receive a message.
|
||||
/// </summary>
|
||||
/// <param name="session">The session to operate on.</param>
|
||||
/// <param name="consumer">The consumer to receive with.</param>
|
||||
/// <returns>The Message received, or <code>null</code> if none</returns>
|
||||
protected virtual IMessage DoReceive(ISession session, IMessageConsumer consumer)
|
||||
{
|
||||
try
|
||||
@@ -920,14 +963,14 @@ namespace Spring.Messaging.Nms
|
||||
: consumer.Receive();
|
||||
if (session.Transacted)
|
||||
{
|
||||
// Commit necessary - but avoid commit call within a JTA transaction.
|
||||
if (resourceHolder == null)
|
||||
// Commit necessary - but avoid commit call is Session transaction is externally coordinated.
|
||||
if (IsSessionLocallyTransacted(session))
|
||||
{
|
||||
// Transacted session created by this template -> commit.
|
||||
NmsUtils.CommitIfNecessary(session);
|
||||
}
|
||||
}
|
||||
else if (ClientAcknowledge(session))
|
||||
else if (IsClientAcknowledge(session))
|
||||
{
|
||||
// Manually acknowledge message, if any.
|
||||
if (message != null)
|
||||
@@ -1060,6 +1103,9 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
#region Supporting Internal Classes
|
||||
|
||||
/// <summary>
|
||||
/// ResourceFactory implementation that delegates to this template's callback methods.
|
||||
/// </summary>
|
||||
private class NmsTemplateResourceFactory : ConnectionFactoryUtils.ResourceFactory
|
||||
{
|
||||
private NmsTemplate enclosingTemplateInstance;
|
||||
@@ -1074,34 +1120,34 @@ namespace Spring.Messaging.Nms
|
||||
enclosingTemplateInstance = enclosingInstance;
|
||||
}
|
||||
|
||||
public NmsTemplate Enclosing_Instance
|
||||
public NmsTemplate EnclosingInstance
|
||||
{
|
||||
get { return enclosingTemplateInstance; }
|
||||
}
|
||||
|
||||
public virtual IConnection GetConnection(NmsResourceHolder holder)
|
||||
{
|
||||
return Enclosing_Instance.GetConnection(holder);
|
||||
return EnclosingInstance.GetConnection(holder);
|
||||
}
|
||||
|
||||
public virtual ISession GetSession(NmsResourceHolder holder)
|
||||
{
|
||||
return Enclosing_Instance.GetSession(holder);
|
||||
return EnclosingInstance.GetSession(holder);
|
||||
}
|
||||
|
||||
public virtual IConnection CreateConnection()
|
||||
{
|
||||
return Enclosing_Instance.CreateConnection();
|
||||
return EnclosingInstance.CreateConnection();
|
||||
}
|
||||
|
||||
public virtual ISession CreateSession(IConnection con)
|
||||
{
|
||||
return Enclosing_Instance.CreateSession(con);
|
||||
return EnclosingInstance.CreateSession(con);
|
||||
}
|
||||
|
||||
public bool SynchedLocalTransactionAllowed
|
||||
{
|
||||
get { return Enclosing_Instance.SessionTransacted; }
|
||||
get { return EnclosingInstance.SessionTransacted; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,25 +31,25 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public interface IMessageConverter
|
||||
{
|
||||
/// <summary> Convert a .NET object to a NMS IMessage using the supplied session
|
||||
/// <summary> Convert a .NET object to a NMS Message using the supplied session
|
||||
/// to create the message object.
|
||||
/// </summary>
|
||||
/// <param name="objectToConvert">the object to convert
|
||||
/// </param>
|
||||
/// <param name="session">the ISession to use for creating a NMS IMessage
|
||||
/// <param name="session">the Session to use for creating a NMS Message
|
||||
/// </param>
|
||||
/// <returns> the NMS IMessage
|
||||
/// <returns> the NMS Message
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
/// <throws>IMessageConversionException in case of conversion failure </throws>
|
||||
/// <throws>MessageConversionException in case of conversion failure </throws>
|
||||
IMessage ToMessage(object objectToConvert, ISession session);
|
||||
|
||||
/// <summary> Convert from a NMS IMessage to a .NET object.</summary>
|
||||
/// <summary> Convert from a NMS Message to a .NET object.</summary>
|
||||
/// <param name="message">the message to convert
|
||||
/// </param>
|
||||
/// <returns> the converted .NET object
|
||||
/// </returns>
|
||||
/// <throws>IMessageConversionException in case of conversion failure </throws>
|
||||
/// <throws>MessageConversionException in case of conversion failure </throws>
|
||||
object FromMessage(IMessage message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,24 +19,18 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Support.Converter
|
||||
{
|
||||
/// <summary> Thrown by IMessageConverter implementations when the conversion
|
||||
/// of an object to/from a IMessage fails.
|
||||
///
|
||||
/// of an object to/from a Message fails.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
[Serializable]
|
||||
public class IMessageConversionException : ApplicationException
|
||||
public class MessageConversionException : NMSException
|
||||
{
|
||||
//TODO add jms root exception hierarchy?....
|
||||
#region Constructor (s) / Destructor
|
||||
/// <summary>Creates a new instance of the IMessageConverterException class.</summary>
|
||||
public IMessageConversionException()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the IMessageConverterException class. with the specified message.
|
||||
@@ -44,7 +38,7 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
/// <param name="message">
|
||||
/// A message about the exception.
|
||||
/// </param>
|
||||
public IMessageConversionException(string message)
|
||||
public MessageConversionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
@@ -59,27 +53,11 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
/// <param name="rootCause">
|
||||
/// The root exception that is being wrapped.
|
||||
/// </param>
|
||||
public IMessageConversionException(string message, Exception rootCause)
|
||||
public MessageConversionException(string message, Exception rootCause)
|
||||
: base(message, rootCause)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the IMessageConverterException class.
|
||||
/// </summary>
|
||||
/// <param name="info">
|
||||
/// The <see cref="System.Runtime.Serialization.SerializationInfo"/>
|
||||
/// that holds the serialized object data about the exception being thrown.
|
||||
/// </param>
|
||||
/// <param name="context">
|
||||
/// The <see cref="System.Runtime.Serialization.StreamingContext"/>
|
||||
/// that contains contextual information about the source or destination.
|
||||
/// </param>
|
||||
protected IMessageConversionException(
|
||||
SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,17 +39,17 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class SimpleMessageConverter : IMessageConverter
|
||||
{
|
||||
/// <summary> Convert a .NET object to a NMS IMessage using the supplied session
|
||||
/// <summary> Convert a .NET object to a NMS Message using the supplied session
|
||||
/// to create the message object.
|
||||
/// </summary>
|
||||
/// <param name="objectToConvert">the object to convert
|
||||
/// </param>
|
||||
/// <param name="session">the ISession to use for creating a NMS IMessage
|
||||
/// <param name="session">the Session to use for creating a NMS Message
|
||||
/// </param>
|
||||
/// <returns> the NMS IMessage
|
||||
/// <returns> the NMS Message
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
/// <throws>IMessageConversionException in case of conversion failure </throws>
|
||||
/// <throws>MessageConversionException in case of conversion failure </throws>
|
||||
public IMessage ToMessage(object objectToConvert, ISession session)
|
||||
{
|
||||
if (objectToConvert is IMessage)
|
||||
@@ -75,16 +75,16 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IMessageConversionException("Cannot convert object [" + objectToConvert + "] to NMS message");
|
||||
throw new MessageConversionException("Cannot convert object [" + objectToConvert + "] to NMS message");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Convert from a NMS IMessage to a .NET object.</summary>
|
||||
/// <summary> Convert from a NMS Message to a .NET object.</summary>
|
||||
/// <param name="message">the message to convert
|
||||
/// </param>
|
||||
/// <returns> the converted .NET object
|
||||
/// </returns>
|
||||
/// <throws>IMessageConversionException in case of conversion failure </throws>
|
||||
/// <throws>MessageConversionException in case of conversion failure </throws>
|
||||
public object FromMessage(IMessage message)
|
||||
{
|
||||
if (message is ITextMessage)
|
||||
@@ -155,7 +155,7 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
if (!(entry.Key is string))
|
||||
{
|
||||
//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Class.getName' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
|
||||
throw new IMessageConversionException("Cannot convert non-String key of type [" +
|
||||
throw new MessageConversionException("Cannot convert non-String key of type [" +
|
||||
(entry.Key != null ? entry.Key.GetType().FullName : null) +
|
||||
"] to IMapMessage entry");
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
/// </param>
|
||||
/// <returns> the resulting Map
|
||||
/// </returns>
|
||||
/// <throws> NMSException if thrown by NMS methods </throws>
|
||||
/// <throws>NMSException if thrown by NMS methods </throws>
|
||||
protected virtual IDictionary ExtractMapFromMessage(IMapMessage message)
|
||||
{
|
||||
IDictionary dictionary = new Hashtable();
|
||||
@@ -222,6 +222,11 @@ namespace Spring.Messaging.Nms.Support.Converter
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the serializable object from the given object message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message to convert.</param>
|
||||
/// <returns>The resulting serializable object.</returns>
|
||||
protected virtual object ExtractSerializableFromMessage(
|
||||
IObjectMessage message)
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace Spring.Messaging.Nms.Support.IDestinations
|
||||
/// <summary> Resolve the given destination name, either as located resource
|
||||
/// or as dynamic destination.
|
||||
/// </summary>
|
||||
/// <param name="session">the current NMS ISession
|
||||
/// <param name="session">the current NMS Session
|
||||
/// </param>
|
||||
/// <param name="destinationName">the name of the destination
|
||||
/// </param>
|
||||
@@ -58,7 +58,7 @@ namespace Spring.Messaging.Nms.Support.IDestinations
|
||||
|
||||
|
||||
/// <summary> Resolve the given destination name to a Topic.</summary>
|
||||
/// <param name="session">the current NMS ISession
|
||||
/// <param name="session">the current NMS Session
|
||||
/// </param>
|
||||
/// <param name="topicName">the name of the desired Topic.
|
||||
/// </param>
|
||||
@@ -70,6 +70,14 @@ namespace Spring.Messaging.Nms.Support.IDestinations
|
||||
return session.GetTopic(topicName);
|
||||
}
|
||||
|
||||
/// <summary> Resolve the given destination name to a Queue.</summary>
|
||||
/// <param name="session">the current NMS Session
|
||||
/// </param>
|
||||
/// <param name="queueName">the name of the desired Queue.
|
||||
/// </param>
|
||||
/// <returns> the NMS Queue name
|
||||
/// </returns>
|
||||
/// <throws>NMSException if resolution failed </throws>
|
||||
protected internal virtual IDestination ResolveQueue(ISession session, string queueName)
|
||||
{
|
||||
return session.GetQueue(queueName);
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Spring.Messaging.Nms.Support.IDestinations
|
||||
/// <summary> Resolve the given destination name, either as located resource
|
||||
/// or as dynamic destination.
|
||||
/// </summary>
|
||||
/// <param name="session">the current NMS ISession
|
||||
/// <param name="session">the current NMS Session
|
||||
/// </param>
|
||||
/// <param name="destinationName">the name of the destination
|
||||
/// </param>
|
||||
|
||||
@@ -25,14 +25,12 @@ using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Support
|
||||
{
|
||||
/// <summary> Base class for NmsTemplate and other
|
||||
/// NMS-accessing gateway helpers</summary>
|
||||
/// <remarks>It defines common properties like the
|
||||
/// IConnectionFactory}. The subclass
|
||||
/// NmsIDestinationAccessor adds
|
||||
/// further, destination-related properties.
|
||||
///
|
||||
/// <summary> Base class for NmsTemplate and other NMS-accessing gateway helpers</summary>
|
||||
/// <remarks>It defines common properties like the ConnectionFactory}. The subclass
|
||||
/// NmsIDestinationAccessor adds further, destination-related properties.
|
||||
/// <para>
|
||||
/// Not intended to be used directly. See NmsTemplate.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
@@ -47,7 +45,7 @@ namespace Spring.Messaging.Nms.Support
|
||||
#region Fields
|
||||
|
||||
private IConnectionFactory connectionFactory;
|
||||
private bool sessionTransacted = false;
|
||||
|
||||
private AcknowledgementMode sessionAcknowledgeMode = AcknowledgementMode.AutoAcknowledge;
|
||||
|
||||
#endregion
|
||||
@@ -56,7 +54,7 @@ namespace Spring.Messaging.Nms.Support
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection factory to use for obtaining NMS IConnections.
|
||||
/// Gets or sets the connection factory to use for obtaining NMS Connections.
|
||||
/// </summary>
|
||||
/// <value>The connection factory.</value>
|
||||
virtual public IConnectionFactory ConnectionFactory
|
||||
@@ -78,8 +76,7 @@ namespace Spring.Messaging.Nms.Support
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Set the NMS acknowledgement mode that is used when creating a NMS
|
||||
/// ISession to send a message. The default is ISession.AUTO_ACKNOWLEDGE.
|
||||
/// <p>Vendor-specific extensions to the acknowledgment mode can be set here as well.</p>
|
||||
/// Session to send a message. The default is AUTO_ACKNOWLEDGE.
|
||||
/// </remarks>
|
||||
/// <value>The session acknowledge mode.</value>
|
||||
virtual public AcknowledgementMode SessionAcknowledgeMode
|
||||
@@ -112,7 +109,10 @@ namespace Spring.Messaging.Nms.Support
|
||||
/// </remarks>
|
||||
public bool SessionTransacted
|
||||
{
|
||||
get { return SessionAcknowledgeMode == AcknowledgementMode.Transactional; }
|
||||
get
|
||||
{
|
||||
return SessionAcknowledgeMode == AcknowledgementMode.Transactional;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
@@ -125,6 +125,9 @@ namespace Spring.Messaging.Nms.Support
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Verify that ConnectionFactory property has been set.
|
||||
/// </summary>
|
||||
public virtual void AfterPropertiesSet()
|
||||
{
|
||||
if (ConnectionFactory == null)
|
||||
@@ -142,6 +145,11 @@ namespace Spring.Messaging.Nms.Support
|
||||
return ConnectionFactory.CreateConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the session for the given Connection
|
||||
/// </summary>
|
||||
/// <param name="con">The connection to create a session for.</param>
|
||||
/// <returns>The new session</returns>
|
||||
protected virtual ISession CreateSession(IConnection con)
|
||||
{
|
||||
return con.CreateSession(SessionAcknowledgeMode);
|
||||
@@ -150,9 +158,9 @@ namespace Spring.Messaging.Nms.Support
|
||||
/// <summary>
|
||||
/// Returns whether the ISession is in client acknowledgement mode.
|
||||
/// </summary>
|
||||
/// <param name="session">The session.</param>
|
||||
/// <returns>true ifin client ack mode, false otherwise</returns>
|
||||
protected virtual bool ClientAcknowledge(ISession session)
|
||||
/// <param name="session">The session to check.</param>
|
||||
/// <returns>true if in client ack mode, false otherwise</returns>
|
||||
protected virtual bool IsClientAcknowledge(ISession session)
|
||||
{
|
||||
return (session.AcknowledgementMode == AcknowledgementMode.ClientAcknowledge);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@ using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic utility methods for working with NMS. Mainly for internal use
|
||||
/// within the framework, but also useful for custom NMS access code.
|
||||
/// </summary>
|
||||
public abstract class NmsUtils
|
||||
{
|
||||
#region Logging
|
||||
@@ -33,20 +37,20 @@ namespace Spring.Messaging.Nms.Support
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary> Close the given NMS IConnection and ignore any thrown exception.
|
||||
/// <summary> Close the given NMS Connection and ignore any thrown exception.
|
||||
/// This is useful for typical <code>finally</code> blocks in manual NMS code.
|
||||
/// </summary>
|
||||
/// <param name="con">the NMS IConnection to close (may be <code>null</code>)
|
||||
/// <param name="con">the NMS Connection to close (may be <code>null</code>)
|
||||
/// </param>
|
||||
public static void CloseConnection(IConnection con)
|
||||
{
|
||||
CloseConnection(con, false);
|
||||
}
|
||||
|
||||
/// <summary> Close the given NMS IConnection and ignore any thrown exception.
|
||||
/// <summary> Close the given NMS Connection and ignore any thrown exception.
|
||||
/// This is useful for typical <code>finally</code> blocks in manual NMS code.
|
||||
/// </summary>
|
||||
/// <param name="con">the NMS IConnection to close (may be <code>null</code>)
|
||||
/// <param name="con">the NMS Connection to close (may be <code>null</code>)
|
||||
/// </param>
|
||||
/// <param name="stop">whether to call <code>stop()</code> before closing
|
||||
/// </param>
|
||||
@@ -74,20 +78,20 @@ namespace Spring.Messaging.Nms.Support
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
logger.Debug("Could not close NMS IConnection", ex);
|
||||
logger.Debug("Could not close NMS Connection", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// We don't trust the NMS provider: It might throw another exception.
|
||||
logger.Debug("Unexpected exception on closing NMS IConnection", ex);
|
||||
logger.Debug("Unexpected exception on closing NMS Connection", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Close the given NMS ISession and ignore any thrown exception.
|
||||
/// <summary> Close the given NMS Session and ignore any thrown exception.
|
||||
/// This is useful for typical <code>finally</code> blocks in manual NMS code.
|
||||
/// </summary>
|
||||
/// <param name="session">the NMS ISession to close (may be <code>null</code>)
|
||||
/// <param name="session">the NMS Session to close (may be <code>null</code>)
|
||||
/// </param>
|
||||
public static void CloseSession(ISession session)
|
||||
{
|
||||
@@ -109,10 +113,10 @@ namespace Spring.Messaging.Nms.Support
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Close the given NMS IMessageProducer and ignore any thrown exception.
|
||||
/// <summary> Close the given NMS MessageProducer and ignore any thrown exception.
|
||||
/// This is useful for typical <code>finally</code> blocks in manual NMS code.
|
||||
/// </summary>
|
||||
/// <param name="producer">the NMS IMessageProducer to close (may be <code>null</code>)
|
||||
/// <param name="producer">the NMS MessageProducer to close (may be <code>null</code>)
|
||||
/// </param>
|
||||
public static void CloseMessageProducer(IMessageProducer producer)
|
||||
{
|
||||
@@ -124,20 +128,20 @@ namespace Spring.Messaging.Nms.Support
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
logger.Debug("Could not close NMS IMessageProducer", ex);
|
||||
logger.Debug("Could not close NMS MessageProducer", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// We don't trust the NMS provider: It might throw RuntimeException or Error.
|
||||
logger.Debug("Unexpected exception on closing NMS IMessageProducer", ex);
|
||||
logger.Debug("Unexpected exception on closing NMS MessageProducer", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Close the given NMS IMessageConsumer and ignore any thrown exception.
|
||||
/// <summary> Close the given NMS MessageConsumer and ignore any thrown exception.
|
||||
/// This is useful for typical <code>finally</code> blocks in manual NMS code.
|
||||
/// </summary>
|
||||
/// <param name="consumer">the NMS IMessageConsumer to close (may be <code>null</code>)
|
||||
/// <param name="consumer">the NMS MessageConsumer to close (may be <code>null</code>)
|
||||
/// </param>
|
||||
public static void CloseMessageConsumer(IMessageConsumer consumer)
|
||||
{
|
||||
@@ -149,12 +153,12 @@ namespace Spring.Messaging.Nms.Support
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
logger.Debug("Could not close NMS IMessageConsumer", ex);
|
||||
logger.Debug("Could not close NMS MessageConsumer", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// We don't trust the NMS provider: It might throw RuntimeException or Error.
|
||||
logger.Debug("Unexpected exception on closing NMS IMessageConsumer", ex);
|
||||
logger.Debug("Unexpected exception on closing NMS MessageConsumer", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,11 +190,11 @@ namespace Spring.Messaging.Nms.Support
|
||||
// }
|
||||
|
||||
|
||||
/// <summary> Commit the ISession if not within a distributed transaction.</summary>
|
||||
/// <remarks>Needs investigation - no distributed tx in EMS</remarks>
|
||||
/// <param name="session">the NMS ISession to commit
|
||||
/// <summary> Commit the Session if not within a distributed transaction.</summary>
|
||||
/// <remarks>Needs investigation - no distributed tx in .NET messaging providers</remarks>
|
||||
/// <param name="session">the NMS Session to commit
|
||||
/// </param>
|
||||
/// <throws> NMSException if committing failed </throws>
|
||||
/// <throws>NMSException if committing failed </throws>
|
||||
public static void CommitIfNecessary(ISession session)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(session, "ISession must not be null");
|
||||
@@ -212,9 +216,9 @@ namespace Spring.Messaging.Nms.Support
|
||||
// }
|
||||
}
|
||||
|
||||
/// <summary> Rollback the ISession if not within a distributed transaction.</summary>
|
||||
/// <summary> Rollback the Session if not within a distributed transaction.</summary>
|
||||
/// <remarks>Needs investigation - no distributed tx in EMS</remarks>
|
||||
/// <param name="session">the NMS ISession to rollback
|
||||
/// <param name="session">the NMS Session to rollback
|
||||
/// </param>
|
||||
/// <throws> NMSException if committing failed </throws>
|
||||
public static void RollbackIfNecessary(ISession session)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<DocumentationFile>..\..\..\build\VS.NET.2005\Spring.Messaging.Nms\Debug\Spring.Messaging.Nms.xml</DocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
@@ -67,7 +68,6 @@
|
||||
<Compile Include="Messaging\Nms\Listener\AbstractMessageListenerContainer.cs" />
|
||||
<Compile Include="Messaging\Nms\Listener\AbstractNmsListeningContainer.cs" />
|
||||
<Compile Include="Messaging\Nms\Listener\Adapter\MessageListenerAdapter.cs" />
|
||||
<Compile Include="Messaging\Nms\Listener\DefaultMessageListenerContainer.cs" />
|
||||
<Compile Include="Messaging\Nms\Listener\ISessionAwareMessageListener.cs" />
|
||||
<Compile Include="Messaging\Nms\Listener\LocallyExposedNmsResourceHolder.cs" />
|
||||
<Compile Include="Messaging\Nms\Listener\SimpleMessageListenerContainer.cs" />
|
||||
|
||||
Reference in New Issue
Block a user