Add NmsTransactionManager + tests
Initial work for SingleConnectionFactory
This commit is contained in:
@@ -19,9 +19,10 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
using Common.Logging;
|
||||
using Spring.Transaction.Support;
|
||||
using Spring.Util;
|
||||
using Apache.NMS;
|
||||
|
||||
namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
@@ -33,7 +34,11 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public abstract class ConnectionFactoryUtils
|
||||
{
|
||||
|
||||
#region Logging
|
||||
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(ConnectionFactoryUtils));
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary> Obtain a NMS ISession that is synchronized with the current transaction, if any.</summary>
|
||||
/// <param name="cf">the IConnectionFactory to obtain a ISession for
|
||||
@@ -50,10 +55,13 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// <returns> the transactional ISession, or <code>null</code> if none found
|
||||
/// </returns>
|
||||
/// <throws> NMSException in case of NMS failure </throws>
|
||||
public static ISession GetTransactionalSession(IConnectionFactory cf, IConnection existingCon, bool synchedLocalTransactionAllowed)
|
||||
public static ISession GetTransactionalSession(IConnectionFactory cf, IConnection existingCon,
|
||||
bool synchedLocalTransactionAllowed)
|
||||
{
|
||||
|
||||
return DoGetTransactionalSession(cf, new AnonymousClassResourceFactory(existingCon, cf, synchedLocalTransactionAllowed));
|
||||
return
|
||||
DoGetTransactionalSession(cf,
|
||||
new AnonymousClassResourceFactory(existingCon, cf,
|
||||
synchedLocalTransactionAllowed));
|
||||
}
|
||||
|
||||
/// <summary> Obtain a NMS ISession that is synchronized with the current transaction, if any.</summary>
|
||||
@@ -66,13 +74,13 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// <returns> the transactional ISession, or <code>null</code> if none found
|
||||
/// </returns>
|
||||
/// <throws>NMSException in case of NMS failure </throws>
|
||||
public static ISession DoGetTransactionalSession(System.Object resourceKey, ConnectionFactoryUtils.ResourceFactory resourceFactory)
|
||||
public static ISession DoGetTransactionalSession(Object resourceKey, ResourceFactory resourceFactory)
|
||||
{
|
||||
|
||||
AssertUtils.ArgumentNotNull(resourceKey, "Resource key must not be null");
|
||||
AssertUtils.ArgumentNotNull(resourceKey, "ResourceFactory must not be null");
|
||||
|
||||
NmsResourceHolder resourceHolder = (NmsResourceHolder)TransactionSynchronizationManager.GetResource(resourceKey);
|
||||
NmsResourceHolder resourceHolder =
|
||||
(NmsResourceHolder)TransactionSynchronizationManager.GetResource(resourceKey);
|
||||
if (resourceHolder != null)
|
||||
{
|
||||
ISession rssession = resourceFactory.GetSession(resourceHolder);
|
||||
@@ -90,7 +98,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
conHolderToUse = new NmsResourceHolder();
|
||||
}
|
||||
Apache.NMS.IConnection con = resourceFactory.GetConnection(conHolderToUse);
|
||||
IConnection con = resourceFactory.GetConnection(conHolderToUse);
|
||||
ISession session = null;
|
||||
try
|
||||
{
|
||||
@@ -115,7 +123,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
session.Close();
|
||||
}
|
||||
catch (System.Exception)
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
@@ -126,7 +134,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
con.Close();
|
||||
}
|
||||
catch (System.Exception)
|
||||
catch (Exception)
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
@@ -135,52 +143,90 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
}
|
||||
if (conHolderToUse != resourceHolder)
|
||||
{
|
||||
TransactionSynchronizationManager.RegisterSynchronization(new NmsResourceSynchronization(resourceKey, conHolderToUse, resourceFactory.SynchedLocalTransactionAllowed));
|
||||
TransactionSynchronizationManager.RegisterSynchronization(
|
||||
new NmsResourceSynchronization(resourceKey, conHolderToUse,
|
||||
resourceFactory.SynchedLocalTransactionAllowed));
|
||||
conHolderToUse.SynchronizedWithTransaction = true;
|
||||
TransactionSynchronizationManager.BindResource(resourceKey, conHolderToUse);
|
||||
}
|
||||
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 : ConnectionFactoryUtils.ResourceFactory
|
||||
private class AnonymousClassResourceFactory : ResourceFactory
|
||||
{
|
||||
private IConnection existingCon;
|
||||
private IConnectionFactory cf;
|
||||
private bool synchedLocalTransactionAllowed;
|
||||
|
||||
public AnonymousClassResourceFactory(Apache.NMS.IConnection existingCon, IConnectionFactory cf, bool synchedLocalTransactionAllowed)
|
||||
public AnonymousClassResourceFactory(IConnection existingCon, IConnectionFactory cf,
|
||||
bool synchedLocalTransactionAllowed)
|
||||
{
|
||||
InitBlock(existingCon, cf, synchedLocalTransactionAllowed);
|
||||
}
|
||||
|
||||
private void InitBlock(Apache.NMS.IConnection existingCon, IConnectionFactory cf, bool synchedLocalTransactionAllowed)
|
||||
private void InitBlock(IConnection existingCon, IConnectionFactory cf, bool synchedLocalTransactionAllowed)
|
||||
{
|
||||
this.existingCon = existingCon;
|
||||
this.cf = cf;
|
||||
this.synchedLocalTransactionAllowed = synchedLocalTransactionAllowed;
|
||||
}
|
||||
|
||||
|
||||
public virtual ISession GetSession(NmsResourceHolder holder)
|
||||
{
|
||||
return holder.GetSession(typeof(ISession), existingCon);
|
||||
return holder.GetSession(typeof(ISession), existingCon);
|
||||
}
|
||||
|
||||
public virtual Apache.NMS.IConnection GetConnection(NmsResourceHolder holder)
|
||||
public virtual IConnection GetConnection(NmsResourceHolder holder)
|
||||
{
|
||||
return (existingCon != null ? existingCon : holder.GetConnection());
|
||||
return (existingCon != null ? existingCon : holder.GetConnection());
|
||||
}
|
||||
|
||||
public virtual Apache.NMS.IConnection CreateConnection()
|
||||
public virtual IConnection CreateConnection()
|
||||
{
|
||||
return cf.CreateConnection();
|
||||
}
|
||||
|
||||
public virtual ISession CreateSession(Apache.NMS.IConnection con)
|
||||
public virtual ISession CreateSession(IConnection con)
|
||||
{
|
||||
if (synchedLocalTransactionAllowed)
|
||||
{
|
||||
@@ -190,7 +236,6 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
return con.CreateSession(AcknowledgementMode.AutoAcknowledge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public bool SynchedLocalTransactionAllowed
|
||||
@@ -198,6 +243,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
get { return synchedLocalTransactionAllowed; }
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper classes/interfaces
|
||||
@@ -207,7 +253,6 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// </summary>
|
||||
public interface ResourceFactory
|
||||
{
|
||||
|
||||
/// <summary> Fetch an appropriate ISession from the given NmsResourceHolder.</summary>
|
||||
/// <param name="holder">the NmsResourceHolder
|
||||
/// </param>
|
||||
@@ -236,7 +281,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// <returns> the new NMS ISession
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
ISession CreateSession(Apache.NMS.IConnection con);
|
||||
ISession CreateSession(IConnection con);
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -247,17 +292,13 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// Returns whether to allow for synchronizing a local NMS transaction
|
||||
/// </summary>
|
||||
///
|
||||
bool SynchedLocalTransactionAllowed
|
||||
{
|
||||
get;
|
||||
}
|
||||
bool SynchedLocalTransactionAllowed { get; }
|
||||
}
|
||||
|
||||
/// <summary> Callback for resource cleanup at the end of a non-native NMS transaction
|
||||
/// </summary>
|
||||
private class NmsResourceSynchronization : TransactionSynchronizationAdapter
|
||||
{
|
||||
|
||||
private object resourceKey;
|
||||
|
||||
private NmsResourceHolder resourceHolder;
|
||||
@@ -275,7 +316,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
|
||||
public override void Suspend()
|
||||
{
|
||||
if (this.holderActive)
|
||||
if (holderActive)
|
||||
{
|
||||
TransactionSynchronizationManager.UnbindResource(resourceKey);
|
||||
}
|
||||
@@ -283,7 +324,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
|
||||
public override void Resume()
|
||||
{
|
||||
if (this.holderActive)
|
||||
if (holderActive)
|
||||
{
|
||||
TransactionSynchronizationManager.BindResource(resourceKey, resourceHolder);
|
||||
}
|
||||
@@ -291,22 +332,22 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
|
||||
public override void BeforeCompletion()
|
||||
{
|
||||
TransactionSynchronizationManager.UnbindResource(this.resourceKey);
|
||||
this.holderActive = false;
|
||||
TransactionSynchronizationManager.UnbindResource(resourceKey);
|
||||
holderActive = false;
|
||||
if (!transacted)
|
||||
{
|
||||
this.resourceHolder.CloseAll();
|
||||
resourceHolder.CloseAll();
|
||||
}
|
||||
}
|
||||
|
||||
//TODO bring in new Spring.Data library to Integration project which has this method in interface.
|
||||
public override void AfterCommit()
|
||||
{
|
||||
if (this.transacted)
|
||||
if (transacted)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.resourceHolder.CommitAll();
|
||||
resourceHolder.CommitAll();
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
@@ -317,12 +358,13 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
|
||||
public override void AfterCompletion(TransactionSynchronizationStatus status)
|
||||
{
|
||||
if (this.transacted)
|
||||
if (transacted)
|
||||
{
|
||||
this.resourceHolder.CloseAll();
|
||||
resourceHolder.CloseAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
|
||||
#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.IConnections
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension of the <code>IConnectionFactory</code> interface,
|
||||
/// indicating how to release Connections obtained from it.
|
||||
/// </summary>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public interface ISmartConnectionFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Shoulds we stop the connection, obtained from this ConnectionFactory?
|
||||
/// </summary>
|
||||
/// <param name="con">The connection to check.</param>
|
||||
/// <returns>wheter a stop call is necessary</returns>
|
||||
bool ShouldStop(IConnection con);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
private IList sessions = new LinkedList();
|
||||
|
||||
private IDictionary sessionsPerIConnection = new Hashtable();
|
||||
private IConnectionFactory connectionFactory;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -71,12 +72,20 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
/// </param>
|
||||
/// <param name="session">the NMS ISession
|
||||
/// </param>
|
||||
public NmsResourceHolder(Apache.NMS.IConnection connection, ISession session)
|
||||
public NmsResourceHolder(Apache.NMS.IConnection connection, ISession session)
|
||||
{
|
||||
AddConnection(connection);
|
||||
AddSession(session, connection);
|
||||
this.frozen = true;
|
||||
}
|
||||
|
||||
public NmsResourceHolder(IConnectionFactory connectionFactory, IConnection connection, ISession session)
|
||||
{
|
||||
this.connectionFactory = connectionFactory;
|
||||
AddConnection(connection);
|
||||
AddSession(session, connection);
|
||||
this.frozen = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@@ -191,25 +200,17 @@ namespace Spring.Messaging.Nms.IConnections
|
||||
logger.Debug("Could not close NMS ISession after transaction", ex);
|
||||
}
|
||||
}
|
||||
foreach (Apache.NMS.IConnection connection in connections)
|
||||
foreach (IConnection connection in connections)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
connection.Stop();
|
||||
}
|
||||
finally
|
||||
{
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Debug("Could not close NMS IConnection after transaction", ex);
|
||||
}
|
||||
ConnectionFactoryUtils.ReleaseConnection(connection, connectionFactory, true);
|
||||
}
|
||||
}
|
||||
|
||||
public bool ContainsSession(ISession session)
|
||||
{
|
||||
return this.sessions.Contains(session);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Data;
|
||||
using Apache.NMS;
|
||||
using Common.Logging;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Transaction;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="AbstractPlatformTransactionManager"/> implementation
|
||||
/// for a single NMS <code>Apache.NMS.IConnectionFactory</code>. Binds a
|
||||
/// Connection/Session pair from the specified ConnecctionFactory to the thread,
|
||||
/// potentially allowing for one thread-bound Session per ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Application code is required to retrieve the transactional Session via
|
||||
/// <see cref="ConnectionFactoryUtils.GetTransactionalSession"/>. Spring's
|
||||
/// <see cref="NmsTemplate"/> will autodetect a thread-bound Session and
|
||||
/// automatically participate in it.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This transaction strategy will typically be used in combination with
|
||||
/// <see cref="SingleConnectionFactory"/>, which uses a single NMS Connection
|
||||
/// for all NMS access in order to avoid the overhead of repeated Connection
|
||||
/// creation. Each transaction will then share the same NMS Connection, while still using
|
||||
/// its own individual Session.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Transaction synchronization is turned off by default, as this manager might be used
|
||||
/// alongside an IDbProvider based Spring transaction manager such as the
|
||||
/// AdoPlatformTransactionManager, which has stronger needs for synchronization.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class NmsTransactionManager : AbstractPlatformTransactionManager,
|
||||
IResourceTransactionManager, IInitializingObject
|
||||
{
|
||||
|
||||
#region Logging Definition
|
||||
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(NmsTransactionManager));
|
||||
|
||||
#endregion
|
||||
|
||||
private IConnectionFactory connectionFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NmsTransactionManager"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ConnectionFactory has to be set before using the instance.
|
||||
/// This constructor can be used to prepare a NmsTemplate via a ApplicationContext,
|
||||
/// typically setting the ConnectionFactory via ConnectionFactory property.
|
||||
/// <para>
|
||||
/// Turns off transaction synchronization by default, as this manager might
|
||||
/// be used alongside a dbprovider-based Spring transaction manager like
|
||||
/// AdoPlatformTransactionManager, which has stronger needs for synchronization.
|
||||
/// Only one manager is allowed to drive synchronization at any point of time.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public NmsTransactionManager()
|
||||
{
|
||||
TransactionSynchronization = TransactionSynchronizationState.Never;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NmsTransactionManager"/> class
|
||||
/// given a ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <param name="connectionFactory">The connection factory to obtain connections from.</param>
|
||||
public NmsTransactionManager(IConnectionFactory connectionFactory) : this()
|
||||
{
|
||||
ConnectionFactory = connectionFactory;
|
||||
AfterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the connection factory that this instance should manage transaction.
|
||||
/// for.
|
||||
/// </summary>
|
||||
/// <value>The connection factory.</value>
|
||||
public IConnectionFactory ConnectionFactory
|
||||
{
|
||||
get { return connectionFactory; }
|
||||
set
|
||||
{
|
||||
//TODO if create TransactionAwareConnectionFactoryProxy need to check for it here.
|
||||
connectionFactory = value;
|
||||
}
|
||||
}
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the ConnectionFactory has been set.
|
||||
/// </summary>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
if (ConnectionFactory == null)
|
||||
{
|
||||
throw new ArgumentException("Property 'ConnectionFactory' is required.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IResourceTransactionManager Members
|
||||
|
||||
/// <summary>
|
||||
/// Gets the resource factory that this transaction manager operates on,
|
||||
/// In tihs case the ConnectionFactory
|
||||
/// </summary>
|
||||
/// <value>The ConnectionFactory.</value>
|
||||
public object ResourceFactory
|
||||
{
|
||||
get { return ConnectionFactory; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
protected override object DoGetTransaction()
|
||||
{
|
||||
NmsTransactionObject txObject = new NmsTransactionObject();
|
||||
|
||||
txObject.ResourceHolder =
|
||||
(NmsResourceHolder) TransactionSynchronizationManager.GetResource(ConnectionFactory);
|
||||
return txObject;
|
||||
}
|
||||
|
||||
protected override void DoBegin(object transaction, ITransactionDefinition definition)
|
||||
{
|
||||
//This is the default value defined in DefaultTransactionDefinition
|
||||
if (definition.TransactionIsolationLevel != IsolationLevel.ReadCommitted)
|
||||
{
|
||||
throw new InvalidIsolationLevelException("NMS does not support an isoliation level concept");
|
||||
}
|
||||
NmsTransactionObject txObject = (NmsTransactionObject) transaction;
|
||||
IConnection con = null;
|
||||
ISession session = null;
|
||||
try
|
||||
{
|
||||
con = CreateConnection();
|
||||
session = CreateSession(con);
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
log.Debug("Created NMS transaction on Session [" + session + "] from Connection [" + con + "]");
|
||||
}
|
||||
txObject.ResourceHolder = new NmsResourceHolder(ConnectionFactory, con, session);
|
||||
txObject.ResourceHolder.SynchronizedWithTransaction = true;
|
||||
int timeout = DetermineTimeout(definition);
|
||||
if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
|
||||
{
|
||||
txObject.ResourceHolder.TimeoutInSeconds = timeout;
|
||||
}
|
||||
TransactionSynchronizationManager.BindResource(ConnectionFactory, txObject.ResourceHolder);
|
||||
|
||||
|
||||
|
||||
} catch (NMSException ex)
|
||||
{
|
||||
if (session != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
session.Close();
|
||||
} catch (Exception)
|
||||
{}
|
||||
}
|
||||
if (con != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
con.Close();
|
||||
} catch (Exception){}
|
||||
}
|
||||
throw new CannotCreateTransactionException("Could not create NMS Transaction", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override object DoSuspend(object transaction)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject) transaction;
|
||||
txObject.ResourceHolder = null;
|
||||
return TransactionSynchronizationManager.UnbindResource(ConnectionFactory);
|
||||
}
|
||||
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
NmsResourceHolder conHolder = (NmsResourceHolder) suspendedResources;
|
||||
TransactionSynchronizationManager.BindResource(ConnectionFactory, conHolder);
|
||||
}
|
||||
|
||||
protected override void DoCommit(DefaultTransactionStatus status)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
|
||||
ISession session = txObject.ResourceHolder.GetSession();
|
||||
try
|
||||
{
|
||||
if (status.Debug)
|
||||
{
|
||||
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)
|
||||
//{
|
||||
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
throw new TransactionSystemException("Could not commit NMS transaction.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DoRollback(DefaultTransactionStatus status)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
|
||||
ISession session = txObject.ResourceHolder.GetSession();
|
||||
try
|
||||
{
|
||||
if (status.Debug)
|
||||
{
|
||||
LOG.Debug("Rolling back NMS transaction on Session [" + session + "]");
|
||||
}
|
||||
session.Rollback();
|
||||
}
|
||||
catch (NMSException ex)
|
||||
{
|
||||
throw new TransactionSystemException("Could not roll back NMS transaction.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)status.Transaction;
|
||||
txObject.ResourceHolder.RollbackOnly = true;
|
||||
}
|
||||
|
||||
protected override void DoCleanupAfterCompletion(object transaction)
|
||||
{
|
||||
NmsTransactionObject txObject = (NmsTransactionObject)transaction;
|
||||
TransactionSynchronizationManager.UnbindResource(ConnectionFactory);
|
||||
txObject.ResourceHolder.CloseAll();
|
||||
txObject.ResourceHolder.Clear();
|
||||
}
|
||||
|
||||
protected override bool IsExistingTransaction(object transaction)
|
||||
{
|
||||
NmsTransactionObject txObject = transaction as NmsTransactionObject;
|
||||
if (txObject != null)
|
||||
{
|
||||
return txObject.ResourceHolder != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the connection via thie manager's ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <returns>The new Connection</returns>
|
||||
/// <exception cref="NMSException">If thrown by underlying messaging APIs</exception>
|
||||
protected virtual IConnection CreateConnection()
|
||||
{
|
||||
return ConnectionFactory.CreateConnection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the session for the given Connection
|
||||
/// </summary>
|
||||
/// <param name="connection">The connection to create a Session for.</param>
|
||||
/// <returns>the new Session</returns>
|
||||
/// <exception cref="NMSException">If thrown by underlying messaging APIs</exception>
|
||||
protected virtual ISession CreateSession(IConnection connection)
|
||||
{
|
||||
return connection.CreateSession(AcknowledgementMode.Transactional);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// NMS Transaction object, representing a NmsResourceHolder.
|
||||
/// Used as transaction object by NmsTransactionManager
|
||||
/// </summary>
|
||||
internal class NmsTransactionObject : ISmartTransactionObject
|
||||
{
|
||||
private NmsResourceHolder resourceHolder;
|
||||
|
||||
|
||||
public NmsResourceHolder ResourceHolder
|
||||
{
|
||||
get { return resourceHolder; }
|
||||
set { resourceHolder = value; }
|
||||
}
|
||||
|
||||
#region ISmartTransactionObject Members
|
||||
|
||||
public bool RollbackOnly
|
||||
{
|
||||
get { return resourceHolder.RollbackOnly; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
using Common.Logging;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Messaging.Nms.IConnections
|
||||
{
|
||||
public class SingleConnectionFactory : IConnectionFactory, IInitializingObject, IDisposable
|
||||
{
|
||||
#region Logging Definition
|
||||
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof (SingleConnectionFactory));
|
||||
|
||||
#endregion
|
||||
|
||||
private IConnectionFactory targetConnectionFactory;
|
||||
|
||||
private string clientId;
|
||||
|
||||
private ExceptionListener exceptionListenerDelegate;
|
||||
|
||||
private bool reconnectOnException = false;
|
||||
|
||||
/// <summary>
|
||||
/// Wrapped Connection
|
||||
/// </summary>
|
||||
private IConnection target;
|
||||
|
||||
/// <summary>
|
||||
/// Proxy Connection
|
||||
/// </summary>
|
||||
private IConnection connection;
|
||||
|
||||
/// <summary>
|
||||
/// Synchronization monitor for the shared Connection
|
||||
/// </summary>
|
||||
private object connectionMonitor = new object();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SingleConnectionFactory"/> class.
|
||||
/// </summary>
|
||||
public SingleConnectionFactory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SingleConnectionFactory"/> class
|
||||
/// that alwasy returns the given Connection.
|
||||
/// </summary>
|
||||
/// <param name="target">The single Connection.</param>
|
||||
public SingleConnectionFactory(IConnection target)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(target, "connection", "Target Connection must not be null");
|
||||
this.target = target;
|
||||
connection = GetSharedConnection(target);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SingleConnectionFactory"/> class
|
||||
/// that alwasy returns a single Connection.
|
||||
/// </summary>
|
||||
/// <param name="targetConnectionFactory">The target connection factory.</param>
|
||||
public SingleConnectionFactory(IConnectionFactory targetConnectionFactory)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(targetConnectionFactory, "targetConnectionFactory",
|
||||
"Target ConnectionFactory must not be null");
|
||||
this.targetConnectionFactory = targetConnectionFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the target connection factory which will be used to create a single
|
||||
/// connection.
|
||||
/// </summary>
|
||||
/// <value>The target connection factory.</value>
|
||||
public IConnectionFactory TargetConnectionFactory
|
||||
{
|
||||
get { return targetConnectionFactory; }
|
||||
set { targetConnectionFactory = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the client id for the single Connection created and exposed by
|
||||
/// this ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <remarks>Note that the client IDs need to be unique among all active
|
||||
/// Connections of teh underlying provider. Furthermore, a client ID can only
|
||||
/// be assigned if the original ConnectionFactory hasn't already assigned one.</remarks>
|
||||
/// <value>The client id.</value>
|
||||
public string ClientId
|
||||
{
|
||||
get { return clientId; }
|
||||
set { clientId = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exception listener delegate that should be registered with
|
||||
/// the single connection created by this factory.
|
||||
/// </summary>
|
||||
/// <value>The exception listener delegate.</value>
|
||||
public ExceptionListener ExceptionListenerDelegate
|
||||
{
|
||||
get { return exceptionListenerDelegate; }
|
||||
set { exceptionListenerDelegate = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the single Connection
|
||||
/// should be reset (to be subsequently renewed) when a NMSException
|
||||
/// is reported by the underlying Connection.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Default is <code>false</code>. Switch this to <code>true</code>
|
||||
/// to automatically trigger recover based on your messaging provider's
|
||||
/// exception notifications.
|
||||
/// <para>
|
||||
/// Internally, this will lead to a special ExceptionListener (this
|
||||
/// SingleConnectionFactory itself) being registered with the underlying
|
||||
/// Connection. This can also be combined with a user-specified
|
||||
/// ExceptionListener, if desired.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// <c>true</c> if [reconnect on exception]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool ReconnectOnException
|
||||
{
|
||||
get { return reconnectOnException; }
|
||||
set { reconnectOnException = value; }
|
||||
}
|
||||
|
||||
#region IConnectionFactory Members
|
||||
|
||||
public IConnection CreateConnection()
|
||||
{
|
||||
lock (connectionMonitor)
|
||||
{
|
||||
if (connection == null)
|
||||
{
|
||||
InitConnection();
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
|
||||
public void InitConnection()
|
||||
{
|
||||
if (TargetConnectionFactory == null)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"'TargetConnectionFactory' is required for lazily initializing a Connection");
|
||||
}
|
||||
lock (connectionMonitor)
|
||||
{
|
||||
if (this.target != null)
|
||||
{
|
||||
CloseConnection(this.target);
|
||||
}
|
||||
this.target = DoCreateConnection();
|
||||
PrepareConnection(this.target);
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Info("Established shared NMS Connection: " + this.target);
|
||||
}
|
||||
this.connection = GetSharedConnection(this.target);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PrepareConnection(IConnection con)
|
||||
{
|
||||
if (ClientId != null)
|
||||
{
|
||||
con.ClientId = ClientId;
|
||||
}
|
||||
if (ExceptionListenerDelegate != null || ReconnectOnException)
|
||||
{
|
||||
ExceptionListener listenerToUse = ExceptionListenerDelegate;
|
||||
if (ReconnectOnException)
|
||||
{
|
||||
InternalChainedExceptionListenerSupport chained = new InternalChainedExceptionListenerSupport(this, listenerToUse);
|
||||
con.ExceptionListener += chained.OnException;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual IConnection DoCreateConnection()
|
||||
{
|
||||
return TargetConnectionFactory.CreateConnection();
|
||||
}
|
||||
|
||||
private void CloseConnection(IConnection con)
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
con.Stop();
|
||||
} finally
|
||||
{
|
||||
con.Close();
|
||||
}
|
||||
} catch (Exception ex)
|
||||
{
|
||||
LOG.Warn("Could not close shared NMS connection.");
|
||||
}
|
||||
}
|
||||
|
||||
public IConnection CreateConnection(string userName, string password)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
if (connection == null && TargetConnectionFactory == null)
|
||||
{
|
||||
throw new ArgumentException("Connection or 'TargetConnectionFactory' is required.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ResetConnection();
|
||||
}
|
||||
|
||||
public void ResetConnection()
|
||||
{
|
||||
lock (connectionMonitor)
|
||||
{
|
||||
if (this.target != null)
|
||||
{
|
||||
CloseConnection(this.target);
|
||||
}
|
||||
this.target = null;
|
||||
this.connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected virtual IConnection GetSharedConnection(IConnection target)
|
||||
{
|
||||
lock (connectionMonitor)
|
||||
{
|
||||
return new CloseSupressingConnection(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class InternalChainedExceptionListenerSupport
|
||||
{
|
||||
private SingleConnectionFactory factory;
|
||||
private ExceptionListener listenerToUse;
|
||||
public InternalChainedExceptionListenerSupport(SingleConnectionFactory factory, ExceptionListener listenerToUse)
|
||||
{
|
||||
this.factory = factory;
|
||||
this.listenerToUse = listenerToUse;
|
||||
}
|
||||
|
||||
public void OnException(Exception exception)
|
||||
{
|
||||
//TODO exception mgmt.
|
||||
}
|
||||
}
|
||||
|
||||
internal class CloseSupressingConnection : IConnection
|
||||
{
|
||||
private IConnection target;
|
||||
|
||||
public CloseSupressingConnection(IConnection target)
|
||||
{
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public event ExceptionListener ExceptionListener
|
||||
{
|
||||
add { target.ExceptionListener += value; }
|
||||
remove { target.ExceptionListener -= value; }
|
||||
}
|
||||
|
||||
public ISession CreateSession()
|
||||
{
|
||||
return target.CreateSession();
|
||||
}
|
||||
|
||||
public ISession CreateSession(AcknowledgementMode acknowledgementMode)
|
||||
{
|
||||
return target.CreateSession(acknowledgementMode);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
// don't pass the call to the target.
|
||||
}
|
||||
|
||||
public AcknowledgementMode AcknowledgementMode
|
||||
{
|
||||
get { return target.AcknowledgementMode; }
|
||||
set { target.AcknowledgementMode = value; }
|
||||
}
|
||||
|
||||
public string ClientId
|
||||
{
|
||||
get { return target.ClientId; }
|
||||
set { target.ClientId = value; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
target.Dispose();
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
target.Start();
|
||||
}
|
||||
|
||||
public bool IsStarted
|
||||
{
|
||||
get { return target.IsStarted; }
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
//don't pass the call to the target.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Spring.Context;
|
||||
using Spring.Messaging.Nms.IConnections;
|
||||
using Spring.Messaging.Nms.Support;
|
||||
using Spring.Messaging.Nms.Support.IDestinations;
|
||||
using Spring.Util;
|
||||
@@ -505,7 +506,7 @@ namespace Spring.Messaging.Nms.Listener
|
||||
{
|
||||
lock (this.sharedConnectionMonitor)
|
||||
{
|
||||
NmsUtils.CloseConnection(this.sharedConnection);
|
||||
ConnectionFactoryUtils.ReleaseConnection(sharedConnection, ConnectionFactory, autoStartup);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,6 @@ namespace Spring.Messaging.Nms
|
||||
|
||||
private TimeSpan timeToLive;
|
||||
|
||||
private bool cacheNmsResources = true;
|
||||
|
||||
private NmsResources jmsResources = new NmsResources();
|
||||
|
||||
#endregion
|
||||
@@ -180,17 +178,10 @@ namespace Spring.Messaging.Nms
|
||||
return action.DoInNms(sessionToUse);
|
||||
}
|
||||
//TODO make sure don't want to do exception translation.
|
||||
//TODO investigate options to not close session/connection via caching since
|
||||
//these objects are thread safe in tibco ems.
|
||||
finally
|
||||
{
|
||||
if (!CacheNmsResources)
|
||||
{
|
||||
NmsUtils.CloseSession(sessionToClose);
|
||||
NmsUtils.CloseConnection(conToClose, startConnection);
|
||||
}
|
||||
//TODO No IConnectionFactory interface so can't create
|
||||
// non closing impl of IConnection Need NMS.
|
||||
NmsUtils.CloseSession(sessionToClose);
|
||||
ConnectionFactoryUtils.ReleaseConnection(conToClose, ConnectionFactory, startConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,12 +349,6 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
|
||||
|
||||
virtual public bool CacheNmsResources
|
||||
{
|
||||
get { return cacheNmsResources; }
|
||||
set { cacheNmsResources = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected virtual object DoConvertFromMessage(IMessage message)
|
||||
@@ -401,58 +386,6 @@ namespace Spring.Messaging.Nms
|
||||
return holder.GetSession();
|
||||
}
|
||||
|
||||
/// <summary>Create a NMS IConnection via this template's IConnectionFactory.
|
||||
/// </summary>
|
||||
/// <remarks>If CacheNmsResource is true, then the connection
|
||||
/// will be created upon the first invocation and will retrun the same
|
||||
/// connection on all subsequent calls.
|
||||
/// </remarks>
|
||||
/// <returns>A NMS IConnection
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
protected virtual IConnection CreateConnection()
|
||||
{
|
||||
if (this.CacheNmsResources)
|
||||
{
|
||||
if (jmsResources.Connection == null)
|
||||
{
|
||||
jmsResources.Connection = ConnectionFactory.CreateConnection();
|
||||
}
|
||||
return jmsResources.Connection;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return ConnectionFactory.CreateConnection();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Create a NMS ISession for the given IConnection.
|
||||
/// <p>This implementation uses NMS 1.1 API.</p>
|
||||
/// </summary>
|
||||
/// <param name="con">the NMS IConnection to create a ISession for
|
||||
/// </param>
|
||||
/// <returns> the new NMS ISession
|
||||
/// </returns>
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
protected virtual ISession CreateSession(IConnection con)
|
||||
{
|
||||
if (CacheNmsResources)
|
||||
{
|
||||
if (jmsResources.Session == null)
|
||||
{
|
||||
jmsResources.Session = jmsResources.Connection.CreateSession(SessionAcknowledgeMode);
|
||||
}
|
||||
return jmsResources.Session;
|
||||
}
|
||||
else
|
||||
{
|
||||
return con.CreateSession(SessionAcknowledgeMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Create a NMS IMessageProducer for the given ISession and IDestination,
|
||||
/// configuring it to disable message ids and/or timestamps (if necessary).
|
||||
/// <p>Delegates to <code>doCreateProducer</code> for creation of the raw
|
||||
@@ -498,18 +431,7 @@ namespace Spring.Messaging.Nms
|
||||
/// <throws>NMSException if thrown by NMS API methods </throws>
|
||||
protected virtual IMessageProducer DoCreateProducer(ISession session, IDestination destination)
|
||||
{
|
||||
if (CacheNmsResources)
|
||||
{
|
||||
if (jmsResources.MessageProducer == null)
|
||||
{
|
||||
jmsResources.MessageProducer = session.CreateProducer(destination);
|
||||
}
|
||||
return jmsResources.MessageProducer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return session.CreateProducer(destination);
|
||||
}
|
||||
return session.CreateProducer(destination);
|
||||
}
|
||||
|
||||
/// <summary> Create a NMS IMessageConsumer for the given ISession and IDestination.
|
||||
@@ -595,19 +517,12 @@ namespace Spring.Messaging.Nms
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseProducer(producer);
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseProducer(IMessageProducer producer)
|
||||
{
|
||||
if (!CacheNmsResources)
|
||||
{
|
||||
NmsUtils.CloseMessageProducer(producer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Actually send the given NMS message.</summary>
|
||||
/// <param name="producer">the NMS IMessageProducer to send with
|
||||
/// </param>
|
||||
|
||||
@@ -112,8 +112,14 @@ namespace Spring.Messaging.Nms.Support
|
||||
/// </remarks>
|
||||
public bool SessionTransacted
|
||||
{
|
||||
get { return sessionTransacted; }
|
||||
set { sessionTransacted = value; }
|
||||
get { return SessionAcknowledgeMode == AcknowledgementMode.Transactional; }
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
sessionAcknowledgeMode = AcknowledgementMode.Transactional;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -126,5 +132,19 @@ namespace Spring.Messaging.Nms.Support
|
||||
throw new ArgumentException("ConnectionFactory is required");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the connection via the ConnectionFactory.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual IConnection CreateConnection()
|
||||
{
|
||||
return ConnectionFactory.CreateConnection();
|
||||
}
|
||||
|
||||
protected virtual ISession CreateSession(IConnection con)
|
||||
{
|
||||
return con.CreateSession(SessionAcknowledgeMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,10 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Context\ILifecycle.cs" />
|
||||
<Compile Include="Messaging\Nms\Connections\ConnectionFactoryUtils.cs" />
|
||||
<Compile Include="Messaging\Nms\Connections\ISmartConnectionFactory.cs" />
|
||||
<Compile Include="Messaging\Nms\Connections\NmsResourceHolder.cs" />
|
||||
<Compile Include="Messaging\Nms\Connections\NmsTransactionManager.cs" />
|
||||
<Compile Include="Messaging\Nms\Connections\SingleConnectionFactory.cs" />
|
||||
<Compile Include="Messaging\Nms\Connections\SynchedLocalTransactionFailedException.cs" />
|
||||
<Compile Include="Messaging\Nms\IMessageCreator.cs" />
|
||||
<Compile Include="Messaging\Nms\IMessageListener.cs" />
|
||||
@@ -74,6 +77,10 @@
|
||||
<Compile Include="Messaging\Nms\Support\NmsUtils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Aop\Spring.Aop.2005.csproj">
|
||||
<Project>{3A3A4E65-45A6-4B20-B460-0BEDC302C02C}</Project>
|
||||
<Name>Spring.Aop.2005</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Spring.Core\Spring.Core.2005.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2005</Name>
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Spring.Data
|
||||
|
||||
SqlConnection conn = new SqlConnection(connString);
|
||||
conn.Open();
|
||||
conn.Open();
|
||||
//conn.BeginTransaction(IsolationLevel.Unspecified);
|
||||
SqlTransaction trans = conn.BeginTransaction();
|
||||
Console.WriteLine(trans.IsolationLevel);
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
<sectionGroup name="common">
|
||||
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
|
||||
</sectionGroup>
|
||||
<sectionGroup name="spring">
|
||||
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
|
||||
|
||||
@@ -1,58 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly: AssemblyTitle("")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project output directory which is
|
||||
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||
// located in the project directory, you would specify the AssemblyKeyFile
|
||||
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly: AssemblyDelaySign(false)]
|
||||
[assembly: AssemblyKeyFile("")]
|
||||
[assembly: AssemblyKeyName("")]
|
||||
[assembly: AssemblyTitle("Spring.Messaging.Nms Tests")]
|
||||
[assembly: AssemblyDescription("Unit tests for Spring.Messaging.Nms assembly")]
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region Imports
|
||||
|
||||
using System;
|
||||
using Apache.NMS;
|
||||
using NUnit.Framework;
|
||||
using Rhino.Mocks;
|
||||
using Spring.Messaging.Nms.IConnections;
|
||||
using Spring.Transaction;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Messaging.Nms.Connections
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains tests for
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
/// <version>$Id:$</version>
|
||||
[TestFixture]
|
||||
public class NmsTransactionManagerTests
|
||||
{
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
mocks = new MockRepository();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TransactionCommit()
|
||||
{
|
||||
IConnectionFactory connectionFactory = (IConnectionFactory) mocks.CreateMock(typeof (IConnectionFactory));
|
||||
IConnection connection = (IConnection) mocks.CreateMock(typeof (IConnection));
|
||||
ISession session = (ISession) mocks.CreateMock(typeof (ISession));
|
||||
|
||||
using (mocks.Ordered())
|
||||
{
|
||||
SetupCommitExpectations(connection, connectionFactory, session);
|
||||
}
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
NmsTransactionManager tm = new NmsTransactionManager(connectionFactory);
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
NmsTemplate nt = new NmsTemplate(connectionFactory);
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
tm.Commit(ts);
|
||||
|
||||
mocks.VerifyAll();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TransactionRollback()
|
||||
{
|
||||
IConnectionFactory connectionFactory = (IConnectionFactory) mocks.CreateMock(typeof (IConnectionFactory));
|
||||
IConnection connection = (IConnection) mocks.CreateMock(typeof (IConnection));
|
||||
ISession session = (ISession) mocks.CreateMock(typeof (ISession));
|
||||
|
||||
SetupRollbackExpectations(connection, connectionFactory, session);
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
NmsTransactionManager tm = new NmsTransactionManager(connectionFactory);
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
NmsTemplate nt = new NmsTemplate(connectionFactory);
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
tm.Rollback(ts);
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO because using anonymous delegates - refactor to support .net 1.1 later.
|
||||
*/
|
||||
#if NET_2_0
|
||||
[Test]
|
||||
public void ParticipatingTransactionWithCommit()
|
||||
{
|
||||
IConnectionFactory connectionFactory = (IConnectionFactory)mocks.CreateMock(typeof(IConnectionFactory));
|
||||
IConnection connection = (IConnection)mocks.CreateMock(typeof(IConnection));
|
||||
ISession session = (ISession)mocks.CreateMock(typeof(ISession));
|
||||
|
||||
using (mocks.Ordered())
|
||||
{
|
||||
SetupCommitExpectations(connection, connectionFactory, session);
|
||||
}
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
|
||||
NmsTransactionManager tm = new NmsTransactionManager(connectionFactory);
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
NmsTemplate nt = new NmsTemplate(connectionFactory);
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.Execute(delegate(ITransactionStatus status)
|
||||
{
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
return null;
|
||||
});
|
||||
|
||||
tm.Commit(ts);
|
||||
|
||||
mocks.VerifyAll();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParticipatingTransactionWithRollback()
|
||||
{
|
||||
IConnectionFactory connectionFactory = (IConnectionFactory) mocks.CreateMock(typeof (IConnectionFactory));
|
||||
IConnection connection = (IConnection) mocks.CreateMock(typeof (IConnection));
|
||||
ISession session = (ISession) mocks.CreateMock(typeof (ISession));
|
||||
|
||||
using (mocks.Ordered())
|
||||
{
|
||||
SetupRollbackExpectations(connection, connectionFactory, session);
|
||||
}
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
NmsTransactionManager tm = new NmsTransactionManager(connectionFactory);
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
NmsTemplate nt = new NmsTemplate(connectionFactory);
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.Execute(delegate(ITransactionStatus status)
|
||||
{
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
status.RollbackOnly = true;
|
||||
return null;
|
||||
});
|
||||
try
|
||||
{
|
||||
tm.Commit(ts);
|
||||
Assert.Fail("Should have thrown UnexpectedRollbackException");
|
||||
} catch (UnexpectedRollbackException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SuspendedTransaction()
|
||||
{
|
||||
IConnectionFactory connectionFactory = (IConnectionFactory) mocks.CreateMock(typeof (IConnectionFactory));
|
||||
IConnection connection = (IConnection) mocks.CreateMock(typeof (IConnection));
|
||||
ISession session = (ISession) mocks.CreateMock(typeof (ISession));
|
||||
ISession session2 = (ISession)mocks.CreateMock(typeof(ISession));
|
||||
|
||||
Expect.Call(connectionFactory.CreateConnection()).Return(connection).Repeat.Twice();
|
||||
Expect.Call(connection.CreateSession(AcknowledgementMode.Transactional)).Return(session).Repeat.Once();
|
||||
Expect.Call(connection.CreateSession(AcknowledgementMode.AutoAcknowledge)).Return(session2).Repeat.Once();
|
||||
|
||||
session.Commit();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
session.Close();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
|
||||
session2.Close();
|
||||
LastCall.On(session2).Repeat.Once();
|
||||
|
||||
connection.Close();
|
||||
LastCall.On(connection).Repeat.Twice();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
NmsTransactionManager tm = new NmsTransactionManager(connectionFactory);
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
NmsTemplate nt = new NmsTemplate(connectionFactory);
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.NotSupported;
|
||||
tt.Execute(delegate(ITransactionStatus status)
|
||||
{
|
||||
nt.Execute(new AssertNotSameSessionCallback(session));
|
||||
return null;
|
||||
});
|
||||
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
|
||||
tm.Commit(ts);
|
||||
|
||||
mocks.VerifyAll();
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TransactionSuspension()
|
||||
{
|
||||
IConnectionFactory connectionFactory = (IConnectionFactory)mocks.CreateMock(typeof(IConnectionFactory));
|
||||
IConnection connection = (IConnection)mocks.CreateMock(typeof(IConnection));
|
||||
ISession session = (ISession)mocks.CreateMock(typeof(ISession));
|
||||
ISession session2 = (ISession)mocks.CreateMock(typeof(ISession));
|
||||
|
||||
|
||||
Expect.Call(connectionFactory.CreateConnection()).Return(connection).Repeat.Twice();
|
||||
Expect.Call(connection.CreateSession(AcknowledgementMode.Transactional)).Return(session).Repeat.Once();
|
||||
Expect.Call(connection.CreateSession(AcknowledgementMode.Transactional)).Return(session2).Repeat.Once();
|
||||
|
||||
session.Commit();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
session2.Commit();
|
||||
LastCall.On(session2).Repeat.Once();
|
||||
|
||||
session.Close();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
session2.Close();
|
||||
LastCall.On(session2).Repeat.Once();
|
||||
|
||||
connection.Close();
|
||||
LastCall.On(connection).Repeat.Twice();
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
NmsTransactionManager tm = new NmsTransactionManager(connectionFactory);
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
NmsTemplate nt = new NmsTemplate(connectionFactory);
|
||||
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
tt.Execute(delegate(ITransactionStatus status)
|
||||
{
|
||||
nt.Execute(new AssertNotSameSessionCallback(session));
|
||||
return null;
|
||||
});
|
||||
|
||||
nt.Execute(new AssertSessionCallback(session));
|
||||
|
||||
tm.Commit(ts);
|
||||
|
||||
mocks.VerifyAll();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
private static void SetupRollbackExpectations(IConnection connection, IConnectionFactory connectionFactory, ISession session)
|
||||
{
|
||||
Expect.Call(connectionFactory.CreateConnection()).Return(connection).Repeat.Once();
|
||||
Expect.Call(connection.CreateSession(AcknowledgementMode.Transactional)).Return(session).Repeat.Once();
|
||||
session.Rollback();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
session.Close();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
connection.Close();
|
||||
LastCall.On(connection).Repeat.Once();
|
||||
}
|
||||
|
||||
private static void SetupCommitExpectations(IConnection connection, IConnectionFactory connectionFactory, ISession session)
|
||||
{
|
||||
Expect.Call(connectionFactory.CreateConnection()).Return(connection).Repeat.Once();
|
||||
Expect.Call(connection.CreateSession(AcknowledgementMode.Transactional)).Return(session).Repeat.Once();
|
||||
session.Commit();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
session.Close();
|
||||
LastCall.On(session).Repeat.Once();
|
||||
connection.Close();
|
||||
LastCall.On(connection).Repeat.Once();
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
Assert.IsTrue(TransactionSynchronizationManager.ResourceDictionary.Count == 0);
|
||||
Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal class AssertSessionCallback : ISessionCallback
|
||||
{
|
||||
private ISession session;
|
||||
public AssertSessionCallback(ISession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
#region ISessionCallback Members
|
||||
|
||||
public object DoInNms(ISession session)
|
||||
{
|
||||
Assert.IsTrue(this.session == session);
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class AssertNotSameSessionCallback : ISessionCallback
|
||||
{
|
||||
private ISession session;
|
||||
public AssertNotSameSessionCallback(ISession session)
|
||||
{
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
#region ISessionCallback Members
|
||||
|
||||
public object DoInNms(ISession session)
|
||||
{
|
||||
Assert.IsTrue(this.session != session);
|
||||
return null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\..\build\VS.NET.2005\Spring.Messaging.Nms.Tests\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;NET_2_0</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
@@ -28,24 +28,61 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Accessibility" />
|
||||
<Reference Include="antlr.runtime, Version=2.7.5.22, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\net\2.0\antlr.runtime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Apache.NMS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=65e474d141e25e07, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Apache.NMS.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Common.Logging, Version=1.2.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Common.Logging.Log4Net, Version=1.2.0.2, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.Log4Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.2.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\net\2.0\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Rhino.Mocks, Version=2.9.6.40380, Culture=neutral, PublicKeyToken=0b3305902db7183f, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Rhino.Mocks.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.2005.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2005</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Data\Spring.Data.2005.csproj">
|
||||
<Project>{AE00E5AB-C39A-436F-86D2-33BFE33E2E40}</Project>
|
||||
<Name>Spring.Data.2005</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Messaging.Nms\Spring.Messaging.Nms.2005.csproj">
|
||||
<Project>{AEB1578C-9018-4D49-B440-789F38DD2F29}</Project>
|
||||
<Name>Spring.Messaging.Nms.2005</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Messaging\Nms\Connections\NmsTransactionManagerTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Spring.Messaging.Nms.Tests.dll.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<include name="**/*.cs" />
|
||||
<include name="../CommonAssemblyInfo.cs" />
|
||||
</sources>
|
||||
<resources prefix="Spring" dynamicprefix="true" failonempty="true">
|
||||
<resources prefix="Spring" dynamicprefix="true" failonempty="false">
|
||||
<include name="**/*.xml" />
|
||||
</resources>
|
||||
<references basedir="${current.bin.dir}">
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--
|
||||
Copyright 2002-2005 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.
|
||||
-->
|
||||
<configuration>
|
||||
|
||||
<configSections>
|
||||
|
||||
</configSections>
|
||||
|
||||
|
||||
|
||||
</configuration>
|
||||
@@ -192,7 +192,7 @@
|
||||
<PreBuildEvent>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>echo "Copying .xml files for tests"
|
||||
xcopy "$(ProjectDir)Data" ..\..\..\..\build\VS.Net.2005\Spring.Web.Tests\$(ConfigurationName)\ /y /s /q /d
|
||||
%25SystemRoot%25\system32\xcopy "$(ProjectDir)Data" ..\..\..\..\build\VS.Net.2005\Spring.Web.Tests\$(ConfigurationName)\ /y /s /q /d
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user