charlessolar / Aggregates.NET

.NET event sourced domain driven design model via NServiceBus and GetEventStore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to catch BusinessException in custom built behavior?

AbdoDabbas opened this issue · comments

Hi Charles,

I was trying to build a custom behavior to catch exceptions and publish a notification, and also tried to follow this tutorial about Subscribing to Error notifications from ParticularSoftware site, but I can't catch any BusinessException thrown.

In my system I'm not using the Command method in the class BusExtensions in Aggregates.NET, I'm using directly the bus.Send like in the method PassiveCommand in the pre-mentioned class.

I looked in the source code and figured out the library is handling it in the ExceptionRejector class, any way to catch the exception? and way to remove this step? because I couldn't, 3 steps are depending on each other:

  • CommandAcceptor
  • UnitOfWorkExecution
  • ExceptionRejector

I tried this and it's not working:

endpointConfiguration.Pipeline.Remove("CommandAcceptor");
endpointConfiguration.Pipeline.Remove("UnitOfWorkExecution");
endpointConfiguration.Pipeline.Remove("ExceptionRejector");

I don't think you'll be able to remove those behaviors - they are added via a NSB feature installed via Agg.Net.

If your handler throws a BusinessException - a reply message is sent to the sender of the command. An example of how to catch and handle these exceptions is shown in the examples: https://github.com/charlessolar/eShopOnContainersDDD/blob/master/src/Infrastructure/Extensions/BusExtensions.cs#L132

If you are sending a PassiveCommand - thats a command that is not expecting a reply. So you actually wouldn't get any accept or failure by design. A PassiveCommand is meant to be a command sent where you don't care if it succeeds or not. The important line in the example's when sending commands is
options.SetHeader(Aggregates.Defaults.RequestResponse, "1"); this tells the receiver that you're waiting for a response.

The library will catch and send back to the origin any exception that occurs during message processing.

If you want to catch an exception and send a message to some other endpoint as a notification. You can create your own pipeline behavior as NSB recommends. Just make sure its inserted into the pipeline AFTER ExceptionRejector - because that class is meant to handle ALL exceptions.

If you want to catch an exception and send a message to some other endpoint as a notification...
Exactly this is what I want, to send notification and continue the pipeline as it is.
I tried to add custom behavior and insert it after ExceptionRejector, but it continues as nothing happened (I throw an exception of type BusinessException in the handler).
Here's the invoke method in this custom behavior:

public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
{
	try
	{
		// this will be called normally, then it'll continue
		await next().ConfigureAwait(false);
	}
	catch (BusinessException ex)
	{
                // Do something here
		throw;
	}
	catch (Exception ex)
	{
                // Do something here
		throw;
	}
}

I don't if it's related but I set retries to 1 .SetRetries(1).

If I throw a standard Exception it'll work and will go in the catch block.

Make sure your behavior is also inserted after CommandAcceptor actually - that behavior is handling business exceptions specifically.

I tried, still the same, just continue like nothing thrown.

I'll try to add my behavior in sample you provide, so I'll not be doing something wrong.

I tried the same with the ToDo sample and gives the same behavior, no exception thrown.

I set a break point and it's sure being used, because it hits the break point, call the next(), goes to the handler and I throw a BusinessException there, then it continues after the next normally without going to the catch (already mentioned the code above.

Sounds like something is eating that exception. Do a breakpoint on your throw and see where it goes. Also make sure when you get inside your behavior, check the stack trace and make sure CommandAcceptor is in the stack

I add a breakpoint in the handler and got the stack trace after throwing the exception, you can see the custom behavior FailedMessageNotification I added is at line 60 which is after the CommandAcceptor behavior at line 65:

