Closed mojamcpds closed 8 years ago
So you have two endpoints
The first endpoint has the SendOnly bus and you are totally sure that the seconds bus for the Registrations is not SendOnly?
When you have sent the command, the command will go into the queue of the Registrations endpoint. Please can you shut down the Registrations Application and send the command? This way you can ensure that the command is really in the inbox queue of the Registrations endpoint.
You have checked the error queue, that there is nothing?
Please provide the log file of the Registrations endpoint.
Dear @marinkobabic According to your instruction I removed Endpoints and checked but yet not working.
Here is my Bus Registration code:
public static ISendOnlyBus Bus { get; private set; }
private void RegisterBus()
{
var busConfiguration = new BusConfiguration();
busConfiguration.UseSerialization<JsonSerializer>();
busConfiguration.UseTransport<MsmqTransport>();
busConfiguration.Transactions().Disable();
busConfiguration.PurgeOnStartup(false);
LogManager.Use<NServiceBus.Log4Net.Log4NetFactory>();
Bus = NServiceBus.Bus.CreateSendOnly(busConfiguration);
}
And my Endpoint configuration is as follows:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantToRunWhenBusStartsAndStops, IWantToRunWhenConfigurationIsComplete
{
public void Init()
{
LogManager.Use<Log4NetFactory>();
}
public void Start()
{
Wireup.Init()
.UsingInMemoryPersistence()
.EnlistInAmbientTransaction()
.NES()
.Build();
}
public void Stop()
{
}
public void Customize(BusConfiguration configuration)
{
configuration.UseSerialization<Json>();
configuration.EnableInstallers();
configuration.UsePersistence<InMemoryPersistence>();
configuration.UseTransport<MsmqTransport>();
configuration.PurgeOnStartup(false);
configuration.RegisterComponents(c =>
{
c.ConfigureComponent<Repository>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<SqlBlobStorage>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<RegistrationProcessManagerRouter>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<RegistrationProcessManager>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<ConferenceViewModelGenerator>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<DraftOrderViewModelGenerator>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<OrderCommandHandler>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<PricedOrderViewModelGenerator>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<SeatAssignmentsHandler>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<SeatAssignmentsViewModelGenerator>(DependencyLifecycle.InstancePerUnitOfWork);
c.ConfigureComponent<SeatsAvailabilityHandler>(DependencyLifecycle.InstancePerUnitOfWork);
});
}
public void Run(Configure config)
{
config.NES();
}
}
I did not tell you to remove the endpoint. I just said that you have two NServiceBus services running. You should just stop one of the instances to be sure that it does not process any commands. When your controller sends the command and the transaction is commited you should go into the message queue and check if the message is in the "Registrations" inbox queue. If this is the case the command was sent successfully. We can from that point on investigate what is going on with the "Registrations" endpoint. For that purpose you can enable logging and start the instance of the "Registrations" endpoint. If there is a message in the inbox queue it will take the message and try to process it.
Yes. It goes to Registration queue but still doesn't invoke Command handler.
So the process which hosts the targed queue must be named as "Registrations" endpoint. When you startup this process then you can see the mappings in the log of message -> handler. When the process is started the message should disappear from inbox queue. Does this happen? How does the log look like?
Following message is given when I run EndPoint Server. Is it related to above problem?
Actually I am very new in Nservicebus so it takes time for me to understand the problem.
Yes. It tried to process your message but it failed. You will find the message in the error queue. The header of the message contains the reason resp. the sracktrace.
You can do a simple check. In your command handler remove the constructor which gets parameters and create a parameter less constructor. Set a break point inside of the handle method to check if the point is reached.
If the point is reached but when your constructor has parameters not, then you know the source of the problem.
In your case I can imagine that IRepository is not registered in the unity container. Please verify ny statement.
First step is to create root unitycontainer. Register your classes and IRepository. Pass the container to nservicebus during bootstrapping so that nservicebus uses your container.
In case if unity the hierarchicallifetime = unitofwork.
Whenever a command comes in, nservicebus creates a child container as unitofwork container and removes this when transaction is completed.
Thanks for your reply. According to your instruction I configured as follows:
private void RegisterBus(IUnityContainer container)
{
var busConfiguration = new BusConfiguration();
busConfiguration.UseSerialization<JsonSerializer>();
busConfiguration.UseTransport<MsmqTransport>();
busConfiguration.Transactions().Disable();
busConfiguration.PurgeOnStartup(false);
busConfiguration.UseContainer<UnityBuilder>();
busConfiguration.UseContainer<UnityBuilder>(c => c.UseExistingContainer(container));
LogManager.Use<NServiceBus.Log4Net.Log4NetFactory>();
Bus = NServiceBus.Bus.CreateSendOnly(busConfiguration);
}
And Resolved my dependencies as follows:
private static UnityContainer CreateContainer()
{
var container = new UnityContainer();
try
{
container.RegisterInstance<ITextSerializer>(new JsonTextSerializer());
container.RegisterType<DbContext, RegistrationProcessManagerDbContext>("registration", new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistrationProcesses"));
container.RegisterType<IProcessManagerDataContext<RegistrationProcessManager>, SqlProcessManagerDataContext<RegistrationProcessManager>>(
new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<Func<DbContext>>("registration"), typeof(IBus), typeof(ITextSerializer)));
container.RegisterType<DbContext, PaymentsDbContext>("payments", new TransientLifetimeManager(), new InjectionConstructor("Payments"));
container.RegisterType<IDataContext<ThirdPartyProcessorPayment>, SqlDataContext<ThirdPartyProcessorPayment>>(
new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<Func<DbContext>>("payments"), typeof(IBus)));
container.RegisterType<ConferenceRegistrationDbContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistration"));
container.RegisterType<IConferenceDao, ConferenceDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IOrderDao, OrderDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IPricingService, PricingService>(new ContainerControlledLifetimeManager());
container.RegisterType<global::Conference.ConferenceContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceManagement"));
container.RegisterType<ConferenceRegistrationDbContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistration"));
container.RegisterType<PaymentsReadDbContext>(new TransientLifetimeManager(), new InjectionConstructor("Payments"));
container.RegisterType<IRepository,Repository>(new ContainerControlledLifetimeManager());
var cache = new MemoryCache("ReadModel");
container.RegisterType<IOrderDao, OrderDao>();
container.RegisterType<IConferenceDao, CachingConferenceDao>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<ConferenceDao>(), cache));
container.RegisterType<IPaymentDao, PaymentDao>();
OnCreateContainer(container);
return container;
}
catch
{
container.Dispose();
throw;
}
}
static partial void OnCreateContainer(UnityContainer container);
Finally called them inside Application_Start() method of Global.asax as follows:
private IUnityContainer container;
protected void Application_Start()
{
DatabaseSetup.Initialize();
this.container = CreateContainer();
DependencyResolver.SetResolver(new UnityServiceLocator(this.container));
RegisterBus(this.container);
RegisterGlobalFilters(GlobalFilters.Filters);
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AreaRegistration.RegisterAllAreas();
AppRoutes.RegisterRoutes(RouteTable.Routes);
this.OnStart();
}
But the behavior is still unchanged. If I remove constructors from OrderHandler class then it fires Command Handler. But with dependency resolver it doesn't work.
Don't know where I am making the mistake.
Looks good now. So please try just to have IRepository in your OrderCommandHandler constructor. Does it still work? Now remove the IRepository and use just the IPricingService. Does it now work?
To make it even simpler in the last line of Application_Start please add the following lines just as test:
var rep = this.container.Resolve < IRepository >(); var pr = this.container.Resolve < IPricingService >(); var handler = this.container.Resolve < OrderCommandHandler >();
Do all the three resolving work?
By the way please remove the first line here
busConfiguration.UseContainer
I tried according to your instruction as follows.
Then I registered & resolved all command handlers and event handlers:
private static void RegisterEventHandlers(IUnityContainer container)
{
container.RegisterType<RegistrationProcessManagerRouter>();
container.RegisterType<DraftOrderViewModelGenerator>();
container.RegisterType<PricedOrderViewModelGenerator>();
container.RegisterType<ConferenceViewModelGenerator>();
container.RegisterType<SeatAssignmentsViewModelGenerator>();
container.RegisterType<SeatAssignmentsHandler>();
container.RegisterType<global::Conference.OrderEventHandler>();
}
private static void RegisterCommandHanlders(IUnityContainer container)
{
container.RegisterType<OrderCommandHandler>();
container.RegisterType<SeatsAvailabilityHandler>();
container.RegisterType<ThirdPartyProcessorPaymentCommandHandler>();
}
private void ResolveEventHandlers(IUnityContainer container)
{
container.Resolve<RegistrationProcessManagerRouter>();
container.Resolve<DraftOrderViewModelGenerator>();
container.Resolve<PricedOrderViewModelGenerator>();
container.Resolve<ConferenceViewModelGenerator>();
container.Resolve<SeatAssignmentsViewModelGenerator>();
container.Resolve<SeatAssignmentsHandler>();
container.Resolve<global::Conference.OrderEventHandler>();
}
private void ResolveCommandHanlders(IUnityContainer container)
{
container.Resolve<IRepository>();
container.Resolve<IPricingService>();
container.Resolve<OrderCommandHandler>();
container.Resolve<SeatsAvailabilityHandler>();
container.Resolve<ThirdPartyProcessorPaymentCommandHandler>();
}
Though my PricingService
(concrete implementation of IPricingService
) takes IConferenceDao
as constructor parameter so I registered it as follows:
container.RegisterType<IPricingService, PricingService>(new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<ConferenceDao>())
);
Then I called them from Application_Start()
method of Global.asax.cs
as follows:
protected void Application_Start()
{
DatabaseSetup.Initialize();
this.container = CreateContainer();
DependencyResolver.SetResolver(new UnityServiceLocator(this.container));
RegisterBus(this.container);
RegisterGlobalFilters(GlobalFilters.Filters);
RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
AreaRegistration.RegisterAllAreas();
AppRoutes.RegisterRoutes(RouteTable.Routes);
ResolveCommandHanlders(this.container);
ResolveEventHandlers(this.container);
this.OnStart();
}
Also called Registered methods inside Ioc configuration method as follows:
private static UnityContainer CreateContainer()
{
var container = new UnityContainer();
try
{
RegisterCommandHanlders(container);
RegisterEventHandlers(container);
container.RegisterInstance<ITextSerializer>(new JsonTextSerializer());
container.RegisterType<DbContext, RegistrationProcessManagerDbContext>("registration", new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistrationProcesses"));
container.RegisterType<IProcessManagerDataContext<RegistrationProcessManager>, SqlProcessManagerDataContext<RegistrationProcessManager>>(
new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<Func<DbContext>>("registration"), typeof(IBus), typeof(ITextSerializer)));
container.RegisterType<DbContext, PaymentsDbContext>("payments", new TransientLifetimeManager(), new InjectionConstructor("Payments"));
container.RegisterType<IDataContext<ThirdPartyProcessorPayment>, SqlDataContext<ThirdPartyProcessorPayment>>(
new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<Func<DbContext>>("payments"), typeof(IBus)));
container.RegisterType<ConferenceRegistrationDbContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistration"));
container.RegisterType<IConferenceDao, ConferenceDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IOrderDao, OrderDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IPricingService, PricingService>(new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<ConferenceDao>())
);
container.RegisterType<global::Conference.ConferenceContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceManagement"));
container.RegisterType<ConferenceRegistrationDbContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistration"));
container.RegisterType<PaymentsReadDbContext>(new TransientLifetimeManager(), new InjectionConstructor("Payments"));
container.RegisterType<IRepository,Repository>(new ContainerControlledLifetimeManager());
var cache = new MemoryCache("ReadModel");
container.RegisterType<IOrderDao, OrderDao>();
container.RegisterType<IConferenceDao, CachingConferenceDao>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<ConferenceDao>(), cache));
container.RegisterType<IPaymentDao, PaymentDao>();
OnCreateContainer(container);
return container;
}
catch
{
container.Dispose();
throw;
}
}
I also removed the linebusConfiguration.UseContainer<UnityBuilder>();
from BusRegistration()
method as follows:
private void RegisterBus(IUnityContainer container)
{
var busConfiguration = new BusConfiguration();
busConfiguration.UseSerialization<JsonSerializer>();
busConfiguration.UseTransport<MsmqTransport>();
busConfiguration.Transactions().Disable();
busConfiguration.PurgeOnStartup(false);
busConfiguration.UseContainer<UnityBuilder>(c => c.UseExistingContainer(container));
LogManager.Use<NServiceBus.Log4Net.Log4NetFactory>();
Bus = NServiceBus.Bus.CreateSendOnly(busConfiguration);
}
But yet it doesn't work. If I remove IPricingService
from the constructor of OrderCommandHandler
then it fire the Handle method. I think something wrong with the registration of IPricingService
. For your kind consideration I am giving the entire dependencies of PricingService
class.
Constructor of OrderCommandHandler.cs:
private readonly IRepository repository;
private readonly IPricingService pricingService;
public OrderCommandHandler(IRepository repository, IPricingService pricingService)
{
this.repository = repository;
this.pricingService = pricingService;
}
Constructor of PriceService.cs
private readonly IConferenceDao conferenceDao;
public PricingService(IConferenceDao conferenceDao)
{
if (conferenceDao == null) throw new ArgumentNullException("conferenceDao");
this.conferenceDao = conferenceDao;
}
_Constructor of ConferenceDao.cs _
private readonly Func<ConferenceRegistrationDbContext> contextFactory;
public ConferenceDao(Func<ConferenceRegistrationDbContext> contextFactory)
{
this.contextFactory = contextFactory;
}
Considering above constructors is it right to register dependency of IPricingService and PricingService that defined as follows:
container.RegisterType<IPricingService, PricingService>(new TransientLifetimeManager(),
new InjectionConstructor(new ResolvedParameter<ConferenceDao>())
);
I really struggling with this issue.
To register the dependecies do the following
container.Register < IPricingService, PricingService >(); container.Register < IConferenceDao, ConferenceDao >();
and the problem you have is the constructor of ConferenceDao. It can't be a Func. Please make a new interface likeConferenceRegistrationDbContextFactory and pass it as parameter to ConferenceDao. Don't forget to register the new interface in container. After you have done all of this it will work :smiley:
Tried according to your instruction but yet doesn't work.
What I did is just instead of passing Func I just sendConferenceRegistrationDbContext
through the constructor of ConferenceDao
as follows:
private readonly ConferenceRegistrationDbContext context;
public ConferenceDao(ConferenceRegistrationDbContext context)
{
this.context = context;
}
And dependency resolved as follows:
container.RegisterType<ConferenceRegistrationDbContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistration"));
container.RegisterType<IConferenceDao, ConferenceDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IOrderDao, OrderDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IPricingService, PricingService>(new ContainerControlledLifetimeManager());
But result is as previous
You don't need to tell unity that it will be used as parameter to constructor.
container.RegisterType< ConferenceRegistrationDbContext >();
is enough. Can you resolve
container.Resolve< IConferenceDao > ();
If not pass the constructor return following error: The type String cannot be constructed. You must configure the container to supply this value.
However I resolved IConferenceDao
as follows:
container.RegisterType<IConferenceDao, ConferenceDao>(new ContainerControlledLifetimeManager());
container.Resolve<IConferenceDao>();
container.RegisterType<IOrderDao, OrderDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IPricingService, PricingService>(new ContainerControlledLifetimeManager());
ConferenceDao gets the ConferenceRegistrationDbContext and not a string. Please can you copy your few classes in a console application and demonstrate the problem. So that I can download it and make it work in few minutes.
Actually we are going to develop a Web based ERP System where we'll use following architectures and technologies: Database : Microsoft SQL Server Framework : ASP.NET MVC Front-End : KendoUI, RAZOR CSHTML, Bootstrap, and HTML-5 Server-Side : C#, Node.js API : ASP.NET Web API, Node.js API ORM : Entity Framework Unit Testing : X-Unit Methodology : Domain Driven Design, Domain Model Architectures : Onion Architecture (DDD), CQRS & Event Sourcing. Enterprise Service Bus : NServiceBus. EventStorage : RavenDB (Though NEventStore provide RavenDB usage flexibility so we’ll use it) Messaging : MSMQ Dependency Injection : Unity Mocking : Moq Mapping : Automapper Continuous Integration: Teamcity Refactoring : Resharper Source control : Git
Though NES.Cqrs gives us the built-in flexibility to work with CQRS architecture including NServiceBus, NEventStore (with RavenDB), MSMQ so we decided to use it.
Before starting the project we have to R&D on some concepts and* NES.CQRS* is one of them. So we started R&D on NES.CQRS and trying to convert Conference project into _NES _ framework for learning purpose.
However I am uploading my whole project. Please check and help me where I am making the mistake.
Thanks for your kind help.
When I start your project the following interfaces are resolved properly
private void ResolveCommandHanlders(IUnityContainer container)
{
var rep = container.Resolve<IRepository>();
var pric = container.Resolve<IPricingService>();
var ord = container.Resolve<OrderCommandHandler>();
var seat = container.Resolve<SeatsAvailabilityHandler>();
var pay = container.Resolve<ThirdPartyProcessorPaymentCommandHandler>();
}
Is this also the case on your machine?
Then where is the problem? Why not it works properly? Any other configuration related issue?
Will run the whole solution in the evening and let you know about the results ;-)
Ok. Thanks. Waiting for your kind response. Shall I give you database script?
No it's ok :-) thanks
Any update regarding the issue? I debugged it line by line. To do so when I Step-in i.e. press F11 on commandbus.Send(command)
method it shows me unicast.cs
not found
Then I removed the constructor injection from OrderCommandHandler class by configuring as follows:
private readonly IRepository repository;
private readonly IPricingService pricingService;
public OrderCommandHandler()
{
var container = new UnityContainer();
container.RegisterType<IRepository, Repository>();
container.RegisterType<ConferenceRegistrationDbContext>(new TransientLifetimeManager(), new InjectionConstructor("ConferenceRegistration"));
container.RegisterType<IConferenceDao, ConferenceDao>(new ContainerControlledLifetimeManager());
container.RegisterType<IPricingService, PricingService>();
this.repository = container.Resolve<IRepository>();
this.pricingService = container.Resolve<IPricingService>();
}
After remove the constructor injection now when commandbus.Send() method executes it invoke OrderCommandHandler class and execute proper handle method. But the problem is when it tries to execute repository.Get<Registration.Order>(command.OrderId);
this line it shows me behaviorchain.cs not found.
For your kind consideration I am giving you the Handle methods code:
public void Handle(RegisterToConference command)
{
var items = command.Seats.Select(t => new OrderItem(t.SeatType, t.Quantity)).ToList();
var order = repository.Get<Registration.Order>(command.OrderId);
if (order == null)
{
order = new Registration.Order(command.OrderId, command.ConferenceId, items, pricingService);
}
else
{
order.UpdateSeats(items, pricingService);
}
repository.Add<Registration.Order>(order);
}
Thanks. Solved that issue. :)
Is now everything working properly? In your backed you have to use the unity and to register all dependencies. Actually there is nothing related to unity.
Yes. Got the issue. :) If needed I will contact you :) Thanks for your kind effort :)
Dear @marinkobabic:/ @elliotritchie
My Command Class is as follows:
I send above command from my controllers action method as follows:
Logically when I click on register button it had to send the command to registered command handler and executes further actions. But it doesn't. For kind consideration I am giving my all related codes with this action.
Note: Messages are saves in Queue properly.
Following is my command handler class:
The aggregate is as follows:
Events are as follows:
Events are handled as follows:
My EndPoint Configuration is as follows:
Inside my web.config I configured as follows:
Inside Global.asax I registered Bus as follows:
Note: I am using Unity Container for Resolve Dependencies as follows:
Now I am really confused where I am making mistake.
Please help me to fix the issue.