Single NServiceBus message handled by Saga two times - nservicebus

I have a NServiceBus version 3.3.8 Saga that I am working on migrating from NServiceBus 2.6. After I upgraded it, I have found that a single message in the queue is getting processed twice by the saga. What is most strange about it is that NServiceBus is treating this as two separate Transport Messages because my IMessageModule implementation is getting called twice as well.
The message it is receiving is a message bound to NServiceBus 2.6. Has anyone seen this before? I at first thought it was a dependency injection issue, as we are switching from Unity to Autofac, but that doesn't seem to explain the issue with the MessageModule getting called twice.
I appreciate any help you can provide.
UPDATE
It turns out that the issue was a dependency injection issue that I had inadvertently created. The saga has some additional dependencies that require IBus and the IBus is a property and set via property injection. Using an Autofac module, I tried to simplify the configuration by overriding the AttachToComponentRegistration and injecting properties on all registered items like this:
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
registration.Activating += (s, e) => e.Context.InjectProperties(e.Instance);
}
This, however, caused the issue above. To fix it, I removed this override and manually set up property injection via a call to:
builder.RegisterType<Implementation>().As<Interface>().PropertiesAutowired();
This resolved my duplicate processing issue. I am still not sure why it caused the issue, but removing that override did prevent the duplicate message handling.

It turns out that the issue was a dependency injection issue that I had inadvertently created. The saga has some additional dependencies that require IBus and the IBus is a property and set via property injection. Using an Autofac module, I tried to simplify the configuration by overriding the AttachToComponentRegistration and injecting properties on all registered items like this:
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
registration.Activating += (s, e) => e.Context.InjectProperties(e.Instance);
}
This, however, caused the issue above. To fix it, I removed this override and manually set up property injection via a call to:
builder.RegisterType<Implementation>().As<Interface>().PropertiesAutowired();
This resolved my duplicate processing issue. I am still not sure why it caused the issue, but removing that override did prevent the duplicate message handling.

Related

NServiceBus Removing IBus - Utilising IPipelineContext and IMessageSession

