Hi Nazariy, I was able to remove the default ErrorAction and replace it with my own without changing the RSB code base. I'll show you the code below, but first a caveat: this code is for RSB 1.9. I know there has been a lot of work done since then on containers, etc, so some of this may not work exactly the same way depending on what version you are using.
First, I had to create a new DefaultHost so I can change the way the container gets configured. The methods in the DefaultHost are private, so I just copied the DefaultHost code into a new class. When you start up RSB, you now have specify this new class as the host: /Host:"MagicBus.Utils.RhinoServiceBus.MyDefaultHost,MagicBus.Utils". The only code that needs to change in the class is in the InitializeContainer() method: private void InitializeContainer() { bootStrapper.InitializeContainer(container); if (hostConfiguration != null) container.Kernel.ConfigurationStore.AddFacilityConfiguration("rhino.esb", hostConfiguration); // This is the only line which is different than the DefaultHost that comes with RSB. var facility = new MyServiceBusFacility(); bootStrapper.ConfigureBusFacility(facility); container.Kernel.AddFacility("rhino.esb", facility); } MyDefaultHost will now be configured with MyServiceBusFacility instead of the default implementation. MyServiceBusFacility inherits from RhinoSerivceBusFacility to modify some configuration to include your custom ErrorAction. First, I copied the Init method (actually from the AbstractRhinoServiceBusFacility) and change the line: Kernel.Register( AllTypes.FromAssembly(typeof(IBusConfigurationAware).Assembly) .BasedOn<IBusConfigurationAware>() ); To: // Register our custom MsmqTransport configuration and exclude the // version provided by RSB Kernel.Register( Component.For<IBusConfigurationAware>().ImplementedBy<MyMsmqTransportConfigurationAware>(), AllTypes.FromAssembly(typeof (IBusConfigurationAware).Assembly) .BasedOn<IBusConfigurationAware>() .Unless(x => x == typeof (MsmqTransportConfigurationAware))); You will have to override ReadConfiguration() as well. Be sure to call base.ReadConfiguration first, then add any additional logic to Register the configuration information in the Kernel: /* Do stuff to set up your configuration here */ // Register the custom error action here so it will be // first in the registrations and therefore the first // to receive the events we care about later Kernel.Register( Component.For<IMsmqTransportAction>() .ImplementedBy<ErrorHandlingAction>() .DependsOn(new { numberOfRetries = NumberOfRetries, messageOwners, BusEndpoint = Endpoint.OriginalString })); The code above will register ErrorHandlingAction to handle errors in place of the default Action in RSB. My custom error handling will send an email to alert that an error has occurred. I went farther with my changes to configure the MSMQTransport to handle retries based on configuration values. I had to make the following changes so that I could override the default behavior of using the numberOfRetries from the bus configuration. You may or may not need to do this, depending on what you are trying to accomplish. I created MyMsmqTransportConfigurationAware by copying the MsmqTransportConfigurationAware class and changing this: Component.For<ITransport>() .LifeStyle.Is(LifestyleType.Singleton) .ImplementedBy(typeof(MsmqTransport)) .DependsOn(new { threadCount = facility.ThreadCount, endpoint = facility.Endpoint, queueIsolationLevel = facility.IsolationLevel, numberOfRetries = facility.NumberOfRetries, transactional = facility.Transactional, consumeInTransaction = facility.ConsumeInTransaction, }), To: Component.For<ITransport>() .LifeStyle.Is(LifestyleType.Singleton) .ImplementedBy(typeof(MyMsmqTransport)) .DependsOn(new { threadCount = facility.ThreadCount, endpoint = facility.Endpoint, queueIsolationLevel = facility.IsolationLevel, numberOfRetries = facility.NumberOfRetries, transactional = facility.Transactional, consumeInTransaction = facility.ConsumeInTransaction, }), MyMsmqTransport is what determines what to do with an errored message: retry or move to the Errors queue. I'm only using MSMQ for transport, so I ignored other transports for my case. In the finally{} block of the ProcessMessage method I made changes to determine how often to retry the error, and how long the delay should be before retrying the message. It took me a while to get this all working right. I learned a lot about RSB, and Castle configuration along the way. I had to copy code and create my own classes in places where the original code didn't allow access to its methods to inherit from the class, or override the methods. I suspect there are more elegant ways to accomplish some of what I did using better configuration of the container, or something similar. I would be happy to see improvements in this. I hope it helps. I'm happy to provide more detail if you need it. -Scott On Friday, October 12, 2012 2:14:22 AM UTC-6, Nazariy Kotylo wrote: > > Hi Scott > > Do you know if it is possible to replace the ErrorAction with a custom one > without modifying the RhinoServiceBus source code? > > Пʼятниця, 24 серпня 2012 р. 19:18:53 UTC+3 користувач Scott написав: >> >> You can extend the service bus to add other behaviors to do what you >> want. I don't have the code in front of me now, so I don't remember the >> exact implementation. You can create your own flavor of the ErrorAction >> and modify the service bus or facility to load your Action instead of, or >> in addition to, the ErrorAction. >> >> I did something similar in that the retries still occur, but the retry >> intervals are configurable and can be read from the config file at startup. >> We have a specific case where this was necessary due to outages from an >> external service. The Action will also email the IT staff when the service >> bus hits its maximum number of retries and moves the message to the error >> queue. >> >> It can be a little challenging to trace through the code to see where >> and when Actions and MessageModules get loaded. If you invest the time to >> understand the flow of the application on startup, you will discover how to >> plug in your custom code with very little effort. >> >> -Scott >> >> On Wednesday, August 22, 2012 7:02:28 AM UTC-6, René M. Andersen wrote: >>> >>> Hi, >>> >>> Is it possible to configure the error handling behaviour when message >>> processing fails? I am specifically thinking about how to replace the >>> built-in ErrorAction which controls the retries and moves the message to >>> the error queue when all retries have been used. >>> >>> We would like to preserve the retry functionality but remove the message >>> from the queue instead of moving it to the error queue. >>> >> -- You received this message because you are subscribed to the Google Groups "Rhino Tools Dev" group. To view this discussion on the web visit https://groups.google.com/d/msg/rhino-tools-dev/-/PWtgpYa1YkUJ. To post to this group, send email to rhino-tools-dev@googlegroups.com. To unsubscribe from this group, send email to rhino-tools-dev+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rhino-tools-dev?hl=en.