1. at System.Environment.get_StackTrace()
2. at Example.Todo.Domain.Handler.Handle(Add command, IMessageHandlerContext ctx) in C:\Projects\temp\TodoMVC-DDD-CQRS-EventSourcing3\src\Domain\Todo\Handler.cs:line 19
3. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
4. at Example.Todo.Domain.Handler.Handle(Add command, IMessageHandlerContext ctx)
5. at NServiceBus.Pipeline.MessageHandler.Invoke(Object message, IMessageHandlerContext handlerContext)
6. at Aggregates.Internal.BulkInvokeHandlerTerminator.Terminate(IInvokeHandlerContext context) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\BulkInvokeHandlerTerminator.cs:line 87
7. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
8. at Aggregates.Internal.BulkInvokeHandlerTerminator.Terminate(IInvokeHandlerContext context)
9. at Aggregates.Internal.BulkInvokeHandlerTerminator.Terminate(IInvokeHandlerContext context) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\BulkInvokeHandlerTerminator.cs:line 166
10. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
11. at Aggregates.Internal.BulkInvokeHandlerTerminator.Terminate(IInvokeHandlerContext context)
12. at NServiceBus.SagaPersistenceBehavior.Invoke(IInvokeHandlerContext context, Func`2 next)
13. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
14. at NServiceBus.SagaPersistenceBehavior.Invoke(IInvokeHandlerContext context, Func`2 next)
15. at NServiceBus.LoadHandlersConnector.Invoke(IIncomingLogicalMessageContext context, Func`2 stage)
16. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
17. at NServiceBus.LoadHandlersConnector.Invoke(IIncomingLogicalMessageContext context, Func`2 stage)
18. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
19. at NServiceBus.RequestResponseInvocationForMessagesBehavior.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
20. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
21. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
22. at Aggregates.Internal.MutateIncoming.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\MutateIncoming.cs:line 51
23. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
24. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
25. at Aggregates.Internal.LogContextProviderBehaviour.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\LogContextProviderBehaviour.cs:line 38
26. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
27. at Aggregates.Internal.LogContextProviderBehaviour.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
28. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
29. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
30. at Aggregates.Internal.LocalMessageUnpack.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\LocalMessageUnpack.cs:line 119
31. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
32. at Aggregates.Internal.LocalMessageUnpack.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
33. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
34. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
35. at Aggregates.Internal.UnitOfWorkExecutor.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\UnitOfWorkExecutor.cs:line 88
36. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
37. at Aggregates.Internal.UnitOfWorkExecutor.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
38. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
39. at NServiceBus.ScheduledTaskHandlingBehavior.Invoke(IIncomingLogicalMessageContext context, Func`2 next)
40. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
41. at NServiceBus.ScheduledTaskHandlingBehavior.Invoke(IIncomingLogicalMessageContext context, Func`2 next)
42. at NServiceBus.MutateIncomingMessageBehavior.InvokeIncomingMessageMutators(IIncomingLogicalMessageContext context, Func`2 next)
43. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
44. at NServiceBus.MutateIncomingMessageBehavior.InvokeIncomingMessageMutators(IIncomingLogicalMessageContext context, Func`2 next)
45. at NServiceBus.MutateIncomingMessageBehavior.Invoke(IIncomingLogicalMessageContext context, Func`2 next)
46. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
47. at Aggregates.Internal.ExceptionRejector.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\ExceptionRejector.cs:line 48
48. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
49. at Aggregates.Internal.ExceptionRejector.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
50. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
51. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
52. at Aggregates.Internal.SagaBehaviour.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\SagaBehaviour.cs:line 31
53. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
54. at Aggregates.Internal.SagaBehaviour.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
55. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
56. at NServiceBus.InvokeSagaNotFoundBehavior.Invoke(IIncomingLogicalMessageContext context, Func`2 next)
57. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
58. at NServiceBus.InvokeSagaNotFoundBehavior.Invoke(IIncomingLogicalMessageContext context, Func`2 next)
59. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
60. at Domain.FailedMessageNotification.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\Projects\temp\TodoMVC-DDD-CQRS-EventSourcing3\src\Domain\FailedMessageNotification.cs:line 39
61. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
62. at Domain.FailedMessageNotification.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
63. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
64. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
65. at Aggregates.Internal.CommandAcceptor.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\CommandAcceptor.cs:line 38
66. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
67. at Aggregates.Internal.CommandAcceptor.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
68. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
69. at NServiceBus.DeserializeMessageConnector.Invoke(IIncomingPhysicalMessageContext context, Func`2 stage)
70. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
71. at NServiceBus.DeserializeMessageConnector.Invoke(IIncomingPhysicalMessageContext context, Func`2 stage)
72. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
73. at NServiceBus.RequestResponseInvocationForControlMessagesBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`1 next)
74. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
75. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
76. at Aggregates.Internal.MessageIdentifier.Invoke(IIncomingPhysicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\MessageIdentifier.cs:line 45
77. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
78. at NServiceBus.MutateIncomingTransportMessageBehavior.InvokeIncomingTransportMessagesMutators(IIncomingPhysicalMessageContext context, Func`2 next)
79. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
80. at NServiceBus.MutateIncomingTransportMessageBehavior.InvokeIncomingTransportMessagesMutators(IIncomingPhysicalMessageContext context, Func`2 next)
81. at NServiceBus.MutateIncomingTransportMessageBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`2 next)
82. at NServiceBus.ProcessingStatisticsBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`2 next)
83. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
84. at NServiceBus.ProcessingStatisticsBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`2 next)
85. at NServiceBus.TransportReceiveToPhysicalMessageConnector.Invoke(ITransportReceiveContext context, Func`2 next)
86. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
87. at NServiceBus.TransportReceiveToPhysicalMessageConnector.Invoke(ITransportReceiveContext context, Func`2 next)
88. at NServiceBus.Pipeline`1.Invoke(TContext context)
89. at NServiceBus.MainPipelineExecutor.Invoke(MessageContext messageContext)
90. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
91. at NServiceBus.MainPipelineExecutor.Invoke(MessageContext messageContext)
92. at NServiceBus.TransportReceiver.<Init>b__4_0(MessageContext c)
93. at NServiceBus.Transport.RabbitMQ.MessagePump.Process(BasicDeliverEventArgs message, Byte[] messageBody) in /_/src/NServiceBus.Transport.RabbitMQ/Receiving/MessagePump.cs:line 265
94. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
95. at NServiceBus.Transport.RabbitMQ.MessagePump.Process(BasicDeliverEventArgs message, Byte[] messageBody)
96. at NServiceBus.Transport.RabbitMQ.MessagePump.Consumer_Received(Object sender, BasicDeliverEventArgs eventArgs) in /_/src/NServiceBus.Transport.RabbitMQ/Receiving/MessagePump.cs:line 207
97. at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object s)
98. at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
99. at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread)
100. at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
101. at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.<>c.<OutputCorrelationEtwEvent>b__6_0(Action innerContinuation, Task continuationIdTask)
102. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke()
103. at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.RunAction(Object state)
104. at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
105. at System.Threading.ThreadPoolWorkQueue.Dispatch()
106. at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

