I'm struggling with an error message I'm getting from the NServiceBus.Host during startup and not sure where I'm going wrong. I initially encountered the problem within a large project but I seem to be able to reproduce this from scratch.
In VS2012, start with a new C# Class Library project, set for .NET 4.6.2. Then add NuGet packages - NServiceBus (6.0.0), NServiceBus.Host (7.0.1) and NServiceBus.NHibernate (7.2.0).
Then edit the EndpointConfiguration
class to be as follows:
using NServiceBus.Features;
using NServiceBus.Persistence;
namespace NSB6_Pure
{
using NServiceBus;
public class EndpointConfig : IConfigureThisEndpoint
{
public void Customize(EndpointConfiguration endpointConfiguration)
{
//TODO: NServiceBus provides multiple durable storage options, including SQL Server, RavenDB, and Azure Storage Persistence.
// Refer to the documentation for more details on specific options.
endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Timeouts>();
endpointConfiguration.DisableFeature<MessageDrivenSubscriptions>();
endpointConfiguration.DisableFeature<Sagas>();
// NServiceBus will move messages that fail repeatedly to a separate "error" queue. We recommend
// that you start with a shared error queue for all your endpoints for easy integration with ServiceControl.
endpointConfiguration.SendFailedMessagesTo("error");
// NServiceBus will store a copy of each successfully process message in a separate "audit" queue. We recommend
// that you start with a shared audit queue for all your endpoints for easy integration with ServiceControl.
endpointConfiguration.AuditProcessedMessagesTo("audit");
}
}
}
Then compile (in this case a debug build) and, from a command prompt, try to run NServiceBus.Host.exe
in the bin\Debug
directory. In my case, I get this output, most of it in Red:
2017-04-28 12:46:11.876 INFO DefaultFactory Logging to 'C:\blah\bin\Debug\' with level Info
2017-04-28 12:46:13.446 FATAL NServiceBus.LicenseManager Your license has expire
d! You can renew it at https://particular.net/licensing.
2017-04-28 12:46:13.561 ERROR NServiceBus.GenericHost Exception when starting en
dpoint.
System.InvalidOperationException: In order to use NServiceBus with NHibernate yo
u need to provide at least one connection string. You can do it via (in order of
precedence):
* specifying 'NServiceBus/Persistence/NHibernate/Saga' connection string for th
e Saga persister
* specifying 'NServiceBus/Persistence' connection string that applies to all pe
rsisters
* specifying 'NServiceBus/Persistence/connection.connection_string' or 'NServic
eBus/Persistence/connection.connection_string_name' value in AppSettings or your
NHibernate configuration file.
For most scenarios the 'NServiceBus/Persistence' connection string is the best o
ption.
at NServiceBus.Persistence.NHibernate.NHibernateConfigurationBuilder.Validate
ConfigurationViaConfigFile(Configuration configuration, String configPrefix) in
C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\Internal\NHiberna
teConfigurationBuilder.cs:line 130
at NServiceBus.Features.NHibernateStorageSession.Setup(FeatureConfigurationCo
ntext context) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate
\SynchronizedStorage\NHibernateStorageSession.cs:line 45
at NServiceBus.Features.FeatureActivator.ActivateFeature(FeatureInfo featureI
nfo, List`1 featuresToActivate, IConfigureComponents container, PipelineSettings
pipelineSettings) in C:\Build\src\NServiceBus.Core\Features\FeatureActivator.cs
:line 194
at NServiceBus.Features.FeatureActivator.SetupFeatures(IConfigureComponents c
ontainer, PipelineSettings pipelineSettings) in C:\Build\src\NServiceBus.Core\Fe
atures\FeatureActivator.cs:line 57
at NServiceBus.InitializableEndpoint.<Initialize>d__1.MoveNext() in C:\Build\
src\NServiceBus.Core\InitializableEndpoint.cs:line 50
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at NServiceBus.GenericHost.<Start>d__1.MoveNext() in C:\BuildAgent\work\fc89e
968acb99302\src\NServiceBus.Hosting.Windows\GenericHost.cs:line 48
2017-04-28 12:46:13.582 ERROR NServiceBus.Hosting.Windows.WindowsHost Start fail
ure
System.InvalidOperationException: In order to use NServiceBus with NHibernate yo
u need to provide at least one connection string. You can do it via (in order of
precedence):
* specifying 'NServiceBus/Persistence/NHibernate/Saga' connection string for th
e Saga persister
* specifying 'NServiceBus/Persistence' connection string that applies to all pe
rsisters
* specifying 'NServiceBus/Persistence/connection.connection_string' or 'NServic
eBus/Persistence/connection.connection_string_name' value in AppSettings or your
NHibernate configuration file.
For most scenarios the 'NServiceBus/Persistence' connection string is the best o
ption.
at NServiceBus.Persistence.NHibernate.NHibernateConfigurationBuilder.Validate
ConfigurationViaConfigFile(Configuration configuration, String configPrefix) in
C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate\Internal\NHiberna
teConfigurationBuilder.cs:line 130
at NServiceBus.Features.NHibernateStorageSession.Setup(FeatureConfigurationCo
ntext context) in C:\BuildAgent\work\5135de308b2f3016\src\NServiceBus.NHibernate
\SynchronizedStorage\NHibernateStorageSession.cs:line 45
at NServiceBus.Features.FeatureActivator.ActivateFeature(FeatureInfo featureI
nfo, List`1 featuresToActivate, IConfigureComponents container, PipelineSettings
pipelineSettings) in C:\Build\src\NServiceBus.Core\Features\FeatureActivator.cs
:line 194
at NServiceBus.Features.FeatureActivator.SetupFeatures(IConfigureComponents c
ontainer, PipelineSettings pipelineSettings) in C:\Build\src\NServiceBus.Core\Fe
atures\FeatureActivator.cs:line 57
at NServiceBus.InitializableEndpoint.<Initialize>d__1.MoveNext() in C:\Build\
src\NServiceBus.Core\InitializableEndpoint.cs:line 50
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at NServiceBus.GenericHost.<Start>d__1.MoveNext() in C:\BuildAgent\work\fc89e
968acb99302\src\NServiceBus.Hosting.Windows\GenericHost.cs:line 54
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNot
ification(Task task)
at NServiceBus.Hosting.Windows.WindowsHost.Start() in C:\BuildAgent\work\fc89
e968acb99302\src\NServiceBus.Hosting.Windows\WindowsHost.cs:line 33
And the bit I'm focussing on is here:
In order to use NServiceBus with NHibernate you need to provide at least one connection string. You can do it via (in order of precedence):
- specifying 'NServiceBus/Persistence/NHibernate/Saga' connection string for the Saga persister
I've checked the NServiceBus code - this isn't a generic message. If the issue was the lack of config for Timeouts1, I'm sure it would be talking about it rather than Saga, since that part of the error message is parameterized.
But I don't want to use Sagas in this particular project. I'd have thought DisableFeature<Sagas>
would be sufficient to indicate to NServiceBus that I don't want to use sagas here, but apparently not.
So why is NServiceBus trying to configure Saga storage and, more importantly, how do I stop it from doing so?
1Of course, I am expecting such an error to occur since I haven't done anything such as even adding an app.config
to the class library yet. So even once the Saga issue is resolved, I'm expecting this code to still produce errors. Just hopefully ones I can work out how to fix for myself.
(The rationale behind my wanting to avoid configuring any storage is that the real work to do is to upgrade some existing endpoints that have dedicated databases for each feature (Timeouts/Subscriptions/Sagas) and although I've been recommending for a while that we ought to merge these databases, and could thus just configure a NServiceBus/Persistence
database for each endpoint, that's not been approved. But I'm loath to add another database for some of these endpoints when they only use timeouts at present)
I must admit I have not much knowledge about NServiceBus, I just feel obliged to try to help people with high reputation when they ask questions :) So I don't have an explanation why it works like this, only where it fails. In stack trace you can see NHibernateStorageSession.Setup
, and NHibernateStorageSession
is one of the features. So it fails when trying to activate that feature. Setup
starts like this:
protected override void Setup(FeatureConfigurationContext context)
{
NHibernateConfiguration config = new NHibernateConfigurationBuilder(context.Settings, "Saga", new string[1]
{
"StorageConfiguration"
}).Build();
// the rest
}
Where second parameter is connection string suffix. In this case it is hardcoded to "Saga", and as you see - there is no check that Sagas
feature is enabled or not. NHibernateConfigurationBuilder
then tries to find a connection string for saga (or any more general connection string) and fails to do so with the exception message you observe.
So easy solution is to disable that feature via
endpointConfiguration.DisableFeature<NHibernateStorageSession>();
However you should take care of course and ensure functionality you need is not dependent on that feature. It's not entirely clear for me what this feature is for, and I didn't found any documentation for it (though of course its name tells us something about its purpose).