轴突框架中的通用 CommandExecutionException 处理

Generic CommandExecutionException handling in axon framework

我有一个相当简单的 axon 应用程序,我试图将一些通用的“捕获所有”异常处理逻辑应用到该应用程序。

如果我有一个进入聚合的命令会抛出某种异常,例如

class UserAggregate {
    //... 
        
    @CommandHandler()
    public void on(CreateUserCommand cmd) {
       Validate.notNull(cmd.getEmail(), "Email cannot be null");

       //other processing
   }
}

然后当我从 Rest Controller 调用这个命令时,异常与我预期的相去甚远

org.axonframework.commandhandling.CommandExecutionException: Email cannot be null at org.axonframework.axonserver.connector.ErrorCode.lambda$static(ErrorCode.java:88) at org.axonframework.axonserver.connector.ErrorCode.convert(ErrorCode.java:182) at org.axonframework.axonserver.connector.command.CommandSerializer.deserialize(CommandSerializer.java:157) at org.axonframework.axonserver.connector.command.AxonServerCommandBus.onNext(AxonServerCommandBus.java:313) at org.axonframework.axonserver.connector.command.AxonServerCommandBus.onNext(AxonServerCommandBus.java:306) at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onMessage(ClientCalls.java:429) at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33) at io.grpc.ForwardingClientCallListener.onMessage(ForwardingClientCallListener.java:33) at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInternal(ClientCallImpl.java:596) at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplMessagesAvailable.runInContext(ClientCallImpl.java:581)

虽然该消息很有用,但是,这并不总是给定的。这可以在像这样

实现 ExceptionHandler 时得到缓解
@ExceptionHandler
public void handle(Exception exception) {
   log.info("Caught Exception - {}", exception.getMessage(), exception);
}

这现在为我提供了一个堆栈跟踪,指出问题的实际来源,但是,这是以必须在我想调用此命令的任何地方编写这样一个异常处理程序为代价的。

是否有更通用的方法来记录这些异常,而不必在每个 class 发出的命令上强加 ExceptionHandler?

我会向您指出 code-samples 存储库,其中显示了一种使用 MessageHandlerInterceptor.

处理它的方法

引用回购协议本身:

One of the most common ways to indicate that a logical error has occurred and that Command handling failed is to throw an exception from a Command handler. However, if the exception is directly serialized there is no guarantee that the command sending side can properly deserialize the exception in question. That is why by default Axon Framework will wrap any exception thrown inside a Command handler into a CommandExecutionException.

简而言之,您将定义一个MessageHandlerInterceptor负责try-catch命令执行逻辑。在那里你可以集中处理 CommandExecutionException.