From b6f610230fe166d4cfe34f3dbb727ed4653c4915 Mon Sep 17 00:00:00 2001
From: markpollack
Date: Fri, 25 Jul 2008 04:45:15 +0000
Subject: [PATCH] NMS development
---
.../Nms/Connections/CachedMessageProducer.cs | 92 ++++-
.../Nms/Connections/CachedSession.cs | 97 +++++-
.../Connections/CachingConnectionFactory.cs | 12 +-
.../Connections/ChainedExceptionListener.cs | 2 +-
.../Nms/Connections/ConnectionFactoryUtils.cs | 184 +++++-----
.../Nms/Connections/IDecoratorSession.cs | 6 +-
.../Connections/ISmartConnectionFactory.cs | 4 +-
.../Nms/Connections/NmsResourceHolder.cs | 98 ++++--
.../Nms/Connections/NmsTransactionManager.cs | 127 ++++++-
.../Connections/SingleConnectionFactory.cs | 134 ++++++--
.../SynchedLocalTransactionFailedException.cs | 2 +-
.../Messaging/Nms/IExceptionListener.cs | 4 +
.../Messaging/Nms/IMessageCreator.cs | 10 +-
.../Messaging/Nms/IMessageListener.cs | 7 +
.../Messaging/Nms/IMessagePostProcessor.cs | 2 +-
.../Messaging/Nms/INmsOperations.cs | 20 +-
.../Messaging/Nms/IProducerCallback.cs | 10 +-
.../Messaging/Nms/ISessionCallback.cs | 8 +-
.../AbstractMessageListenerContainer.cs | 124 ++++++-
.../Listener/AbstractNmsListeningContainer.cs | 69 +++-
.../Adapter/MessageListenerAdapter.cs | 319 +++++++++++++++---
.../DefaultMessageListenerContainer.cs | 6 -
.../Listener/ISessionAwareMessageListener.cs | 40 ++-
.../LocallyExposedNmsResourceHolder.cs | 2 +-
.../SimpleMessageListenerContainer.cs | 44 ++-
.../Messaging/Nms/MessageCreatorDelegate.cs | 6 +-
.../Messaging/Nms/NmsGatewaySupport.cs | 17 +-
.../Messaging/Nms/NmsTemplate.cs | 182 ++++++----
.../Support/Converter/IMessageConverter.cs | 12 +-
.../Converter/MessageConversionException.cs | 34 +-
.../Converter/SimpleMessageConverter.cs | 23 +-
.../DynamicDestinationResolver.cs | 12 +-
.../Destinations/IDestinationResolver.cs | 2 +-
.../Messaging/Nms/Support/NmsAccessor.cs | 38 ++-
.../Messaging/Nms/Support/NmsUtils.cs | 48 +--
.../Spring.Messaging.Nms.2005.csproj | 2 +-
36 files changed, 1373 insertions(+), 426 deletions(-)
delete mode 100644 src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/DefaultMessageListenerContainer.cs
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedMessageProducer.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedMessageProducer.cs
index b9238b47..91b7e078 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedMessageProducer.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedMessageProducer.cs
@@ -21,7 +21,7 @@
using System;
using Apache.NMS;
-namespace Spring.Messaging.Nms.Connection
+namespace Spring.Messaging.Nms.Connections
{
///
/// MessageProducer decorator that adapts specific settings
@@ -31,7 +31,7 @@ namespace Spring.Messaging.Nms.Connection
/// Mark Pollack (.NET)
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;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The target.
public CachedMessageProducer(IMessageProducer target)
{
this.target = target;
}
+ ///
+ /// Gets the target MessageProducer, the procder we are 'wrapping'
+ ///
+ /// The target MessageProducer.
public IMessageProducer Target
{
get { return target; }
}
+ ///
+ /// Sends the specified message.
+ ///
+ /// The message.
public void Send(IMessage message)
{
target.Send(message);
}
+ ///
+ /// Sends a message to the specified message.
+ ///
+ /// The message to send.
+ /// if set to true use persistent QOS.
+ /// The message priority.
+ /// The time to live.
public void Send(IMessage message, bool persistent, byte priority, TimeSpan timeToLive)
{
target.Send(message, persistent, priority, timeToLive);
}
+ ///
+ /// Sends a message to the specified destination.
+ ///
+ /// The destination.
+ /// The message.
public void Send(IDestination destination, IMessage message)
{
target.Send(destination, message);
}
+ ///
+ /// Sends a message the specified destination.
+ ///
+ /// The destination.
+ /// The message to send.
+ /// if set to true use persistent QOS.
+ /// The priority.
+ /// The time to live.
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.
+ ///
+ /// Creates the message.
+ ///
+ /// A new message
public IMessage CreateMessage()
{
return target.CreateMessage();
}
+ ///
+ /// Creates the text message.
+ ///
+ /// A new text message.
public ITextMessage CreateTextMessage()
{
return target.CreateTextMessage();
}
+ ///
+ /// Creates the text message.
+ ///
+ /// The text.
+ /// A texst message with the given text.
public ITextMessage CreateTextMessage(string text)
{
return target.CreateTextMessage(text);
}
+ ///
+ /// Creates the map message.
+ ///
+ /// a new map message.
public IMapMessage CreateMapMessage()
{
return target.CreateMapMessage();
}
+ ///
+ /// Creates the object message.
+ ///
+ /// The body.
+ /// A new object message with the given body.
public IObjectMessage CreateObjectMessage(object body)
{
return target.CreateObjectMessage(body);
}
+ ///
+ /// Creates the bytes message.
+ ///
+ /// A new bytes message.
public IBytesMessage CreateBytesMessage()
{
return target.CreateBytesMessage();
}
+ ///
+ /// Creates the bytes message.
+ ///
+ /// The body.
+ /// A new bytes message with the given body.
public IBytesMessage CreateBytesMessage(byte[] body)
{
return target.CreateBytesMessage(body);
}
#endregion
+ ///
+ /// Gets or sets a value indicating whether this uses a persistent QOS
+ ///
+ /// true if persistent; otherwise, false.
public bool Persistent
{
get { return persistent; }
set { persistent = value; }
}
+ ///
+ /// Gets or sets the time to live value for messages sent with this producer.
+ ///
+ /// The time to live.
public TimeSpan TimeToLive
{
get { return timeToLive; }
set { timeToLive = value; }
}
+ ///
+ /// Gets or sets the priority of messages sent with this producer.
+ ///
+ /// The priority.
public byte Priority
{
get { return priority; }
set { priority = value;}
}
+ ///
+ /// Gets or sets a value indicating whether disable setting of the message ID property.
+ ///
+ /// true if disable message ID setting; otherwise, false.
public bool DisableMessageID
{
get
@@ -153,6 +232,12 @@ namespace Spring.Messaging.Nms.Connection
}
}
+ ///
+ /// Gets or sets a value indicating whether disable setting the message timestamp property.
+ ///
+ ///
+ /// true if disable message timestamp; otherwise, false.
+ ///
public bool DisableMessageTimestamp
{
get
@@ -169,6 +254,9 @@ namespace Spring.Messaging.Nms.Connection
}
}
+ ///
+ /// Reset properties.
+ ///
public void Dispose()
{
// It's a cached MessageProducer... reset properties only.
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedSession.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedSession.cs
index 6c67e40f..8d57fb65 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedSession.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachedSession.cs
@@ -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
{
///
- /// 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
+ ///
+ /// Creates the consumer.
+ ///
+ /// The destination.
+ ///
public IMessageConsumer CreateConsumer(IDestination destination)
{
return target.CreateConsumer(destination);
}
+ ///
+ /// Creates the consumer.
+ ///
+ /// The destination.
+ /// The selector.
+ ///
public IMessageConsumer CreateConsumer(IDestination destination, string selector)
{
return target.CreateConsumer(destination, selector);
}
+ ///
+ /// Creates the consumer.
+ ///
+ /// The destination.
+ /// The selector.
+ /// if set to true [no local].
+ ///
public IMessageConsumer CreateConsumer(IDestination destination, string selector, bool noLocal)
{
return target.CreateConsumer(destination, selector, noLocal);
}
+
+ ///
+ /// Creates the durable consumer.
+ ///
+ /// The destination.
+ /// The name.
+ /// The selector.
+ /// if set to true [no local].
+ ///
public IMessageConsumer CreateDurableConsumer(ITopic destination, string name, string selector, bool noLocal)
{
return target.CreateDurableConsumer(destination, name, selector, noLocal);
}
+ ///
+ /// Gets the queue.
+ ///
+ /// The name.
+ ///
public IQueue GetQueue(string name)
{
return target.GetQueue(name);
}
+ ///
+ /// Gets the topic.
+ ///
+ /// The name.
+ ///
public ITopic GetTopic(string name)
{
return target.GetTopic(name);
}
+ ///
+ /// Creates the temporary queue.
+ ///
+ ///
public ITemporaryQueue CreateTemporaryQueue()
{
return target.CreateTemporaryQueue();
}
+ ///
+ /// Creates the temporary topic.
+ ///
+ ///
public ITemporaryTopic CreateTemporaryTopic()
{
return target.CreateTemporaryTopic();
}
+ ///
+ /// Creates the message.
+ ///
+ ///
public IMessage CreateMessage()
{
return target.CreateMessage();
}
+ ///
+ /// Creates the text message.
+ ///
+ ///
public ITextMessage CreateTextMessage()
{
return target.CreateTextMessage();
}
+ ///
+ /// Creates the text message.
+ ///
+ /// The text.
+ ///
public ITextMessage CreateTextMessage(string text)
{
return target.CreateTextMessage(text);
}
+ ///
+ /// Creates the map message.
+ ///
+ ///
public IMapMessage CreateMapMessage()
{
return target.CreateMapMessage();
}
+ ///
+ /// Creates the object message.
+ ///
+ /// The body.
+ ///
public IObjectMessage CreateObjectMessage(object body)
{
return target.CreateObjectMessage(body);
}
+ ///
+ /// Creates the bytes message.
+ ///
+ ///
public IBytesMessage CreateBytesMessage()
{
return target.CreateBytesMessage();
}
+ ///
+ /// Creates the bytes message.
+ ///
+ /// The body.
+ ///
public IBytesMessage CreateBytesMessage(byte[] body)
{
return target.CreateBytesMessage(body);
}
+ ///
+ /// Commits this instance.
+ ///
public void Commit()
{
target.Commit();
}
+ ///
+ /// Rollbacks this instance.
+ ///
public void Rollback()
{
target.Rollback();
}
+ ///
+ /// Gets a value indicating whether this is transacted.
+ ///
+ /// true if transacted; otherwise, false.
public bool Transacted
{
get { return target.Transacted; }
}
+ ///
+ /// Gets the acknowledgement mode.
+ ///
+ /// The acknowledgement mode.
public AcknowledgementMode AcknowledgementMode
{
get { return target.AcknowledgementMode; }
}
+ ///
+ /// Call dispose on the target.
+ ///
public void Dispose()
{
target.Dispose();
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachingConnectionFactory.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachingConnectionFactory.cs
index b27ec9d4..3c42cfe6 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachingConnectionFactory.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/CachingConnectionFactory.cs
@@ -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
{
///
/// 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;
}
+ ///
+ /// 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.
+ ///
+ /// The original Session to wrap.
+ /// The List of cached Sessions that the given Session belongs to.
+ /// The wrapped Session
protected virtual ISession GetCachedSessionWrapper(ISession targetSession, LinkedList sessionList)
{
return new CachedSession(targetSession, sessionList, SessionCacheSize, CacheProducers);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ChainedExceptionListener.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ChainedExceptionListener.cs
index 30889c66..acb0b1f0 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ChainedExceptionListener.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ChainedExceptionListener.cs
@@ -23,7 +23,7 @@ using System;
using System.Collections;
using Spring.Util;
-namespace Spring.Messaging.Nms.Connection
+namespace Spring.Messaging.Nms.Connections
{
///
/// Implementation of Spring IExceptionListener interface that supports
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ConnectionFactoryUtils.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ConnectionFactoryUtils.cs
index b14b04df..7f22bf88 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ConnectionFactoryUtils.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ConnectionFactoryUtils.cs
@@ -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
{
/// Helper class for obtaining transactional NMS resources
- /// for a given IConnectionFactory.
- ///
+ /// for a given ConnectionFactory.
///
/// Juergen Hoeller
/// Mark Pollack (.NET)
@@ -40,19 +40,76 @@ namespace Spring.Messaging.Nms.Connection
#endregion
- /// Obtain a NMS ISession that is synchronized with the current transaction, if any.
- /// the IConnectionFactory to obtain a ISession for
+ ///
+ /// Releases the given connection, stopping it (if necessary) and eventually closing it.
+ ///
+ /// Checks , if available.
+ /// This is essentially a more sophisticated version of
+ ///
+ ///
+ /// The connection to release. (if this is null, the call will be ignored)
+ /// The ConnectionFactory that the Connection was obtained from. (may be null)
+ /// whether the Connection might have been started by the application.
+ 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);
+ }
+ }
+
+ ///
+ /// Determines whether the given JMS Session is transactional, that is,
+ /// bound to the current thread by Spring's transaction facilities.
+ ///
+ /// The session to check.
+ /// The ConnectionFactory that the Session originated from
+ ///
+ /// true if is session transactional, bound to current thread; otherwise, false.
+ ///
+ 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));
+ }
+
+ /// Obtain a NMS Session that is synchronized with the current transaction, if any.
+ /// the ConnectionFactory to obtain a Session for
///
- /// the existing NMS IConnection to obtain a ISession for
+ /// the existing NMS Connection to obtain a Session for
/// (may be null)
///
/// 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.
///
- /// the transactional ISession, or null if none found
+ /// the transactional Session, or null if none found
///
/// NMSException in case of NMS failure
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);
}
- /// Obtain a NMS ISession that is synchronized with the current transaction, if any.
+ ///
+ /// Obtain a NMS Session that is synchronized with the current transaction, if any.
+ ///
/// the TransactionSynchronizationManager key to bind to
- /// (usually the IConnectionFactory)
- ///
+ /// (usually the ConnectionFactory)
/// the ResourceFactory to use for extracting or creating
- /// NMS resources
- ///
- /// the transactional ISession, or null if none found
+ /// NMS resources
+ /// 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 false.
+ ///
+ /// the transactional Session, or null if none found
///
/// NMSException in case of NMS failure
- 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
///
public interface ResourceFactory
{
- /// Fetch an appropriate ISession from the given NmsResourceHolder.
+ /// Fetch an appropriate Session from the given NmsResourceHolder.
/// the NmsResourceHolder
///
- /// an appropriate ISession fetched from the holder,
+ /// an appropriate Session fetched from the holder,
/// or null if none found
///
ISession GetSession(NmsResourceHolder holder);
- /// Fetch an appropriate IConnection from the given NmsResourceHolder.
+ /// Fetch an appropriate Connection from the given NmsResourceHolder.
/// the NmsResourceHolder
///
- /// an appropriate IConnection fetched from the holder,
+ /// an appropriate Connection fetched from the holder,
/// or null if none found
///
IConnection GetConnection(NmsResourceHolder holder);
- /// Create a new NMS IConnection for registration with a NmsResourceHolder.
- /// the new NMS IConnection
+ /// Create a new NMS Connection for registration with a NmsResourceHolder.
+ /// the new NMS Connection
///
/// NMSException if thrown by NMS API methods
IConnection CreateConnection();
/// Create a new NMS ISession for registration with a NmsResourceHolder.
- /// the NMS IConnection to create a ISession for
+ /// the NMS Connection to create a ISession for
///
- /// the new NMS ISession
+ /// the new NMS Session
///
/// NMSException if thrown by NMS API methods
ISession CreateSession(IConnection con);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/IDecoratorSession.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/IDecoratorSession.cs
index 8e705824..87f3738e 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/IDecoratorSession.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/IDecoratorSession.cs
@@ -20,11 +20,11 @@
using Apache.NMS;
-namespace Spring.Messaging.Nms.Connection
+namespace Spring.Messaging.Nms.Connections
{
///
- /// 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.
///
/// Mark Pollack
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ISmartConnectionFactory.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ISmartConnectionFactory.cs
index 2911c003..822db229 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ISmartConnectionFactory.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/ISmartConnectionFactory.cs
@@ -22,10 +22,10 @@
using Apache.NMS;
-namespace Spring.Messaging.Nms.Connection
+namespace Spring.Messaging.Nms.Connections
{
///
- /// Extension of the IConnectionFactory interface,
+ /// Extension of the ConnectionFactory interface,
/// indicating how to release Connections obtained from it.
///
/// Juergen Hoeller
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsResourceHolder.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsResourceHolder.cs
index 16ba704f..9964efc7 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsResourceHolder.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsResourceHolder.cs
@@ -26,11 +26,11 @@ using Spring.Transaction.Support;
using Spring.Util;
using Apache.NMS;
-namespace Spring.Messaging.Nms.Connection
+namespace Spring.Messaging.Nms.Connections
{
- /// IConnection holder, wrapping a NMS IConnection and a NMS ISession.
+ /// 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.
///
/// Note: This is an SPI class, not intended to be used by applications.
///
@@ -92,17 +92,23 @@ namespace Spring.Messaging.Nms.Connection
}
/// Create a new NmsResourceHolder for the given NMS resources.
- /// the NMS IConnection
+ /// the NMS Connection
///
- /// the NMS ISession
+ /// the NMS Session
///
- public NmsResourceHolder(Apache.NMS.IConnection connection, ISession session)
+ public NmsResourceHolder(IConnection connection, ISession session)
{
AddConnection(connection);
AddSession(session, connection);
this.frozen = true;
}
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection factory.
+ /// The connection.
+ /// The session.
public NmsResourceHolder(IConnectionFactory connectionFactory, IConnection connection, ISession session)
{
this.connectionFactory = connectionFactory;
@@ -114,6 +120,12 @@ namespace Spring.Messaging.Nms.Connection
#region Properties
+ ///
+ /// Gets a value indicating whether this 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.
+ ///
+ /// true if frozen; otherwise, false.
virtual public bool Frozen
{
get
@@ -125,11 +137,14 @@ namespace Spring.Messaging.Nms.Connection
#endregion
#region Methods
-
- public void AddConnection(Apache.NMS.IConnection connection)
+
+ ///
+ /// Adds the connection to the list of resources managed by this holder.
+ ///
+ /// The connection.
+ 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
}
}
+ ///
+ /// Adds the session to the list of resources managed by this holder.
+ ///
+ /// The session.
public void AddSession(ISession session)
{
AddSession(session, null);
}
- public void AddSession(ISession session, Apache.NMS.IConnection connection)
+ ///
+ /// Adds the session and connection to the list of resources managed by this holder.
+ ///
+ /// The session.
+ /// The connection.
+ 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()
+ ///
+ /// Gets the connection managed by this resource holder
+ ///
+ /// A Connection, or null if no managed connection.
+ 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)
+ ///
+ /// 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.
+ ///
+ /// Type of the connection.
+ /// The connection, or null if not found.
+ 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);
}
+ ///
+ /// Gets the first session manged by this holder or null if not available.
+ ///
+ /// The session or null if not available.
public virtual ISession GetSession()
{
return (!(this.sessions.Count == 0) ? (ISession)this.sessions[0] : null);
}
+ ///
+ /// Gets the session managed by this holder by type.
+ ///
+ /// Type of the session.
+ /// The session or null if not available.
public virtual ISession GetSession(Type sessionType)
{
return GetSession(sessionType, null);
}
- public virtual ISession GetSession(System.Type sessionType, Apache.NMS.IConnection connection)
+ ///
+ /// Gets the session of a given type associated with the given connection
+ ///
+ /// Type of the session.
+ /// The connection.
+ /// The sessin or null if not available.
+ 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);
}
///
@@ -230,6 +275,13 @@ namespace Spring.Messaging.Nms.Connection
}
}
+ ///
+ /// Determines whether the holder contains the specified session.
+ ///
+ /// The session.
+ ///
+ /// true if the holder contains the specified session; otherwise, false.
+ ///
public bool ContainsSession(ISession session)
{
return this.sessions.Contains(session);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsTransactionManager.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsTransactionManager.cs
index b018e9e2..e3a6b294 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsTransactionManager.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/NmsTransactionManager.cs
@@ -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
{
///
/// A implementation
- /// for a single NMS Apache.NMS.IConnectionFactory. Binds a
+ /// for a single NMS ConnectionFactory. Binds a
/// Connection/Session pair from the specified ConnecctionFactory to the thread,
/// potentially allowing for one thread-bound Session per ConnectionFactory.
///
@@ -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
+ ///
+ /// Get the NmsTransactionObject.
+ ///
+ /// he NmsTransactionObject.
protected override object DoGetTransaction()
{
NmsTransactionObject txObject = new NmsTransactionObject();
@@ -135,6 +157,21 @@ namespace Spring.Messaging.Nms.Connection
return txObject;
}
+
+ ///
+ /// Begin a new transaction with the given transaction definition.
+ ///
+ /// Transaction object returned by
+ /// .
+ /// instance, describing
+ /// propagation behavior, isolation level, timeout etc.
+ ///
+ /// Does not have to care about applying the propagation behavior,
+ /// as this has already been handled by this abstract manager.
+ ///
+ ///
+ /// In the case of creation or system errors.
+ ///
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
}
+ ///
+ /// Suspend the resources of the current transaction.
+ ///
+ /// Transaction object returned by
+ /// .
+ ///
+ /// An object that holds suspended resources (will be kept unexamined for passing it into
+ /// .)
+ ///
+ ///
+ /// Transaction synchronization will already have been suspended.
+ ///
+ ///
+ /// in case of system errors.
+ ///
protected override object DoSuspend(object transaction)
{
NmsTransactionObject txObject = (NmsTransactionObject) transaction;
@@ -193,12 +245,31 @@ namespace Spring.Messaging.Nms.Connection
return TransactionSynchronizationManager.UnbindResource(ConnectionFactory);
}
+ ///
+ /// Resume the resources of the current transaction.
+ ///
+ /// Transaction object returned by
+ /// .
+ /// The object that holds suspended resources as returned by
+ /// .
+ /// Transaction synchronization will be resumed afterwards.
+ ///
+ ///
+ /// In the case of system errors.
+ ///
protected override void DoResume(object transaction, object suspendedResources)
{
NmsResourceHolder conHolder = (NmsResourceHolder) suspendedResources;
TransactionSynchronizationManager.BindResource(ConnectionFactory, conHolder);
}
+ ///
+ /// Perform an actual commit on the given transaction.
+ ///
+ /// The status representation of the transaction.
+ ///
+ /// In the case of system errors.
+ ///
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);
}
}
+ ///
+ /// Perform an actual rollback on the given transaction.
+ ///
+ /// The status representation of the transaction.
+ ///
+ /// In the case of system errors.
+ ///
protected override void DoRollback(DefaultTransactionStatus status)
{
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
@@ -242,12 +316,33 @@ namespace Spring.Messaging.Nms.Connection
}
+ ///
+ /// Set the given transaction rollback-only. Only called on rollback
+ /// if the current transaction takes part in an existing one.
+ ///
+ /// The status representation of the transaction.
+ ///
+ /// In the case of system errors.
+ ///
protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
{
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
txObject.ResourceHolder.RollbackOnly = true;
}
+ ///
+ /// Cleanup resources after transaction completion.
+ ///
+ /// Transaction object returned by
+ /// .
+ ///
+ ///
+ /// Called after
+ /// and
+ ///
+ /// execution on any outcome.
+ ///
+ ///
protected override void DoCleanupAfterCompletion(object transaction)
{
NmsTransactionObject txObject = (NmsTransactionObject)transaction;
@@ -256,6 +351,18 @@ namespace Spring.Messaging.Nms.Connection
txObject.ResourceHolder.Clear();
}
+ ///
+ /// Check if the given transaction object indicates an existing transaction
+ /// (that is, a transaction which has already started).
+ ///
+ /// Transaction object returned by
+ /// .
+ ///
+ /// True if there is an existing transaction.
+ ///
+ ///
+ /// In the case of system errors.
+ ///
protected override bool IsExistingTransaction(object transaction)
{
NmsTransactionObject txObject = transaction as NmsTransactionObject;
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SingleConnectionFactory.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SingleConnectionFactory.cs
index 93f6ced9..7d5b1474 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SingleConnectionFactory.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SingleConnectionFactory.cs
@@ -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
{
+ ///
+ /// 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.
+ ///
+ ///
+ /// You can either pass in a specific Connection directly or let this
+ /// factory lazily create a Connection via a given target ConnectionFactory.
+ /// Useful in order to keep using the same Connection for multiple
+ /// calls, without having a pooling ConnectionFactory
+ /// underneath. This may span any number of transactions, even concurrently executing transactions.
+ ///
+ ///
+ /// 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.
+ ///
+ ///
+ /// Juergen Hoeller
+ /// Mark Pollack
+ /// Mark Pollack (.NET)
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
}
+ ///
+ /// Gets or sets the exception listener implementation that should be registered
+ /// with with the single Connection created by this factory, if any.
+ ///
+ /// The exception listener.
public IExceptionListener ExceptionListener
{
get { return exceptionListener; }
@@ -162,6 +192,10 @@ namespace Spring.Messaging.Nms.Connection
#region IConnectionFactory Members
+ ///
+ /// Creates the connection.
+ ///
+ /// A single shared connection
public IConnection CreateConnection()
{
lock (connectionMonitor)
@@ -174,6 +208,12 @@ namespace Spring.Messaging.Nms.Connection
}
}
+ ///
+ /// Creates the connection.
+ ///
+ /// Name of the user.
+ /// The password.
+ ///
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
+ ///
+ /// Initialize the underlying shared Connection. Closes and reinitializes the Connection if an underlying
+ /// Connection is present already.
+ ///
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();
}
+ ///
+ /// Prepares the connection before it is exposed.
+ /// The default implementation applies ExceptionListener and client id.
+ /// Can be overridden in subclasses.
+ ///
+ /// The Connection to prepare.
+ /// if thrown by any NMS API methods.
protected virtual void PrepareConnection(IConnection con)
{
if (ClientId != null)
@@ -249,11 +300,19 @@ namespace Spring.Messaging.Nms.Connection
return null;
}
+ ///
+ /// reate a JMS Connection via this template's ConnectionFactory.
+ ///
+ ///
protected virtual IConnection DoCreateConnection()
{
return TargetConnectionFactory.CreateConnection();
}
+ ///
+ /// Closes the given connection.
+ ///
+ /// The connection.
protected virtual void CloseConnection(IConnection con)
{
try
@@ -273,6 +332,9 @@ namespace Spring.Messaging.Nms.Connection
#region IInitializingObject Members
+ ///
+ /// Ensure that the connection or TargetConnectionFactory are specified.
+ ///
public void AfterPropertiesSet()
{
if (connection == null && TargetConnectionFactory == null)
@@ -283,11 +345,20 @@ namespace Spring.Messaging.Nms.Connection
#endregion
+
+ ///
+ /// Close the underlying shared connection. The provider of this ConnectionFactory needs to care for proper shutdown.
+ /// As this object implements an application context will automatically
+ /// invoke this on distruction o
+ ///
public void Dispose()
{
ResetConnection();
}
+ ///
+ /// Resets the underlying shared Connection, to be reinitialized on next access.
+ ///
public virtual void ResetConnection()
{
lock (connectionMonitor)
@@ -301,11 +372,19 @@ namespace Spring.Messaging.Nms.Connection
}
}
- protected virtual IConnection GetSharedConnection(SingleConnectionFactory singleConnectionFactory, IConnection target)
+ ///
+ /// 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.
+ ///
+ /// The original connection to wrap.
+ /// the wrapped connection
+ 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();
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SynchedLocalTransactionFailedException.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SynchedLocalTransactionFailedException.cs
index ce3ebcf4..730910fd 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SynchedLocalTransactionFailedException.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Connections/SynchedLocalTransactionFailedException.cs
@@ -21,7 +21,7 @@
using System;
using Apache.NMS;
-namespace Spring.Messaging.Nms.Connection
+namespace Spring.Messaging.Nms.Connections
{
/// Exception thrown when a synchronized local transaction failed to complete
/// (after the main transaction has already completed).
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IExceptionListener.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IExceptionListener.cs
index 35150487..8953b07a 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IExceptionListener.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IExceptionListener.cs
@@ -28,6 +28,10 @@ namespace Spring.Messaging.Nms
/// Mark Pollack
public interface IExceptionListener
{
+ ///
+ /// Called when there is an exception in message processing.
+ ///
+ /// The exception.
void OnException(Exception exception);
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageCreator.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageCreator.cs
index 4b2937ba..40db1d44 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageCreator.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageCreator.cs
@@ -22,19 +22,19 @@ using Apache.NMS;
namespace Spring.Messaging.Nms
{
- /// Creates a NMS message given a ISession
+ /// Creates a NMS message given a Session
///
- /// The ISession typically is provided by an instance
+ ///
The Session typically is provided by an instance
/// of the NmsTemplate class.
///
/// Mark Pollack
public interface IMessageCreator
{
- /// Create a IMessage to be sent.
- /// the NMS ISession to be used to create the
+ /// Create a Message to be sent.
+ /// the NMS Session to be used to create the
/// IMessage (never null)
///
- /// the IMessage to be sent
+ /// the Message to be sent
///
/// NMSException if thrown by NMS API methods
IMessage CreateMessage(ISession session);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageListener.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageListener.cs
index 9254681d..1728c835 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageListener.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessageListener.cs
@@ -22,8 +22,15 @@ using Apache.NMS;
namespace Spring.Messaging.Nms
{
+ ///
+ /// Interfaced based approach to listen to messaging events.
+ ///
public interface IMessageListener
{
+ ///
+ /// Called when a message is delivered.
+ ///
+ /// The message.
void OnMessage(IMessage message);
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessagePostProcessor.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessagePostProcessor.cs
index cf9e4eda..3aadd167 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessagePostProcessor.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IMessagePostProcessor.cs
@@ -37,7 +37,7 @@ namespace Spring.Messaging.Nms
///
/// the NMS message from the IMessageConverter
///
- /// the modified version of the IMessage
+ /// the modified version of the Message
///
/// NMSException if thrown by NMS API methods
IMessage PostProcessMessage(IMessage message);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/INmsOperations.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/INmsOperations.cs
index 1d561ebe..5dc54305 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/INmsOperations.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/INmsOperations.cs
@@ -39,11 +39,13 @@ namespace Spring.Messaging.Nms
public interface INmsOperations
{
/// Execute the action specified by the given action object within
- /// a NMS ISession.
- /// 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.
+ /// a NMS Session.
///
+ ///
+ /// 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.b
+ ///
/// callback object that exposes the session
///
/// the result object from working with the session
@@ -52,7 +54,7 @@ namespace Spring.Messaging.Nms
object Execute(ISessionCallback action);
/// 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.
///
/// callback object that exposes the session/producer pair
@@ -76,7 +78,7 @@ namespace Spring.Messaging.Nms
void Send(IMessageCreator messageCreator);
/// 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.
///
/// the destination to send this message to
///
@@ -86,7 +88,7 @@ namespace Spring.Messaging.Nms
void Send(IDestination destination, IMessageCreator messageCreator);
/// 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.
///
/// 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);
/// 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.
///
/// the destination to send this message to
///
@@ -119,7 +121,7 @@ namespace Spring.Messaging.Nms
void SendWithDelegate(IDestination destination, IMessageCreatorDelegate messageCreatorDelegate);
/// 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.
///
/// the name of the destination to send this message to
/// (to be resolved to an actual destination by a DestinationResolver)
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IProducerCallback.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IProducerCallback.cs
index e0b62942..d3d909cc 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IProducerCallback.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/IProducerCallback.cs
@@ -28,19 +28,19 @@ namespace Spring.Messaging.Nms
/// method, often implemented as an anonymous inner class.
///
/// The typical implementation will perform multiple operations on the
- /// supplied NMS ISession and IMessageProducer.
+ /// supplied NMS Session and MessageProducer.
///
/// Mark Pollack
public interface IProducerCallback
{
- /// Perform operations on the given ISession and IMessageProducer.
+ /// Perform operations on the given Session and MessageProducer.
/// The message producer is not associated with any destination.
///
- /// the NMS ISession object to use
+ /// the NMS Session object to use
///
- /// the NMS IMessageProducer object to use
+ /// the NMS MessageProducer object to use
///
- /// a result object from working with the ISession, if any (can be null)
+ /// a result object from working with the Session, if any (can be null)
///
object DoInNms(ISession session, IMessageProducer producer);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/ISessionCallback.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/ISessionCallback.cs
index dae030a3..f8c2e185 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/ISessionCallback.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/ISessionCallback.cs
@@ -23,7 +23,7 @@ using Apache.NMS;
namespace Spring.Messaging.Nms
{
/// Callback for executing any number of operations on a provided
- /// ISession
+ /// Session
///
///
/// To be used with the NmsTemplate.Execute(ISessionCallback)}
@@ -35,11 +35,11 @@ namespace Spring.Messaging.Nms
public interface ISessionCallback
{
/// Execute any number of operations against the supplied NMS
- /// ISession, possibly returning a result.
+ /// Session, possibly returning a result.
///
- /// the NMS ISession
+ /// the NMS Session
///
- /// a result object from working with the ISession, if any (so can be null)
+ /// a result object from working with the Session, if any (so can be null)
///
/// NMSException if there is any problem
object DoInNms(ISession session);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractMessageListenerContainer.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractMessageListenerContainer.cs
index 78dff4f6..cd0733f7 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractMessageListenerContainer.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractMessageListenerContainer.cs
@@ -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
{
///
/// Abstract base class for message listener containers. Can either host
- /// a standard NMS or a Spring-specific
+ /// a standard NMS MessageListener or a Spring-specific
///
///
public abstract class AbstractMessageListenerContainer : AbstractNmsListeningContainer
@@ -61,6 +62,12 @@ namespace Spring.Messaging.Nms.Listener
#region Properties
+ ///
+ /// Gets or sets the destination to receive messages from. Will be null
+ /// if the configured destination is not an actual Destination type;
+ /// c.f. when the destination is a String.
+ ///
+ /// The destination.
public IDestination Destination
{
get
@@ -80,6 +87,12 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Gets or sets the name of the destination to receive messages from.
+ /// Will be null if the configured destination is not a
+ /// string type; c.f. when it is an actual Destination object.
+ ///
+ /// The name of the destination.
public string DestinationName
{
get
@@ -95,6 +108,10 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Gets or sets the message selector.
+ ///
+ /// The message selector expression (or null if none)..
public string MessageSelector
{
get { return messageSelector; }
@@ -108,7 +125,7 @@ namespace Spring.Messaging.Nms.Listener
///
///
///
- /// This can be either a standard NMS object or a
+ /// This can be either a standard NMS MessageListener object or a
/// Spring object.
///
///
@@ -132,6 +149,19 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Gets or sets a value indicating whether the subscription is durable.
+ ///
+ ///
+ /// Set whether to make the subscription durable. The durable subscription name
+ /// to be used can be specified through the "DurableSubscriptionName" property.
+ /// 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).
+ ///
+ /// Only makes sense when listening to a topic (pub-sub domain).
+ ///
+ /// true if the subscription is durable; otherwise, false.
public bool SubscriptionDurable
{
get { return subscriptionDurable; }
@@ -139,6 +169,18 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Gets or sets the name of the durable subscription to create.
+ ///
+ ///
+ /// 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.
+ /// Note: Only 1 concurrent consumer (which is the default of this
+ /// message listener container) is allowed for each durable subscription.
+ ///
+ ///
+ /// The name of the durable subscription.
public string DurableSubscriptionName
{
get
@@ -153,6 +195,11 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Gets or sets the exception listener to notify in case of a NMSException thrown
+ /// by the registered message listener or the invocation infrastructure.
+ ///
+ /// The exception listener.
public IExceptionListener ExceptionListener
{
get { return exceptionListener; }
@@ -160,6 +207,24 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Gets or sets a value indicating whether to expose listener session to a registered
+ /// as well as to calls.
+ ///
+ ///
+ /// 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.
+ /// Note that Sessions managed by an external transaction manager will
+ /// always get exposed to
+ /// calls. So in terms of NmsTemplate exposure, this setting only affects
+ /// locally transacted Sessions.
+ ///
+ ///
+ ///
+ /// true if expose listener session; otherwise, false.
+ ///
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
+ ///
+ /// Validate that the destination is not null and that if the subscription is durable, then we are not
+ /// using the Pub/Sub domain.
+ ///
protected override void ValidateConfiguration()
{
if (this.destination == null)
@@ -284,7 +346,7 @@ namespace Spring.Messaging.Nms.Listener
}
///
- /// Invokes the specified listener: either as standard NMS IMessageListener
+ /// Invokes the specified listener: either as standard NMS MessageListener
/// or (preferably) as Spring SessionAwareMessageListener.
///
/// The session to operate on.
@@ -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();
}
}
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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.
+ ///
+ /// The session to check.
+ ///
+ /// true if the is session locally transacted; otherwise, false.
+ ///
+ ///
+ protected virtual bool IsSessionLocallyTransacted(ISession session)
+ {
+ return SessionTransacted;
+ }
+
///
/// Perform a rollback, if appropriate.
@@ -403,7 +486,7 @@ namespace Spring.Messaging.Nms.Listener
/// In case of a rollback error
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)
+ ///
+ /// 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 object will be accepted.
+ ///
+ /// The message listener.
+ 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 + "]");
}
}
}
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractNmsListeningContainer.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractNmsListeningContainer.cs
index 92b05ac4..5f508693 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractNmsListeningContainer.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/AbstractNmsListeningContainer.cs
@@ -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;
-
+
+ ///
+ /// The monitor object to lock on when performing operations on the connection.
+ ///
protected object sharedConnectionMonitor = new object();
private volatile bool active = false;
private bool running = false;
-
+
+ ///
+ /// The monitor object to lock on when performing operations that update the lifecycle of the container.
+ ///
protected object lifecycleMonitor = new object();
#endregion
+ ///
+ /// Gets or sets the client id for a shared Connection created and used by this container.
+ ///
+ ///
+ /// 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.
+ ///
+ /// The client id.
public string ClientId
{
set { clientId = value; }
@@ -89,6 +104,18 @@ namespace Spring.Messaging.Nms.Listener
set { this.autoStartup = value; }
}
+ ///
+ /// Set the name of the object in the object factory that created this object.
+ ///
+ /// The name of the object in the factory.
+ ///
+ ///
+ /// Invoked after population of normal object properties but before an init
+ /// callback like 's
+ ///
+ /// method or a custom init-method.
+ ///
+ ///
public string ObjectName
{
set { objectName = value; }
@@ -134,6 +161,11 @@ namespace Spring.Messaging.Nms.Listener
return true; }
}
+ ///
+ /// Gets a value indicating whether this container is currently active,
+ /// that is, whether it has been set up but not shut down yet.
+ ///
+ /// true if active; otherwise, false.
public virtual bool Active
{
get
@@ -146,11 +178,10 @@ namespace Spring.Messaging.Nms.Listener
}
- /// Return whether a shared NMS IConnection should be maintained
+ /// Return whether a shared NMS Connection should be maintained
/// by this listener container base class.
- ///
- ///
- ///
+ ///
+ ///
protected abstract bool SharedConnectionEnabled { get; }
///
@@ -180,7 +211,10 @@ namespace Spring.Messaging.Nms.Listener
}
}
}
-
+
+ ///
+ /// Call base class method, then and then
+ ///
public override void AfterPropertiesSet()
{
base.AfterPropertiesSet();
@@ -197,6 +231,9 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Calls when the application context destroys the container instance.
+ ///
public void Dispose()
{
Shutdown();
@@ -237,6 +274,9 @@ namespace Spring.Messaging.Nms.Listener
}
}
+ ///
+ /// Stop the shared connection, call , and close this container.
+ ///
public virtual void Shutdown()
{
logger.Debug("Shutting down message listener container");
@@ -283,6 +323,9 @@ namespace Spring.Messaging.Nms.Listener
DoStart();
}
+ ///
+ /// Start the shared Connection, if any, and notify all invoker tasks.
+ ///
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
}
}
+ ///
+ /// Stops the shared connection.
+ ///
+ /// if thrown by NMS API methods.
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.
///
- public class SharedConnectionNotInitializedException : ApplicationException
+ public class SharedConnectionNotInitializedException : NMSException
{
///
/// Initializes a new instance of the class.
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/Adapter/MessageListenerAdapter.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/Adapter/MessageListenerAdapter.cs
index a081f689..d83c2ffa 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/Adapter/MessageListenerAdapter.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/Adapter/MessageListenerAdapter.cs
@@ -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
{
+ ///
+ /// 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.
+ ///
+ ///
+ /// 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
+ /// . By default, a
+ /// will be used. (If you do not want such automatic message conversion taking
+ /// place, then be sure to set the property
+ /// to null.)
+ ///
+ /// If a target listener method returns a non-null object (typically of a
+ /// message content type such as String or byte array), it will get
+ /// wrapped in a NMS Message and sent to the response destination
+ /// (either the NMS "reply-to" destination or the
+ /// specified.
+ ///
+ ///
+ /// The sending of response messages is only available when
+ /// using the entry point (typically through a
+ /// Spring message listener container). Usage as standard NMS MessageListener
+ /// does not support the generation of response messages.
+ ///
+ /// Consult the reference documentation for examples of method signatures compliant with this
+ /// adapter class.
+ ///
+ ///
+ /// Juergen Hoeller
+ /// Mark Pollack (.NET)
public class MessageListenerAdapter : IMessageListener
{
#region Logging
@@ -18,9 +53,14 @@ namespace Spring.Messaging.Nms.Listener.Adapter
#endregion
- private object delegateObject;
+ ///
+ /// The default handler method name.
+ ///
+ 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;
+ ///
+ /// Initializes a new instance of the class with default settings.
+ ///
public MessageListenerAdapter()
{
InitDefaultStrategies();
- delegateObject = this;
- processingExpression = Spring.Expressions.Expression.Parse(defaultListenerMethod + "(#convertedObject)");
+ handlerObject = this;
+ processingExpression = Expression.Parse(defaultHandlerMethod + "(#convertedObject)");
}
- public MessageListenerAdapter(object delegateObject)
+ ///
+ /// Initializes a new instance of the class for the given handler object
+ ///
+ /// The delegate object.
+ public MessageListenerAdapter(object handlerObject)
{
InitDefaultStrategies();
- this.delegateObject = delegateObject;
+ this.handlerObject = handlerObject;
}
- // TODO name change?
-
- public object DelegateObject
+ ///
+ /// Gets or sets the handler object to delegate message listening to.
+ ///
+ ///
+ /// Specified listener methods have to be present on this target object.
+ /// If no explicit handler object has been specified, listener
+ /// methods are expected to present on this adapter instance, that is,
+ /// on a custom subclass of this adapter, defining listener methods.
+ ///
+ /// The handler object.
+ public object HandlerObject
{
- get { return delegateObject; }
- set { delegateObject = value; }
+ get { return handlerObject; }
+ set { handlerObject = value; }
}
- public string DefaultListenerMethod
+ ///
+ /// Gets or sets the default handler method to delegate to,
+ /// for the case where no specific listener method has been determined.
+ /// Out-of-the-box value is ("HandleMessage"}.
+ ///
+ /// The default handler method.
+ public string DefaultHandlerMethod
{
- get { return defaultListenerMethod; }
+ get { return defaultHandlerMethod; }
set
{
- defaultListenerMethod = value;
+ defaultHandlerMethod = value;
}
}
+ ///
+ /// Sets the default destination to send response messages to. This will be applied
+ /// in case of a request message that does not carry a "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.
+ ///
+ /// Alternatively, specify a "DefaultResponseQueueName" or "DefaultResponseTopicName",
+ /// to be dynamically resolved via the DestinationResolver.
+ ///
+ ///
+ /// The default response destination.
public object DefaultResponseDestination
{
set { defaultResponseDestination = value; }
}
+ ///
+ /// Sets the name of the default response queue to send response messages to.
+ /// This will be applied in case of a request message that does not carry a
+ /// "NMSReplyTo" field.
+ /// Alternatively, specify a JMS Destination object as "defaultResponseDestination".
+ ///
+ /// The name of the default response destination queue.
public string DefaultResponseDestinationQueueName
{
set { defaultResponseDestination = new DestinationNameHolder(value, false); }
}
+ ///
+ /// 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.
+ /// Alternatively, specify a JMS Destination object as "defaultResponseDestination".
+ ///
+ /// The name of the default response destination topic.
public string DefaultResponseDestinationTopicName
{
set { defaultResponseDestination = new DestinationNameHolder(value, true); }
}
+ ///
+ /// Gets or sets the destination resolver that should be used to resolve response
+ /// destination names for this adapter.
+ /// The default resolver is a .
+ /// Specify another implementation, for other strategies, perhaps from a directory service.
+ ///
+ /// The destination resolver.
public IDestinationResolver DestinationResolver
{
get { return destinationResolver; }
@@ -87,28 +181,39 @@ namespace Spring.Messaging.Nms.Listener.Adapter
}
}
+ ///
+ /// 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.
+ ///
+ ///
+ /// The default converter is a {@link SimpleMessageConverter}, which is able
+ /// to handle BytesMessages}, TextMessages, MapMessages, and ObjectMessages.
+ ///
+ ///
+ /// The message converter.
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;
- }
-
+ ///
+ /// Standard JMS {@link MessageListener} entry point.
+ /// Delegates the message to the target listener method, with appropriate
+ /// conversion of the message arguments
+ ///
+ ///
+ ///
+ /// In case of an exception, the method will be invoked.
+ /// Note
+ /// Does not support sending response messages based on
+ /// result objects returned from listener methods. Use the
+ /// entry point (typically through a Spring
+ /// message listener container) for handling result objects as well.
+ ///
+ /// The incoming message.
public void OnMessage(IMessage message)
{
try
@@ -121,9 +226,19 @@ namespace Spring.Messaging.Nms.Listener.Adapter
}
}
+ ///
+ /// Spring entry point.
+ ///
+ /// 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.
+ ///
+ ///
+ /// The incoming message.
+ /// The session to operate on.
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)
+ ///
+ /// Initialize the default implementations for the adapter's strategies.
+ ///
+ protected virtual void InitDefaultStrategies()
+ {
+ MessageConverter = new SimpleMessageConverter();
+ }
+
+ ///
+ /// Handle the given exception that arose during listener execution.
+ /// The default implementation logs the exception at error level.
+ /// This method only applies when used as standard NMS MessageListener.
+ /// In case of the Spring mechanism,
+ /// exceptions get handled by the caller instead.
+ ///
+ ///
+ /// The exception to handle.
+ protected virtual void HandleListenerException(Exception ex)
+ {
+ logger.Error("Listener execution failed", ex);
+ }
+
+ ///
+ /// Extract the message body from the given message.
+ ///
+ /// The message.
+ /// the content of the message, to be passed into the
+ /// listener method as argument
+ /// if thrown by NMS API methods
+ private object ExtractMessage(IMessage message)
+ {
+ IMessageConverter converter = MessageConverter;
+ if (converter != null)
+ {
+ return converter.FromMessage(message);
+ }
+ return message;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The NMS request message.
+ /// The converted JMS request message,
+ /// to be passed into the listener method as argument.
+ /// the name of the listener method (never null)
+ /// if thrown by NMS API methods
+ protected virtual string GetHandlerMethodName(IMessage originalIMessage, object extractedMessage)
+ {
+ return DefaultHandlerMethod;
+ }
+
+ ///
+ /// Handles the given result object returned from the listener method, sending a response message back.
+ ///
+ /// The result object to handle (never null).
+ /// The original request message.
+ /// The session to operate on (may be null).
+ protected virtual void HandleResult(object result, IMessage request, ISession session)
{
if (session != null)
{
@@ -170,6 +346,14 @@ namespace Spring.Messaging.Nms.Listener.Adapter
}
}
+ ///
+ /// Builds a JMS message to be sent as response based on the given result object.
+ ///
+ /// The JMS Session to operate on.
+ /// The content of the message, as returned from the listener method.
+ /// the JMS Message (never null)
+ /// If there was an error in message conversion
+ /// if thrown by NMS API methods
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;
}
}
+ ///
+ /// Post-process the given response message before it will be sent. The default implementation
+ /// sets the response's correlation id to the request message's correlation id.
+ ///
+ /// The original incoming message.
+ /// The outgoing JMS message about to be sent.
+ /// if thrown by NMS API methods
protected virtual void PostProcessResponse(IMessage request, IMessage response)
{
response.NMSCorrelationID = request.NMSCorrelationID;
}
-
+
+ ///
+ /// Determine a response destination for the given message.
+ ///
+ ///
+ /// The default implementation first checks the JMS Reply-To
+ /// Destination of the supplied request; if that is not null
+ /// it is returned; if it is null, then the configured
+ /// default response destination}
+ /// is returned; if this too is null, then an
+ /// is thrown.
+ ///
+ ///
+ /// The original incoming message.
+ /// Tthe outgoing message about to be sent.
+ /// The session to operate on.
+ /// the response destination (never null)
+ /// if thrown by NMS API methods
+ /// if no destination can be determined.
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;
}
-
+
+ ///
+ /// Resolves the default response destination into a Destination, using this
+ /// accessor's in case of a destination name.
+ ///
+ /// The session to operate on.
+ /// The located destination
protected virtual IDestination ResolveDefaultResponseDestination(ISession session)
{
IDestination dest = defaultResponseDestination as IDestination;
@@ -225,7 +440,13 @@ namespace Spring.Messaging.Nms.Listener.Adapter
return null;
}
-
+
+ ///
+ /// Sends the given response message to the given destination.
+ ///
+ /// The session to operate on.
+ /// The destination to send to.
+ /// The outgoing message about to be sent.
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);
}
}
-
+
+ ///
+ /// Post-process the given message producer before using it to send the response.
+ /// The default implementation is empty.
+ ///
+ /// The producer that will be used to send the message.
+ /// The outgoing message about to be sent.
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;
- }
}
+ ///
+ /// Internal class combining a destination name and its target destination type (queue or topic).
+ ///
internal class DestinationNameHolder
{
private string name;
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/DefaultMessageListenerContainer.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/DefaultMessageListenerContainer.cs
deleted file mode 100644
index f952d7f4..00000000
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/DefaultMessageListenerContainer.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Spring.Messaging.Nms.Listener
-{
- public class DefaultMessageListenerContainer
- {
- }
-}
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/ISessionAwareMessageListener.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/ISessionAwareMessageListener.cs
index 0b1b61c8..eb2cc30b 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/ISessionAwareMessageListener.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/ISessionAwareMessageListener.cs
@@ -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
{
+ ///
+ /// 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.
+ ///
+ ///
+ /// Supported by Spring's
+ /// as direct alternative to the standard MessageListener interface.
+ ///
+ /// Juergen Hoeller
+ /// Mark Pollack (.NET)
public interface ISessionAwareMessageListener
{
-
/// 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.
///
/// the received NMS message
///
- /// the underlying NMS ISession
+ /// the underlying NMS Session
///
/// NMSException if thrown by NMS methods
void OnMessage(IMessage message, ISession session);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/LocallyExposedNmsResourceHolder.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/LocallyExposedNmsResourceHolder.cs
index 16cb59fc..1eda9a3a 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/LocallyExposedNmsResourceHolder.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/LocallyExposedNmsResourceHolder.cs
@@ -19,7 +19,7 @@
#endregion
using Apache.NMS;
-using Spring.Messaging.Nms.Connection;
+using Spring.Messaging.Nms.Connections;
namespace Spring.Messaging.Nms.Listener
{
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/SimpleMessageListenerContainer.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/SimpleMessageListenerContainer.cs
index 50f10c07..500a2ef9 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/SimpleMessageListenerContainer.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Listener/SimpleMessageListenerContainer.cs
@@ -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
{
///
/// Message listener container that uses the plain NMS client API's
- /// method to create concurrent
+ /// MessageConsumer.Listener method to create concurrent
/// MessageConsumers for the specified listeners.
///
public class SimpleMessageListenerContainer : AbstractMessageListenerContainer, IExceptionListener
@@ -57,12 +58,31 @@ namespace Spring.Messaging.Nms.Listener
#region Properties
+ ///
+ /// Gets or sets a value indicating whether to inhibit the delivery of messages published by its own connection.
+ /// Default is "false".
+ ///
+ /// true if should inhibit the delivery of messages published by its own connection; otherwise, false.
public bool PubSubNoLocal
{
get { return pubSubNoLocal; }
set { pubSubNoLocal = value; }
}
+ ///
+ /// Specify the number of concurrent consumers to create. Default is 1.
+ ///
+ ///
+ /// 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.
+ /// 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.
+ ///
+ ///
+ /// The concurrent consumers.
public int ConcurrentConsumers
{
set
@@ -82,6 +102,10 @@ namespace Spring.Messaging.Nms.Listener
#endregion
+ ///
+ /// Call base class for valdation and then check that if the subscription is durable that the number of
+ /// concurrent consumers is equal to one.
+ ///
protected override void ValidateConfiguration()
{
base.ValidateConfiguration();
@@ -120,10 +144,18 @@ namespace Spring.Messaging.Nms.Listener
{
base.PrepareSharedConnection(connection);
connection.ExceptionListener += OnException;
- }
+ }
+
+ ///
+ /// implementation, invoked by the NMS provider in
+ /// case of connection failures. Re-initializes this listener container's
+ /// shared connection and its sessions and consumers.
+ ///
+ /// The reported connection exception.
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
///
/// The session to work on.
- /// the IMessageConsumer"/>
+ /// the MessageConsumer"/>
/// if thrown by NMS methods
private IMessageConsumer CreateListenerConsumer(ISession session)
{
@@ -216,6 +248,12 @@ namespace Spring.Messaging.Nms.Listener
}
+ ///
+ /// Creates a MessageConsumer for the given Session and Destination.
+ ///
+ /// The session to create a MessageConsumer for.
+ /// The destination to create a MessageConsumer for.
+ /// The new MessageConsumer
protected IMessageConsumer CreateConsumer(ISession session, IDestination destination)
{
// Only pass in the NoLocal flag in case of a Topic:
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/MessageCreatorDelegate.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/MessageCreatorDelegate.cs
index 23090f01..1e87ccf4 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/MessageCreatorDelegate.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/MessageCreatorDelegate.cs
@@ -25,10 +25,10 @@ namespace Spring.Messaging.Nms
///
/// Delegate that creates a NMS message given a ISession
///
- /// the NMS ISession to be used to create the
- /// IMessage (never null)
+ /// the NMS Session to be used to create the
+ /// Message (never null)
///
- /// the IMessage to be sent
+ /// the Message to be sent
///
/// NMSException if thrown by NMS API methods
public delegate IMessage IMessageCreatorDelegate(ISession session);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsGatewaySupport.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsGatewaySupport.cs
index 386e53de..4ce57abe 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsGatewaySupport.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsGatewaySupport.cs
@@ -29,9 +29,9 @@ namespace Spring.Messaging.Nms
/// Convenient super class for application classes that need NMS access.
///
///
- /// 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 createNmsTemplate method.
///
///
@@ -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
///
/// 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.
///
/// The connection factory.
public IConnectionFactory ConnectionFactory
@@ -75,9 +75,9 @@ namespace Spring.Messaging.Nms
}
///
- /// Creates a NmsTemplate for the given IConnectionFactory.
+ /// Creates a NmsTemplate for the given ConnectionFactory.
///
- /// Only invoked if populating the gateway with a IConnectionFactory reference.
+ /// Only invoked if populating the gateway with a ConnectionFactory reference.
/// Can be overridden in subclasses to provide a different NmsTemplate instance
///
///
@@ -88,6 +88,9 @@ namespace Spring.Messaging.Nms
return new NmsTemplate(connectionFactory);
}
+ ///
+ /// Ensures that the JmsTemplate is specified and calls .
+ ///
public void AfterPropertiesSet()
{
if (jmsTemplate == null)
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsTemplate.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsTemplate.cs
index 35c6e712..41c39beb 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsTemplate.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/NmsTemplate.cs
@@ -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.
///
- /// Default settings for NMS ISessions are "not transacted" and "auto-acknowledge".
+ /// Default settings for NMS Sessions is "auto-acknowledge".
///
/// 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
+ ///
+ /// Timeout value indicating that a receive operation should
+ /// check if a message is immediately available without blocking.
+ ///
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
/// Create a new NmsTemplate.
///
- /// Note: The IConnectionFactory has to be set before using the instance.
+ /// 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.
+ /// typically setting the ConnectionFactory.
///
public NmsTemplate()
{
@@ -103,8 +105,8 @@ namespace Spring.Messaging.Nms
}
- /// Create a new NmsTemplate, given a IConnectionFactory.
- /// the IConnectionFactory to obtain IConnections from
+ /// Create a new NmsTemplate, given a ConnectionFactory.
+ /// the ConnectionFactory to obtain IConnections from
///
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
}
/// Execute the action specified by the given action object within a
- /// NMS ISession.
+ /// NMS Session.
///
/// Generalized version of execute(ISessionCallback),
- /// allowing the NMS IConnection to be started on the fly.
+ /// allowing the NMS Connection to be started on the fly.
/// Use execute(ISessionCallback) 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 receive methods.
///
/// 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..
///
- /// Gets or sets a value indicating whether IMessageIds are.
+ /// Gets or sets a value indicating whether Message Ids are enabled.
///
- /// true if [message id enabled]; otherwise, false.
+ /// true if message id enabled; otherwise, false.
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.
///
/// Gets or sets a value indicating whether message timestamps are enabled.
///
@@ -326,9 +326,6 @@ namespace Spring.Messaging.Nms
set { persistent = value; }
}
-
- //TODO verify admin...
-
///
/// Gets or sets the priority when sending.
///
@@ -358,6 +355,11 @@ namespace Spring.Messaging.Nms
#endregion
+ ///
+ /// Extract the content from the given JMS message.
+ ///
+ /// The Message to convert (can be null).
+ /// The content of the message, or null if none
protected virtual object DoConvertFromMessage(IMessage message)
{
if (message != null)
@@ -369,7 +371,7 @@ namespace Spring.Messaging.Nms
#region NMS Factory Methods
- /// Fetch an appropriate IConnection from the given NmsResourceHolder.
+ /// Fetch an appropriate Connection from the given NmsResourceHolder.
///
/// the NmsResourceHolder
///
@@ -381,7 +383,7 @@ namespace Spring.Messaging.Nms
return holder.GetConnection();
}
- /// Fetch an appropriate ISession from the given NmsResourceHolder.
+ /// Fetch an appropriate Session from the given NmsResourceHolder.
///
/// the NmsResourceHolder
///
@@ -393,16 +395,16 @@ namespace Spring.Messaging.Nms
return holder.GetSession();
}
- /// Create a NMS IMessageProducer for the given ISession and IDestination,
+ /// Create a NMS MessageProducer for the given Session and Destination,
/// configuring it to disable message ids and/or timestamps (if necessary).
/// Delegates to doCreateProducer for creation of the raw
- /// NMS IMessageProducer, which needs to be specific to NMS 1.1 or 1.0.2.
+ /// NMS MessageProducer
///
- /// the NMS ISession to create a IMessageProducer for
+ /// the NMS Session to create a MessageProducer for
///
- /// the NMS IDestination to create a IMessageProducer for
+ /// the NMS Destination to create a MessageProducer for
///
- /// the new NMS IMessageProducer
+ /// the new NMS MessageProducer
///
/// NMSException if thrown by NMS API methods
///
@@ -426,14 +428,33 @@ namespace Spring.Messaging.Nms
}
- /// Create a raw NMS IMessageProducer for the given ISession and IDestination.
- /// This implementation uses NMS 1.1 API.
+ ///
+ /// 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.
///
- /// the NMS ISession to create a IMessageProducer for
+ ///
+ /// 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.
+ ///
+ /// The session to check.
+ ///
+ /// true if the session is locally transacted; otherwise, false.
+ ///
+ protected virtual bool IsSessionLocallyTransacted(ISession session)
+ {
+ return SessionTransacted &&
+ !ConnectionFactoryUtils.IsSessionTransactional(session, ConnectionFactory);
+ }
+
+ /// Create a raw NMS MessageProducer for the given Session and Destination.
+ ///
+ /// the NMS Session to create a MessageProducer for
///
- /// the NMS IDestination to create a IMessageProducer for
+ /// the NMS IDestination to create a MessageProducer for
///
- /// the new NMS IMessageProducer
+ /// the new NMS MessageProducer
///
/// NMSException if thrown by NMS API methods
protected virtual IMessageProducer DoCreateProducer(ISession session, IDestination destination)
@@ -441,12 +462,11 @@ namespace Spring.Messaging.Nms
return session.CreateProducer(destination);
}
- /// Create a NMS IMessageConsumer for the given ISession and IDestination.
- /// This implementation uses NMS 1.1 API.
+ /// Create a NMS MessageConsumer for the given Session and Destination.
///
- /// the NMS ISession to create a IMessageConsumer for
+ /// the NMS Session to create a MessageConsumer for
///
- /// the NMS IDestination to create a IMessageConsumer for
+ /// the NMS Destination to create a MessageConsumer for
///
/// the message selector for this consumer (can be null)
///
@@ -469,14 +489,24 @@ namespace Spring.Messaging.Nms
}
}
- //TODO refactor to not pass null as a 'switch' for behavior.
-
+ ///
+ /// Send the given message.
+ ///
+ /// The session to operate on.
+ /// The destination to send to.
+ /// The message creator delegate callback to create a Message.
protected internal virtual void DoSend(ISession session, IDestination destination, IMessageCreatorDelegate messageCreatorDelegate)
{
AssertUtils.ArgumentNotNull(messageCreatorDelegate, "IMessageCreatorDelegate must not be null");
DoSend(session, destination, null, messageCreatorDelegate);
}
+ ///
+ /// Send the given message.
+ ///
+ /// The session to operate on.
+ /// The destination to send to.
+ /// The message creator callback to create a Message.
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
}
/// Send the given NMS message.
- /// the NMS ISession to operate on
+ /// the NMS Session to operate on
///
- /// the NMS IDestination to send to
+ /// the NMS Destination to send to
///
- /// callback to create a NMS IMessage
+ /// callback to create a NMS Message
///
- /// delegate callback to create a NMS IMessage
+ /// delegate callback to create a NMS Message
///
/// NMSException if thrown by NMS API methods
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
/// Actually send the given NMS message.
- /// the NMS IMessageProducer to send with
+ /// the NMS MessageProducer to send with
///
- /// the NMS IMessage to send
+ /// the NMS Message to send
///
/// NMSException if thrown by NMS API methods
protected virtual void DoSend(IMessageProducer producer, IMessage message)
@@ -554,10 +584,10 @@ namespace Spring.Messaging.Nms
#region INmsOperations Implementation
/// Execute the action specified by the given action object within
- /// a NMS ISession.
- /// 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.
+ /// a NMS Session.
+ /// 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.
///
/// callback object that exposes the session
///
@@ -570,7 +600,7 @@ namespace Spring.Messaging.Nms
}
/// 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.
///
/// callback object that exposes the session/producer pair
@@ -603,7 +633,7 @@ namespace Spring.Messaging.Nms
}
/// 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.
///
/// the destination to send this message to
///
@@ -616,7 +646,7 @@ namespace Spring.Messaging.Nms
}
/// 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.
///
/// 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
}
/// 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.
///
/// the destination to send this message to
///
@@ -663,7 +693,7 @@ namespace Spring.Messaging.Nms
}
/// 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.
///
/// the destination to send this message to
///
@@ -898,12 +928,25 @@ namespace Spring.Messaging.Nms
return Execute(new ReceiveSelectedCallback(this, destinationName, messageSelector), true) as IMessage;
}
-
+
+ ///
+ /// Receive a message.
+ ///
+ /// The session to operate on.
+ /// The destination to receive from.
+ /// The message selector for this consumer (can be null
+ /// The Message received, or null if none.
protected virtual IMessage DoReceive(ISession session, IDestination destination, string messageSelector)
{
return DoReceive(session, CreateConsumer(session, destination, messageSelector));
}
-
+
+ ///
+ /// Receive a message.
+ ///
+ /// The session to operate on.
+ /// The consumer to receive with.
+ /// The Message received, or null if none
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
+ ///
+ /// ResourceFactory implementation that delegates to this template's callback methods.
+ ///
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; }
}
}
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/IMessageConverter.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/IMessageConverter.cs
index 214119e0..23368542 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/IMessageConverter.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/IMessageConverter.cs
@@ -31,25 +31,25 @@ namespace Spring.Messaging.Nms.Support.Converter
/// Mark Pollack (.NET)
public interface IMessageConverter
{
- /// Convert a .NET object to a NMS IMessage using the supplied session
+ /// Convert a .NET object to a NMS Message using the supplied session
/// to create the message object.
///
/// the object to convert
///
- /// the ISession to use for creating a NMS IMessage
+ /// the Session to use for creating a NMS Message
///
- /// the NMS IMessage
+ /// the NMS Message
///
/// NMSException if thrown by NMS API methods
- /// IMessageConversionException in case of conversion failure
+ /// MessageConversionException in case of conversion failure
IMessage ToMessage(object objectToConvert, ISession session);
- /// Convert from a NMS IMessage to a .NET object.
+ /// Convert from a NMS Message to a .NET object.
/// the message to convert
///
/// the converted .NET object
///
- /// IMessageConversionException in case of conversion failure
+ /// MessageConversionException in case of conversion failure
object FromMessage(IMessage message);
}
}
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/MessageConversionException.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/MessageConversionException.cs
index c7fbca9f..8c1f1fd9 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/MessageConversionException.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/MessageConversionException.cs
@@ -19,24 +19,18 @@
#endregion
using System;
-using System.Runtime.Serialization;
+using Apache.NMS;
namespace Spring.Messaging.Nms.Support.Converter
{
/// Thrown by IMessageConverter implementations when the conversion
- /// of an object to/from a IMessage fails.
- ///
+ /// of an object to/from a Message fails.
///
/// Mark Pollack
- [Serializable]
- public class IMessageConversionException : ApplicationException
+ public class MessageConversionException : NMSException
{
- //TODO add jms root exception hierarchy?....
#region Constructor (s) / Destructor
- /// Creates a new instance of the IMessageConverterException class.
- public IMessageConversionException()
- {
- }
+
///
/// Creates a new instance of the IMessageConverterException class. with the specified message.
@@ -44,7 +38,7 @@ namespace Spring.Messaging.Nms.Support.Converter
///
/// A message about the exception.
///
- public IMessageConversionException(string message)
+ public MessageConversionException(string message)
: base(message)
{
}
@@ -59,27 +53,11 @@ namespace Spring.Messaging.Nms.Support.Converter
///
/// The root exception that is being wrapped.
///
- public IMessageConversionException(string message, Exception rootCause)
+ public MessageConversionException(string message, Exception rootCause)
: base(message, rootCause)
{
}
- ///
- /// Creates a new instance of the IMessageConverterException class.
- ///
- ///
- /// The
- /// that holds the serialized object data about the exception being thrown.
- ///
- ///
- /// The
- /// that contains contextual information about the source or destination.
- ///
- protected IMessageConversionException(
- SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- }
#endregion
}
}
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/SimpleMessageConverter.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/SimpleMessageConverter.cs
index 11fd51b4..f3acf628 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/SimpleMessageConverter.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Converter/SimpleMessageConverter.cs
@@ -39,17 +39,17 @@ namespace Spring.Messaging.Nms.Support.Converter
/// Mark Pollack (.NET)
public class SimpleMessageConverter : IMessageConverter
{
- /// Convert a .NET object to a NMS IMessage using the supplied session
+ /// Convert a .NET object to a NMS Message using the supplied session
/// to create the message object.
///
/// the object to convert
///
- /// the ISession to use for creating a NMS IMessage
+ /// the Session to use for creating a NMS Message
///
- /// the NMS IMessage
+ /// the NMS Message
///
/// NMSException if thrown by NMS API methods
- /// IMessageConversionException in case of conversion failure
+ /// MessageConversionException in case of conversion failure
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");
}
}
- /// Convert from a NMS IMessage to a .NET object.
+ /// Convert from a NMS Message to a .NET object.
/// the message to convert
///
/// the converted .NET object
///
- /// IMessageConversionException in case of conversion failure
+ /// MessageConversionException in case of conversion failure
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
///
/// the resulting Map
///
- /// NMSException if thrown by NMS methods
+ /// NMSException if thrown by NMS methods
protected virtual IDictionary ExtractMapFromMessage(IMapMessage message)
{
IDictionary dictionary = new Hashtable();
@@ -222,6 +222,11 @@ namespace Spring.Messaging.Nms.Support.Converter
return dictionary;
}
+ ///
+ /// Extracts the serializable object from the given object message.
+ ///
+ /// The message to convert.
+ /// The resulting serializable object.
protected virtual object ExtractSerializableFromMessage(
IObjectMessage message)
{
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/DynamicDestinationResolver.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/DynamicDestinationResolver.cs
index 19ae8811..393ff70b 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/DynamicDestinationResolver.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/DynamicDestinationResolver.cs
@@ -33,7 +33,7 @@ namespace Spring.Messaging.Nms.Support.IDestinations
/// Resolve the given destination name, either as located resource
/// or as dynamic destination.
///
- /// the current NMS ISession
+ /// the current NMS Session
///
/// the name of the destination
///
@@ -58,7 +58,7 @@ namespace Spring.Messaging.Nms.Support.IDestinations
/// Resolve the given destination name to a Topic.
- /// the current NMS ISession
+ /// the current NMS Session
///
/// the name of the desired Topic.
///
@@ -70,6 +70,14 @@ namespace Spring.Messaging.Nms.Support.IDestinations
return session.GetTopic(topicName);
}
+ /// Resolve the given destination name to a Queue.
+ /// the current NMS Session
+ ///
+ /// the name of the desired Queue.
+ ///
+ /// the NMS Queue name
+ ///
+ /// NMSException if resolution failed
protected internal virtual IDestination ResolveQueue(ISession session, string queueName)
{
return session.GetQueue(queueName);
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/IDestinationResolver.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/IDestinationResolver.cs
index f818c4af..921305ae 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/IDestinationResolver.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/Destinations/IDestinationResolver.cs
@@ -43,7 +43,7 @@ namespace Spring.Messaging.Nms.Support.IDestinations
/// Resolve the given destination name, either as located resource
/// or as dynamic destination.
///
- /// the current NMS ISession
+ /// the current NMS Session
///
/// the name of the destination
///
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsAccessor.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsAccessor.cs
index dd0a17c3..4d088d95 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsAccessor.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsAccessor.cs
@@ -25,14 +25,12 @@ using Apache.NMS;
namespace Spring.Messaging.Nms.Support
{
- /// Base class for NmsTemplate and other
- /// NMS-accessing gateway helpers
- /// It defines common properties like the
- /// IConnectionFactory}. The subclass
- /// NmsIDestinationAccessor adds
- /// further, destination-related properties.
- ///
+ /// Base class for NmsTemplate and other NMS-accessing gateway helpers
+ /// It defines common properties like the ConnectionFactory}. The subclass
+ /// NmsIDestinationAccessor adds further, destination-related properties.
+ ///
/// Not intended to be used directly. See NmsTemplate.
+ ///
///
/// Juergen Hoeller
/// Mark Pollack (.NET)
@@ -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
///
- /// Gets or sets the connection factory to use for obtaining NMS IConnections.
+ /// Gets or sets the connection factory to use for obtaining NMS Connections.
///
/// The connection factory.
virtual public IConnectionFactory ConnectionFactory
@@ -78,8 +76,7 @@ namespace Spring.Messaging.Nms.Support
///
///
/// Set the NMS acknowledgement mode that is used when creating a NMS
- /// ISession to send a message. The default is ISession.AUTO_ACKNOWLEDGE.
- /// Vendor-specific extensions to the acknowledgment mode can be set here as well.
+ /// Session to send a message. The default is AUTO_ACKNOWLEDGE.
///
/// The session acknowledge mode.
virtual public AcknowledgementMode SessionAcknowledgeMode
@@ -112,7 +109,10 @@ namespace Spring.Messaging.Nms.Support
///
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
+ ///
+ /// Verify that ConnectionFactory property has been set.
+ ///
public virtual void AfterPropertiesSet()
{
if (ConnectionFactory == null)
@@ -142,6 +145,11 @@ namespace Spring.Messaging.Nms.Support
return ConnectionFactory.CreateConnection();
}
+ ///
+ /// Creates the session for the given Connection
+ ///
+ /// The connection to create a session for.
+ /// The new session
protected virtual ISession CreateSession(IConnection con)
{
return con.CreateSession(SessionAcknowledgeMode);
@@ -150,9 +158,9 @@ namespace Spring.Messaging.Nms.Support
///
/// Returns whether the ISession is in client acknowledgement mode.
///
- /// The session.
- /// true ifin client ack mode, false otherwise
- protected virtual bool ClientAcknowledge(ISession session)
+ /// The session to check.
+ /// true if in client ack mode, false otherwise
+ protected virtual bool IsClientAcknowledge(ISession session)
{
return (session.AcknowledgementMode == AcknowledgementMode.ClientAcknowledge);
}
diff --git a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsUtils.cs b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsUtils.cs
index 91232f14..47f3134b 100644
--- a/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsUtils.cs
+++ b/src/Spring/Spring.Messaging.Nms/Messaging/Nms/Support/NmsUtils.cs
@@ -25,6 +25,10 @@ using Apache.NMS;
namespace Spring.Messaging.Nms.Support
{
+ ///
+ /// Generic utility methods for working with NMS. Mainly for internal use
+ /// within the framework, but also useful for custom NMS access code.
+ ///
public abstract class NmsUtils
{
#region Logging
@@ -33,20 +37,20 @@ namespace Spring.Messaging.Nms.Support
#endregion
- /// Close the given NMS IConnection and ignore any thrown exception.
+ /// Close the given NMS Connection and ignore any thrown exception.
/// This is useful for typical finally blocks in manual NMS code.
///
- /// the NMS IConnection to close (may be null)
+ /// the NMS Connection to close (may be null)
///
public static void CloseConnection(IConnection con)
{
CloseConnection(con, false);
}
- /// Close the given NMS IConnection and ignore any thrown exception.
+ /// Close the given NMS Connection and ignore any thrown exception.
/// This is useful for typical finally blocks in manual NMS code.
///
- /// the NMS IConnection to close (may be null)
+ /// the NMS Connection to close (may be null)
///
/// whether to call stop() before closing
///
@@ -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);
}
}
}
- /// Close the given NMS ISession and ignore any thrown exception.
+ /// Close the given NMS Session and ignore any thrown exception.
/// This is useful for typical finally blocks in manual NMS code.
///
- /// the NMS ISession to close (may be null)
+ /// the NMS Session to close (may be null)
///
public static void CloseSession(ISession session)
{
@@ -109,10 +113,10 @@ namespace Spring.Messaging.Nms.Support
}
}
- /// Close the given NMS IMessageProducer and ignore any thrown exception.
+ /// Close the given NMS MessageProducer and ignore any thrown exception.
/// This is useful for typical finally blocks in manual NMS code.
///
- /// the NMS IMessageProducer to close (may be null)
+ /// the NMS MessageProducer to close (may be null)
///
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);
}
}
}
- /// Close the given NMS IMessageConsumer and ignore any thrown exception.
+ /// Close the given NMS MessageConsumer and ignore any thrown exception.
/// This is useful for typical finally blocks in manual NMS code.
///
- /// the NMS IMessageConsumer to close (may be null)
+ /// the NMS MessageConsumer to close (may be null)
///
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
// }
- /// Commit the ISession if not within a distributed transaction.
- /// Needs investigation - no distributed tx in EMS
- /// the NMS ISession to commit
+ /// Commit the Session if not within a distributed transaction.
+ /// Needs investigation - no distributed tx in .NET messaging providers
+ /// the NMS Session to commit
///
- /// NMSException if committing failed
+ /// NMSException if committing failed
public static void CommitIfNecessary(ISession session)
{
AssertUtils.ArgumentNotNull(session, "ISession must not be null");
@@ -212,9 +216,9 @@ namespace Spring.Messaging.Nms.Support
// }
}
- /// Rollback the ISession if not within a distributed transaction.
+ /// Rollback the Session if not within a distributed transaction.
/// Needs investigation - no distributed tx in EMS
- /// the NMS ISession to rollback
+ /// the NMS Session to rollback
///
/// NMSException if committing failed
public static void RollbackIfNecessary(ISession session)
diff --git a/src/Spring/Spring.Messaging.Nms/Spring.Messaging.Nms.2005.csproj b/src/Spring/Spring.Messaging.Nms/Spring.Messaging.Nms.2005.csproj
index d181f9b1..517aa631 100644
--- a/src/Spring/Spring.Messaging.Nms/Spring.Messaging.Nms.2005.csproj
+++ b/src/Spring/Spring.Messaging.Nms/Spring.Messaging.Nms.2005.csproj
@@ -19,6 +19,7 @@
prompt
4
..\..\..\build\VS.NET.2005\Spring.Messaging.Nms\Debug\Spring.Messaging.Nms.xml
+ true
pdbonly
@@ -67,7 +68,6 @@
-