-
Notifications
You must be signed in to change notification settings - Fork 11
HandlerDescription
Starting with v3.0.0 the saga-lib provides an alternative way to define the messages being handled by a single saga. If one does not want to use annotations it's possible to implement DescribesHandlers
and provide a description directly. The HandlerDescriptions
utility class is there to help with this task.
A description definition is started by first defining the starting message using the static startedBy method followed by the actual handler. From this point forward any number of additional messages and handlers can added to the description.
public class DirectDescriptionSaga extends AbstractSaga<MySagaState>
implements DescribesHandlers {
private void startingSaga(final IncomingRequest startingMessage) {
// start logic [..]
}
private void finishSaga(final SytemResponse response) {
// finish logic [...]
setFinished();
}
@Override
public HandlerDescription describeHandlers() {
return HandlerDescriptions
.startedBy(IncomingRequest.class).usingMethod(this::startingSaga)
.handleMessage(SystemResponse.class).usingMethod(this::finishSaga)
.finishDescription();
}
// key readers and state creation [...]
}
The main advantage here is that no reflection is involved. One can not forget an annotation or use the wrong method signature or type. Another "hidden" benefit is the fact that in case of an exception the call stack is no longer split up with an InvocationTargetException.
There are additional helpers in the form of the AbstractHandler and AbstractAutoTypedHandler classes. Those two provide a simple way to implement sagas with no state which are automatically finished. In comparison to the AbstractSingleEventSaga no annotation is necessary and the handler method is automatically created for you.
public class MyMessageHandler extends AbstractAutoTypedHandler<MyMessage> {
@Override
public void handle(final MyMessage message) {
// do something based on the message
}
}
The AbstractHandler is similar to the AbstractAutoTypedHandler but it requires the generic argument type instance as constructor argument as well. This results in better performance (no reflection necessary to determine the generic type) at the cost of having to write the type twice.
The JMH test suite (provided in this repo) showed a difference of about 1µs between the two forms of handlers. This may not sound much. However, the tests show that the whole saga-lib messaging mechanic itself takes as well about 1µs. This means the message throughput is halved by using the AbstractAutoTypedHandler. Depending on the environment and the work done in the handlers (database access, network IO, ...), one microsecond might be a lot or negligible.
That's the reason both handler implementations are provided to choose from.