And here's the StackTrace from inside the custom behavior I built, after the exception and continuing the execution in the invoke method, you can see the FailedMessageNotification at line 2 and CommandAcceptor at line 7:

1. at System.Environment.get_StackTrace()
2. at Domain.FailedMessageNotification.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\Projects\temp\TodoMVC-DDD-CQRS-EventSourcing3\src\Domain\FailedMessageNotification.cs:line 49
3. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
4. at Domain.FailedMessageNotification.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
5. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
6. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
7. at Aggregates.Internal.CommandAcceptor.Invoke(IIncomingLogicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\CommandAcceptor.cs:line 38
8. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
9. at Aggregates.Internal.CommandAcceptor.Invoke(IIncomingLogicalMessageContext context, Func`1 next)
10. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
11. at NServiceBus.DeserializeMessageConnector.Invoke(IIncomingPhysicalMessageContext context, Func`2 stage)
12. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
13. at NServiceBus.DeserializeMessageConnector.Invoke(IIncomingPhysicalMessageContext context, Func`2 stage)
14. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
15. at NServiceBus.RequestResponseInvocationForControlMessagesBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`1 next)
16. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
17. at NServiceBus.Pipeline.Behavior`1.<>c__DisplayClass0_0.<Invoke>b__0()
18. at Aggregates.Internal.MessageIdentifier.Invoke(IIncomingPhysicalMessageContext context, Func`1 next) in C:\projects\aggregates-net\src\Aggregates.NET.NServiceBus\Internal\MessageIdentifier.cs:line 45
19. at NServiceBus.Pipeline.Behavior`1.Invoke(TContext context, Func`2 next)
20. at NServiceBus.MutateIncomingTransportMessageBehavior.InvokeIncomingTransportMessagesMutators(IIncomingPhysicalMessageContext context, Func`2 next)
21. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
22. at NServiceBus.MutateIncomingTransportMessageBehavior.InvokeIncomingTransportMessagesMutators(IIncomingPhysicalMessageContext context, Func`2 next)
23. at NServiceBus.MutateIncomingTransportMessageBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`2 next)
24. at NServiceBus.ProcessingStatisticsBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`2 next)
25. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
26. at NServiceBus.ProcessingStatisticsBehavior.Invoke(IIncomingPhysicalMessageContext context, Func`2 next)
27. at NServiceBus.TransportReceiveToPhysicalMessageConnector.Invoke(ITransportReceiveContext context, Func`2 next)
28. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
29. at NServiceBus.TransportReceiveToPhysicalMessageConnector.Invoke(ITransportReceiveContext context, Func`2 next)
30. at NServiceBus.Pipeline`1.Invoke(TContext context)
31. at NServiceBus.MainPipelineExecutor.Invoke(MessageContext messageContext)
32. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
33. at NServiceBus.MainPipelineExecutor.Invoke(MessageContext messageContext)
34. at NServiceBus.TransportReceiver.<Init>b__4_0(MessageContext c)
35. at NServiceBus.Transport.RabbitMQ.MessagePump.Process(BasicDeliverEventArgs message, Byte[] messageBody) in /_/src/NServiceBus.Transport.RabbitMQ/Receiving/MessagePump.cs:line 265
36. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
37. at NServiceBus.Transport.RabbitMQ.MessagePump.Process(BasicDeliverEventArgs message, Byte[] messageBody)
38. at NServiceBus.Transport.RabbitMQ.MessagePump.Consumer_Received(Object sender, BasicDeliverEventArgs eventArgs) in /_/src/NServiceBus.Transport.RabbitMQ/Receiving/MessagePump.cs:line 207
39. at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.ExecutionContextCallback(Object s)
40. at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
41. at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext(Thread threadPoolThread)
42. at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.AsyncStateMachineBox`1.MoveNext()
43. at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.<>c.<OutputCorrelationEtwEvent>b__6_0(Action innerContinuation, Task continuationIdTask)
44. at System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke()
45. at System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter.RunAction(Object state)
46. at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
47. at System.Threading.ThreadPoolWorkQueue.Dispatch()
48. at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

The steps are as following:
MyFailedMessageNotification -> ExceptionRejector -> MyHandler -> ExceptionRejector (this one swallows the exception at line 53 and do return instead of throw again) -> MyFailedMessageNotification

There steps between those I didn't mention, but these are the important ones as I think.

I solved the issue by adding these two lines in the registration of my behavior:

InsertAfter("CommandAcceptor");
InsertAfter("ExceptionRejector");

One of them is not enough, it has to be both.

Thanks, @charlessolar for the help.