ncqrs with NServiceBus 3.3

201 Views Asked by At

After upgrading NServiceBus from 2.6 to 3.3 CommandService started to throw System.NullReferenceException: Object reference not set to an instance of an object. on IStartableBus.Start(). Small research has shown that UnicastBus returned by Configure.CreateBus() has null as Transport property value.

There is NSB Config in Global.asax.cs:

IBus bus = Configure.With()
    .DefineEndpointName(endpointName)
    .UnityBuilder(unityContainer)
    .AddLogger()
    .BinarySerializer()
    .MsmqTransport()
    .PurgeOnStartup(false)
    .IsTransactional(true)
    .IsolationLevel(TransactionIsolationLevel)
    .TransactionTimeout(TimeSpan.FromMinutes(TransactionTimeout))
    .UnicastBus()
    .ImpersonateSender(true)
    .LoadMessageHandlers()
    .MsmqSubscriptionStorage()
    .InstallNcqrs()
    .CreateBus()
    .Start();


public class NcqrsNsbConfigure : NServiceBus.Configure
{
    private NsbCommandService _commandService;
    private InProcessEventBus _inProcessEventBus;

    public static NcqrsNsbConfigure InstallNcqrs(NServiceBus.Configure config)
    {
        var configNcqrs = new NcqrsNsbConfigure();
        configNcqrs.Install(config);
        return configNcqrs;
    }

    public void Install(NServiceBus.Configure config)
    {
        Builder = config.Builder;
        Configurer = config.Configurer;

        NcqrsEnvironment.Configure(new NsbEnvironmentConfiguration(Builder));
        var compositeBus = new CompositeEventBus();
        _inProcessEventBus = new SafeInProcessEventBus();
        compositeBus.AddBus(_inProcessEventBus);
        compositeBus.AddBus(new NsbEventBusWrapper());  
        NcqrsEnvironment.SetDefault<IEventBus>(compositeBus);
        _commandService = new NsbCommandService();
        var safeCommandService = new NSBCommandService(NcqrsEnvironment.Get<IBus>(), _commandService);
        config.Configurer.RegisterSingleton(typeof(Ncqrs.Commanding.ServiceModel.ICommandService), safeCommandService);
    }

    public NcqrsNsbConfigure RegisterExecutor<TCommand>(ICommandExecutor<TCommand> executor) where TCommand : Ncqrs.Commanding.ICommand
    {
        _commandService.RegisterExecutor(executor);
        return this;
    }

    public NcqrsNsbConfigure RegisterInProcessEventHandler<TEvent>(IEventHandler<TEvent> handler) where TEvent : Ncqrs.Eventing.IEvent
    {
        _inProcessEventBus.RegisterHandler(handler);
        return this;
    }

    public NcqrsNsbConfigure RegisterInProcessEventHandler(Type eventType, Action<Ncqrs.Eventing.IEvent> handler)
    {
        _inProcessEventBus.RegisterHandler(eventType, handler);
        return this;
    }

    public NcqrsNsbConfigure RegisterAllInProcessEventHandlers(Assembly asm)
    {
        _inProcessEventBus.RegisterAllHandlersInAssembly(asm);
        return this;
    }
}

Has anyone come across this and found a solution?

1

There are 1 best solutions below

3
On

I have not used NCQRS but I would guess that you are leaking the true configuration object.

When you call .InstallNcqrs() (and shouldn't this be an extension method in order to make the fluent config compile?) you are not returning the passed in NServiceBus.Configure object, you are returning your own NcqrsNsbConfigure object. Sure, you supply the Builder and Configurer to match the incoming Configure object, but perhaps you are leaking some other element that the rest of the NServiceBus pipeline now expects.

I would try to rearrange your code so that you initialize the NCQRS things you need to, but then return the original Configure object. You aren't using the returned object to call any other fluent methods to configure NCQRS so I don't think it should be a problem.