SPRNET-1337
-Applied recommended fix from forum post -Added new unit test to validate that handlers are acting in parallel once new patch introduced
This commit is contained in:
@@ -81,11 +81,11 @@ namespace Spring.Messaging.Listener
|
||||
q.ConvertAndSend("Goodbye World 1");
|
||||
|
||||
Assert.AreEqual(0, listener.MessageCount, "PRECONDITION FAILURE: Unable to send the message!");
|
||||
|
||||
distributedTxMessageListenerContainer.Start();
|
||||
|
||||
Thread.Sleep(waitInMillis);
|
||||
|
||||
|
||||
distributedTxMessageListenerContainer.Stop();
|
||||
distributedTxMessageListenerContainer.Shutdown();
|
||||
Thread.Sleep(2500);
|
||||
@@ -105,6 +105,8 @@ namespace Spring.Messaging.Listener
|
||||
//must match the retry count in the object registration for test to pass!
|
||||
const int EXCEPTION_QUEUE_RETRY_COUNT = 2;
|
||||
|
||||
int expectedMessageCount = MESSAGE_COUNT + (MESSAGE_COUNT * EXCEPTION_QUEUE_RETRY_COUNT);
|
||||
|
||||
MessageQueueTemplate q = applicationContext["queueTemplate"] as MessageQueueTemplate;
|
||||
Assert.IsNotNull(q);
|
||||
|
||||
@@ -115,13 +117,22 @@ namespace Spring.Messaging.Listener
|
||||
|
||||
Assert.AreEqual(0, listener.MessageCount);
|
||||
|
||||
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
||||
timer.Start();
|
||||
|
||||
distributedTxMessageListenerContainer.Start();
|
||||
|
||||
//this test needs to wait somewhat longer than the others in order to consistently pass so
|
||||
//artificially inflate the waiting period before attempting subsequent asserts:
|
||||
Thread.Sleep((int)(waitInMillis * 1.5));
|
||||
while (listener.MessageCount < expectedMessageCount)
|
||||
{
|
||||
if (timer.ElapsedMilliseconds > 60000)
|
||||
Assert.Fail("Did not receive expected number of messages within the permitted time limit.");
|
||||
}
|
||||
|
||||
Assert.AreEqual(MESSAGE_COUNT + (MESSAGE_COUNT * EXCEPTION_QUEUE_RETRY_COUNT), listener.MessageCount);
|
||||
timer.Stop();
|
||||
|
||||
System.Diagnostics.Debug.WriteLine("elapsed time = " + timer.ElapsedMilliseconds);
|
||||
|
||||
Assert.AreEqual(expectedMessageCount, listener.MessageCount);
|
||||
|
||||
distributedTxMessageListenerContainer.Stop();
|
||||
distributedTxMessageListenerContainer.Shutdown();
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#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.Threading;
|
||||
using NUnit.Framework;
|
||||
using Spring.Messaging.Core;
|
||||
using Spring.Testing.NUnit;
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace Spring.Messaging.Listener
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains tests for
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack</author>
|
||||
/// <version>$Id:$</version>
|
||||
[TestFixture]
|
||||
public class MultiThreadedNonTransactionalMessageListenerContainerTests : AbstractDependencyInjectionSpringContextTests
|
||||
{
|
||||
|
||||
private NonTransactionalMessageListenerContainer container;
|
||||
private WaitingHandler listener;
|
||||
private SimpleExceptionHandler exceptionHandler;
|
||||
|
||||
[SetUp]
|
||||
public override void SetUp()
|
||||
{
|
||||
MessageQueueUtils.RecreateMessageQueue(@".\Private$\testqueue", false);
|
||||
MessageQueueUtils.RecreateMessageQueue(@".\Private$\testresponsequeue", false);
|
||||
base.SetUp();
|
||||
}
|
||||
|
||||
public SimpleExceptionHandler ExceptionHandler
|
||||
{
|
||||
set { exceptionHandler = value; }
|
||||
}
|
||||
|
||||
public NonTransactionalMessageListenerContainer Container
|
||||
{
|
||||
get { return container; }
|
||||
set { container = value; }
|
||||
}
|
||||
|
||||
public WaitingHandler Listener
|
||||
{
|
||||
get { return listener; }
|
||||
set { listener = value; }
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Test()
|
||||
{
|
||||
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
||||
|
||||
MessageQueueTemplate q = applicationContext["testQueueTemplate"] as MessageQueueTemplate;
|
||||
Assert.IsNotNull(q);
|
||||
|
||||
q.ConvertAndSend("Hello World 1");
|
||||
q.ConvertAndSend("Hello World 2");
|
||||
q.ConvertAndSend("Hello World 3");
|
||||
q.ConvertAndSend("Hello World 4");
|
||||
q.ConvertAndSend("Hello World 5");
|
||||
|
||||
//Reset the state so that running all tests together will succeed.
|
||||
exceptionHandler.MessageCount = 0;
|
||||
|
||||
Assert.AreEqual(0, listener.MessageCount);
|
||||
|
||||
timer.Start();
|
||||
|
||||
container.Start();
|
||||
|
||||
while (listener.MessageCount < 5)
|
||||
{
|
||||
//provide an exit if the test is completely over-length
|
||||
if (timer.ElapsedMilliseconds > 120000)
|
||||
Assert.Fail("Did not receive expected number of messages with the expected time-limit!");
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
|
||||
container.Stop();
|
||||
container.Shutdown();
|
||||
|
||||
Debug.WriteLine(String.Format("Elapsed Milliseconds: {0}", timer.ElapsedMilliseconds));
|
||||
|
||||
Assert.Less(timer.ElapsedMilliseconds, 50000);
|
||||
Assert.AreEqual(5, listener.MessageCount);
|
||||
Assert.AreEqual(0, exceptionHandler.MessageCount);
|
||||
}
|
||||
|
||||
protected override string[] ConfigLocations
|
||||
{
|
||||
get { return new string[] { "assembly://Spring.Messaging.Tests/Spring.Messaging.Listener/MultiThreadedNonTransactionalMessageListenerContainerTests.xml" }; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net"
|
||||
xmlns:db="http://www.springframework.net/database">
|
||||
|
||||
|
||||
<db:provider id="DbProvider"
|
||||
provider="System.Data.SqlClient"
|
||||
connectionString="Data Source=MARKT60\SQL2005;Initial Catalog=Spring;Persist Security Info=True;User ID=springqa;Password=springqa"/>
|
||||
|
||||
<object id="adoTransactionManager"
|
||||
type="Spring.Data.Core.AdoPlatformTransactionManager, Spring.Data">
|
||||
|
||||
<property name="DbProvider" ref="DbProvider"/>
|
||||
</object>
|
||||
|
||||
<object id='msmqTestQueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testqueue'/>
|
||||
<property name='MessageReadPropertyFilterSetAll' value='true'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyTestQueueLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id='msmqTestResponseQueue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='.\Private$\testresponsequeue'/>
|
||||
<property name='MessageReadPropertyFilterSetAll' value='true'/>
|
||||
<property name='ProductTemplate'>
|
||||
<object>
|
||||
<property name='Label' value='MyTestResponseQueueLabel'/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
||||
<object id='testremotequeue' type='Spring.Messaging.Support.MessageQueueFactoryObject, Spring.Messaging'>
|
||||
<property name='Path' value='FormatName:Direct=OS:RAVEN\Private$\testqueue'/>
|
||||
<property name='RemoteQueue' value="true"/>
|
||||
</object>
|
||||
|
||||
<object id="testRemoteTemplate" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="testremotequeue"/>
|
||||
<property name="MessageConverterObjectName" value="binaryMessageConverter"/>
|
||||
</object>
|
||||
|
||||
<object id="testQueueTemplate" type="Spring.Messaging.Core.MessageQueueTemplate, Spring.Messaging">
|
||||
<property name="DefaultMessageQueueObjectName" value="msmqTestQueue"/>
|
||||
<property name="MessageConverterObjectName" value="binaryMessageConverter"/>
|
||||
</object>
|
||||
|
||||
|
||||
<!-- Message Converters -->
|
||||
|
||||
<object id="messageConverter" type="Spring.Messaging.Support.Converters.XmlMessageConverter, Spring.Messaging"
|
||||
singleton="false">
|
||||
<property name="TargetTypes" value="System.String"/>
|
||||
</object>
|
||||
|
||||
<object id="binaryMessageConverter" type="Spring.Messaging.Support.Converters.BinaryMessageConverter, Spring.Messaging" singleton="false">
|
||||
|
||||
</object>
|
||||
|
||||
<object id="nonTransactionalMessageListenerContainer" type="Spring.Messaging.Listener.NonTransactionalMessageListenerContainer, Spring.Messaging">
|
||||
<property name="MessageQueueObjectName" value="testremotequeue"/>
|
||||
<property name="MaxConcurrentListeners" value="5"/>
|
||||
<property name="ListenerTimeLimit" value="20s"/>
|
||||
<property name="MessageListener" ref="messageListenerAdapter"/>
|
||||
<property name="ExceptionHandler" ref="exceptionHandler"/>
|
||||
<property name="AutoStartup" value="false"/>
|
||||
</object>
|
||||
|
||||
|
||||
<!-- Adapter -->
|
||||
<object id="messageListenerAdapter" type="Spring.Messaging.Listener.MessageListenerAdapter, Spring.Messaging">
|
||||
<property name="DefaultResponseQueueName" value="msmqTestResponseQueue"/>
|
||||
<property name="MessageConverterObjectName" value="binaryMessageConverter"/>
|
||||
<property name="HandlerObject" ref="waitingHandler"/>
|
||||
</object>
|
||||
|
||||
|
||||
<!-- Message and Exception Handlers -->
|
||||
<object id="waitingHandler" type="Spring.Messaging.Listener.WaitingHandler, Spring.Messaging.Tests">
|
||||
|
||||
</object>
|
||||
|
||||
<object id="exceptionHandler" type="Spring.Messaging.Listener.SimpleExceptionHandler, Spring.Messaging.Tests">
|
||||
|
||||
</object>
|
||||
|
||||
|
||||
</objects>
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
|
||||
using System;
|
||||
using Common.Logging;
|
||||
using System.Threading;
|
||||
|
||||
namespace Spring.Messaging.Listener
|
||||
{
|
||||
public class WaitingHandler
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(WaitingHandler));
|
||||
|
||||
#endregion
|
||||
|
||||
private int messageCount;
|
||||
|
||||
private string stateVariable;
|
||||
|
||||
public WaitingHandler()
|
||||
{
|
||||
this.stateVariable = "hello";
|
||||
}
|
||||
public WaitingHandler(string stateVariable)
|
||||
{
|
||||
this.stateVariable = stateVariable;
|
||||
}
|
||||
|
||||
|
||||
public int MessageCount
|
||||
{
|
||||
get { return messageCount; }
|
||||
set { messageCount = value; }
|
||||
}
|
||||
|
||||
public string HandleMessage(string msgTxt)
|
||||
{
|
||||
LOG.Debug(String.Format("Received text = [{0}]", msgTxt));
|
||||
LOG.Debug("constructor set state string = " + stateVariable);
|
||||
|
||||
Thread.Sleep(10000);
|
||||
|
||||
messageCount++;
|
||||
LOG.Debug("Message listener count = " + messageCount);
|
||||
return msgTxt + " - processed!";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Messaging\Listener\NonTransactionalMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\MultiThreadedNonTransactionalMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\TransactionalMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\queue-context.xml" />
|
||||
<EmbeddedResource Include="Messaging\Core\MessageQueueTemplateTests.xml" />
|
||||
@@ -87,11 +88,13 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Messaging\Core\MessageQueueMetadataCacheTests.cs" />
|
||||
<Compile Include="Messaging\Core\MessageQueueUtils.cs" />
|
||||
<Compile Include="Messaging\Core\WaitingHander.cs" />
|
||||
<Compile Include="Messaging\Core\ThreadingTests.cs" />
|
||||
<Compile Include="Messaging\Listener\Adapter\MessageListenerAdapterTests.cs" />
|
||||
<Compile Include="Messaging\Listener\DistributedTxMessageListenerContainerTests.cs" />
|
||||
<Compile Include="Messaging\Listener\LoggingExceptionHandler.cs" />
|
||||
<Compile Include="Messaging\Listener\NonTransactionalMessageListenerContainerTests.cs">
|
||||
<Compile Include="Messaging\Listener\NonTransactionalMessageListenerContainerTests.cs" />
|
||||
<Compile Include="Messaging\Listener\MultiThreadedNonTransactionalMessageListenerContainerTests.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Messaging\Listener\SimpleExceptionHandler.cs" />
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Messaging\Listener\NonTransactionalMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\MultiThreadedNonTransactionalMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\TransactionalMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\queue-context.xml" />
|
||||
<EmbeddedResource Include="Messaging\Core\MessageQueueTemplateTests.xml" />
|
||||
@@ -88,13 +89,15 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="MessagingCompilerOptionsTests.cs" />
|
||||
<Compile Include="MessagingExceptionTests.cs" />
|
||||
<Compile Include="Messaging\Listener\WaitingHandler.cs" />
|
||||
<Compile Include="Messaging\Core\MessageQueueMetadataCacheTests.cs" />
|
||||
<Compile Include="Messaging\Core\MessageQueueUtils.cs" />
|
||||
<Compile Include="Messaging\Core\ThreadingTests.cs" />
|
||||
<Compile Include="Messaging\Listener\Adapter\MessageListenerAdapterTests.cs" />
|
||||
<Compile Include="Messaging\Listener\DistributedTxMessageListenerContainerTests.cs" />
|
||||
<Compile Include="Messaging\Listener\LoggingExceptionHandler.cs" />
|
||||
<Compile Include="Messaging\Listener\NonTransactionalMessageListenerContainerTests.cs">
|
||||
<Compile Include="Messaging\Listener\NonTransactionalMessageListenerContainerTests.cs" />
|
||||
<Compile Include="Messaging\Listener\MultiThreadedNonTransactionalMessageListenerContainerTests.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Messaging\Listener\SimpleExceptionHandler.cs" />
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Messaging\Core\MessageQueueTemplateTests.cs" />
|
||||
<Compile Include="Messaging\Core\MessageQueueUtils.cs" />
|
||||
<Compile Include="Messaging\Listener\WaitingHandler.cs" />
|
||||
<Compile Include="Messaging\Listener\MultiThreadedNonTransactionalMessageListenerContainerTests.cs" />
|
||||
<Compile Include="Messaging\Support\MessageQueueFactoryObjectTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
@@ -88,6 +90,9 @@
|
||||
<EmbeddedResource Include="Messaging\Core\MessageQueueTemplateTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\DistributedTxMessageListenerContainerTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Core\MessageQueueMetadataCacheTests.xml" />
|
||||
<EmbeddedResource Include="Messaging\Listener\MultiThreadedNonTransactionalMessageListenerContainerTests.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Content Include="Spring.Messaging.Tests.dll.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
Reference in New Issue
Block a user