I am in the process of migrating NServiceBus up to v6 and am at a roadblock in the process of removing reference to IBus.
We build upon a common library for many of our applications (Website, Micro Services etc) and this library has the concept of IEventPublisher which is essentially a Send and Publish interface. This library has no knowledge of NSB.
We can then supply the implementation of this IEventPublisher using DI from the application, this allows the library's message passing to be replaced with another technology very easily.
So what we end up with is an implementation similar to
public class NsbEventPublisher : IEventPublisher
{
IEndpointInstance _instance;
public NsbEventPublisher(IEndpointInstance endpoint)
{
instance = endpoint;
}
public void Send(object message)
{
instance.Send(message, sendOptions);
}
public void Publish(object message)
{
instance.Publish(message, sendOptions);
}
}
This is a simplification of what actually happens but illustrates my problem.
Now when the DI container is asked for an IEventPublisher it knows to return a NsbEventPublisher and it knows to resolve the IEndpointInstance as we bind this in the bootstrapper for the website to the container as a singleton.
All is fine and my site runs perfect.
I am now migrating the micro-services (running in NSB.Host) and the DI container is refusing to resolve IEndpointInstance when resolving the dependencies within a message handler. Reading the docs this is intentional and I should be using IMessageHandlerContext when in a message handler.
https://docs.particular.net/nservicebus/upgrades/5to6/moving-away-from-ibus
The docs even elude to the issue I have in the bottom example around the class MyContextAccessingDependency. The suggestion is to pass the message context through the method which puts a hard dependency on the code running in the context of a message handler.
What I would like to do is have access to a sender/publisher and the DI container can give me the correct implementation. The code does not need any concept of the caller and if it was called from a message handler or from a self hosted application that just wants to publish.
I see that there is two interfaces for communicating with the "Bus" IPipelineContext and IMessageSession which IMessageHandlerContext and IEndpointInstance interfaces extend respectively.
What I am wondering is there some unification of the two interfaces that gets bound by NSB into the container so I can accept an interface that sends/publishes messages. In a handler it is an IMessageHandlerContext and on my self hosted application the IEndPointInstance.
For now I am looking to change my implementation of IEventPublisher depending on application hosting. I was just hoping there might be some discussion about how this approach is modeled without a reliable interface to send/publish irrespective of what initiated the execution of the code path.
A few things to note before I get to the code:
The abstraction over abstraction promise, never works. I have never seen the argument of "I'm going to abstract ESB/Messaging/Database/ORM so that I can swap it in future" work. ever.
When you abstract message sending functionality like that, you'll lose some of the features the library provides. In this case, you can't perform 'Conversations' or use 'Sagas' which would hinder your overall experience, e.g. when using monitoring tools and watching diagrams in ServiceInsight, you won't see the whole picture but only nugets of messages passing through the system.
Now in order to make that work, you need to register IEndpointInstance in your container when your endpoint starts up. Then that interface can be used in your dependency injection e.g. in NsbEventPublisher to send the messages.
Something like this (depending which IoC container you're using, here I assume Autofac):
static async Task AsyncMain()
{
IEndpointInstance endpoint = null;
var builder = new ContainerBuilder();
builder.Register(x => endpoint)
.As<IEndpointInstance>()
.SingleInstance();
//Endpoint configuration goes here...
endpoint = await Endpoint.Start(busConfiguration)
.ConfigureAwait(false);
}
The issues with using IEndpointInstance / IMessageSession are mentioned here.

Transient Lifestyle requires HttpContext?

I am registering my component like this:
public static void Register(IWindsorContainer container)
{
container.Register(Classes.FromAssembly(Assembly.GetAssembly(typeof(GenericBaseRepository)))
.InSameNamespaceAs<GenericBaseRepository>()
.WithService.DefaultInterfaces()
.LifestyleTransient());
}
I am then resolving it in a piece of code that has no HttpContext:
var baseRepository = ContainerManager.Container.Resolve<IBaseRepository>();
(IBaseRepository being an interface implemented by GenericBaseRepository). This fails with the following message:
"HttpContext.Current is null. PerWebRequestLifestyle can only be used in ASP.Net"
Which confuses me, because the lifestyle I choose is Transient, not PerWebRequest.
Of course, HttpContext doesn't exist during a scheduled task - but I don't really need it, I just want an instance of my Repository which will not interact with any web request.
So, why does Castle Windsor insist in requiring an HttpContext when resolving my component?
Have a look at the full exception message. Your root component may be transient but the exception indicates one of its dependencies uses per web request lifestyle.
Have a look at Windsor's diagnostics debugger view, that may help you pinpoint it.

In ServiceMatrix, is it possible to 'ConvertToSaga' an endpoint which publishes/subscribes event messages rather than command messages?

I've got a solution with 4 NSB host endpoints which were created using ServiceMatrix and I want to use them within a saga.
I know how to Convert To Saga from a command and that works fine in a test project. What I don't understand is how I can do the same thing with published events, as the menu option is not available. Is it possible to do this using ServiceMatrix ?
I have tried to implement the changes by hand by following this tutorial and observing the changes that were made to my test project when I Converted To Saga.
It builds ok but throws an error within the framework when running:
System.InvalidOperationException was unhandled
Message: An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Additional information: No IBus instance available, please configure one and also verify that you're not defining your own Bus property in your saga since that hides the one in the base class
I'm using VS2013 and ServiceBus 5.
UPDATE:
I commented out the inherited IHandleMessages<> interface and public IBus Bus property from the generated code and it runs without this error. I'm not happy doing this, as the next design change using the tool will overwrite these fixes.
In your command handler you usually have a property of type IBus that is injected to the handler class either by property injection or constructor injection.
When you move from a command handler to a Saga, you need to remove your IBus property from the handler. Saga base class has a Bus property that you should use instead. This property is populated for you automatically, you should not care about this. This is exactly what this exception is telling you.

Ninject 3.0.0 and Nservicebus 3.0.3 -> Help on Configuration?

Does anyone have any thoughts as to how to get the two to come together so I can get injection of the IBus on the class file?
I tried downloading the Official Nservicebus.Ninject package but it appears to be constrained to the 2.x line of Ninject via Nuget. I went ahead and downloaded the source to the object builder for Ninject. There's a few issues I'm getting through several trial and error scenarios.
The first was that the IBus is not getting set via property injection. This could be my misunderstanding of how the Objectbuilder is being utilized, but I was under the impression that by setting the public IBus Bus {get; set;} on a class within the assembly that it would be set for me.
I then went down the route of trying something along the lines of:
Configure.Instance.Builder.Build<IBus>()
That yielded the following:
Error activating IBus
More than one matching bindings are available.
Activation path:
1) Request for IBus
Suggestions:
1) Ensure that you have defined a binding for IBus only once.
If I do an explicit request for the UnicastBus instead of IBus I do get one instance, but it will bomb out on the base.Activite with the following:
More than one matching bindings are available.
Activation path:
2) Injection of dependency IBus into property Bus of type TimeoutMessageConverter
1) Request for TimeoutMessageConverter
Suggestions:
1) Ensure that you have defined a binding for IBus only once.
I do not claim to be a ninject master (background is spring.net) as this project was handed to me to see if I could leverage it's existing infrastructure that uses Ninject and get a reference to the Bus to invoke a publish from a dispatcher in the project. Been spinning my wheels on this for the better part of day.
Here's the NServiceBus Module being loaded by Ninject (set up taken from another SO post):
public class NServiceBusModule : NinjectModule
{
public override void Load()
{
this.Bind<IBus>().ToConstant(this.CreateBus()).InSingletonScope();
}
private IBus CreateBus()
{
return Configure.With()
.DefineEndpointName("publishMe")
.NinjectBuilder(this.Kernel)
.XmlSerializer()
.MsmqTransport()
.IsTransactional(true)
.InMemorySubscriptionStorage()
.UnicastBus()
.CreateBus().Start(() =>
Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
}
}
I'm not leveraging any IWantCustomInitialization in the EndpointConfig as I thought this was all I would need to get a reference to the Bus.
I have another idea I can approach where I continue to separate the project out a bit that I believe would work just fine (have the web app --setting up bus in the global.ascx -- directly publish to an endpoint and go from there), but trying to stay within the initial requirements of the project outline.
I can supply more information if need be.
NinjectBuilder adds the IBus binding. You have two options:
Use Rebind in your code
Just call CreateBus() without adding the binding

NServiceBus.ObjectBuilder.Ninject critical bug

I'm experiencing this error mentioned on the nsb group when running in the NServiceBus.Production profile.
Just wondering if it's a known issue (Remo ? :-) ) because it's currently going to prevent me using ninject with nsb.
NServiceBus.Ninject-CI.3.0.2044 nuget.
Many thanks!
2012-02-28 15:24:18,204 [Worker.8] WARN NServiceBus.Unicast.Transport.Transacti
onal.TransactionalTransport [(null)] <(null)> - Failed raising 'transport messag
e received' event for message with ID=02e57b0c-f345-46ae-a095-f52a4cfc0cfb\2071
System.NullReferenceException: Object reference not set to an instance of an obj
ect.
at Ninject.Injection.DynamicMethodInjectorFactory.EmitMethodCall(ILGenerator
il, MethodInfo method) in c:\Projects\Ninject\Maintenance2.2\ninject\src\Ninject
\Injection\DynamicMethodInjectorFactory.cs:line 130
I didn't write the NSB ObjectBuilder for Ninject. From the exception I can tell that Ninject fails to inject a property because there is no public setter. With the an unchanged Ninject this cannot happen because these properties are filtered before unless Ninject is explicitly told that it shall not filter none public members.
I had a short look at the NinjectObjectBuilder. It adds new heuristic and it seems that it does not filter public properties with private setters. This implementation requires some change.
But I think this won't fix your problem since you want to have that property injected anyway. The proper way to do so is to change the setter to public. Alternatively, you can change the settings to allow privat member injection. Settings.InjectNonPublic = true; But I don't recommend to do that.