

Paramore Brighter: DRY with Custom Decorated Command Handlers
source link: https://colinmackay.scot/2018/03/18/paramore-brighter-dry-with-custom-decorated-command-handlers/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

DRY with Custom Decorated Command Handlers – The Blog of Colin MackaySkip to content
You may wish to add similar functionality to many (or all) command handlers. The typical example is logging. You can decorate a command handler in a similar way to the policies I showed in previous posts to add common functionality. I’ve used this technique to guard the handler from invalid command arguments/parameters (essentially a validator), and for ensuring that we ping our APM (Application Performance Management) tool when a command completes. I’ll use the latter to demonstrate creating a custom decorator and handler to initiate this common code.
Paramore Brighter Command Processor will look for any attributes derived from RequestHandlerAttribute
that are added to the Handle
method on your command handler class. It will then use them to build a pipeline for your command.
So, in the example here, our attribute class looks like this:
public class HeartbeatAttribute : RequestHandlerAttribute { public HeartbeatAttribute(int step, HandlerTiming timing = HandlerTiming.After) : base(step, timing) { } public override Type GetHandlerType() { return typeof(HeartbeatHandler<>); } }
We are deriving from RequestHandlerAttribute
, and it has an abstract method that you need to implement. GetHandlerType()
returns the type of handler that needs to be instantiated to handle the common task.
The RequestHandlerAttribute
class also takes two arguments for its constructor that you either need to capture from users of your attribute or supply yourself. It takes a step
and a timing
parameter. Since we’ve already talked about step
in a previous post we’ll move on to talking about timing
.
The two options for timing
are Before
and After
. In the previous examples the timing
has been implicitly set to Before
because the handler needed perform actions before your target handler (the one that you decorated). If you set the timing
to After
it only actions after your target handler.
In the example here, the timing is set After
because we want to make sure that the the handler completed correctly before our handler runs. So, if it throws an exception then our heartbeat handler won’t run. If you need to perform an action before and after, then set the timing to Before
, and perform actions before the call to base.Handle()
and after the call.
Our heartbeat handler looks like this:
public class HeartbeatHandler<TRequest> : RequestHandler<TRequest> where TRequest : class, IRequest { public override TRequest Handle(TRequest command) { // We would probably call a heartbeat service at this point. // But for demonstration we'll just write to the console. Console.WriteLine($"Heartbeat pulsed for {command.GetType().FullName}"); string jsonString = JsonConvert.SerializeObject(command); Console.WriteLine(jsonString); return base.Handle(command); } }
The important thing, as will all handlers, is to remember the call to the base.Handle()
which ensures the pipeline is continued.
The target handler decoration looks like this:
[FallbackPolicy(step:1, backstop:true, circuitBreaker:false)] [UsePolicy(policy: "GreetingRetryPolicy", step:2)] [Heartbeat(step:3)] public override SalutationCommand Handle(SalutationCommand command) { // Stuff to handle the command. return base.Handle(command); }
The first two decorators are from previous posts (Retrying Commands and Implementing a fallback exception handler) while the third is our new decorator.
When run, you can see that if the service fails completely (i.e. all the retries failed) then the Heartbeat does not get run. However, if the command succeeds then the heartbeat handler is run. Our APM knows the command succeeded and can display that.
Remember
Remember to wire up the handler, as with all handlers, to your dependency injection framework, so that it can be correctly instantiated:
serviceCollection.AddScoped(typeof(HeartbeatHandler<>));
Recommend
-
139
Javalin 1.2.0 released Custom jetty handlers (Dec 2, 2017) What's Javalin? Javalin is a very lightweight Java and Kotlin web framework which focuses on simplicity and Java/Kotlin in...
-
75
README.md
-
10
The main sell of AWS Lambda (and Functions as as Service in general) is the ability to shift developer attention away from infrastructure to the business logic. Nonetheless, there are a number of cross-cutting concerns t...
-
17
The Russian Doll Model – The Blog of Colin MackayI’ve mentioned a bit about the attributing the handler and the step and timing parameters, but I’ve not explained them properly in previous posts (“
-
6
Retrying Commands – The Blog of Colin MackaySkip to content Paramore Brighter supports Policies to maintain quality...
-
12
Why You Should Avoid Command Handlers Calling Other Commands?One of the patterns that I keep coming back to when building ASP NET Applications is the Command and Query Responsibility Segregation (CQRS) pattern. Fundamentally, the pat...
-
6
# How to create custom handlers for Azure Functions
-
6
Write and configure custom sensu handlers Oct 27, 2017 Sensu is a decent monitoring platform compared to nagios, since the configuration is more flexible (and a lot more config mgmt friendly) and the platform is also eas...
-
5
Running Custom Tasks in jBPM with work item handlersIntroductionYou can use a WorkItemHandler to run custom tasks during the execution of a process in jBPM. In this article, you will run through the steps to create a custom task...
-
6
August 9, 2022 Fun With Custom Interpolated String Handlers ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK