使用@Exceptionhandler 捕获消息处理异常
Catching Message Handling Exceptions with the @Exceptionhandler
我有两个申请 e.g) A, B
A有一个Saga
B 只是网络应用程序
A 向 B 发送了命令消息,并且
B 将该命令的异常发送给 A 的 Saga,A 的 Saga 收到良好
B 有一个 @ExceptionHandler
,我希望它能被调用,但它不起作用
如何调用它们?
编辑
这是A应用的向B应用发送命令消息的Saga
并处理 B 发送的异常
@Saga
public class OrderSaga {
@Autowired
private transient CommandGateway commandGateway;
@StartSaga
@SagaEventHandler(associationProperty = "orderId")
public void handle(CreateOrderEvent evt) {
String paymentId = UUID.randomUUID().toString();
SagaLifecycle.associateWith("paymentId", paymentId);
commandGateway.send(new CreatedPaymentCommand(paymentId, evt.getUserId(),evt.getFoodPrice())).exceptionally(exp -> {
System.out.println("got it");
System.out.println(exp.getMessage());
return null;
});
}
}
这是为测试抛出异常的 B 应用程序
@Aggregate
@NoArgsConstructor
public class PaymentAggregate {
@AggregateIdentifier
private String paymentId;
private String userId;
private PaymentStatus status;
@CommandHandler
public PaymentAggregate(CreatedPaymentCommand cmd) {
throw new IllegalStateException("this exception was came from payment aggregates");
// AggregateLifecycle.apply(new CreatedPaymentEvent(cmd.getPaymentId(),
// cmd.getUserId(),cmd.getMoney()));
}
@ExceptionHandler(resultType = IllegalStateException.class)
public void error(IllegalStateException exp) {
System.out.println(exp.getMessage());
}
// I want this @ExceptionHandler to be invoked
@EventSourcingHandler
public void on(CreatedPaymentEvent evt) {
this.paymentId = evt.getPaymentId();
this.userId = evt.getUserId();
}
}
应用程序捕获异常如下所示
2021-08-24 11:46:43.534 WARN 14244 --- [ault-executor-2] o.a.c.gateway.DefaultCommandGateway : Command 'com.common.cmd.CreatedPaymentCommand' resulted in org.axonframework.commandhandling.CommandExecutionException(this exception was came from payment aggregates)
got it
this exception was came from payment aggregates
但 B 不是我认为 B 的 @ExceptionHandler 会捕获该异常
简而言之,如何让 B 的 @ExceptionHandler 被调用
它现在不起作用,因为异常是从聚合的构造函数中抛出的。
当您使用构造函数命令处理程序时,还没有实例存在。
如果没有实例,Axon Framework 无法识别您设置的 @ExceptionHandler
注释方法。
这是现阶段异常处理程序的唯一缺失点。老实说,参考指南应该对此更具体一些。不过,我相信这会在未来发生变化。
有一种不同的方法可以让命令处理程序构造可以使用 @ExceptionHandler
: 和 @CreationPolicy
注释的聚合 和 。参考指南有 this 顺便说一下。
因此,您可以使用 AggregateCreationPolicy.ALWAYS
设置常规命令处理程序,而不是使用构造函数命令处理程序。
这将像这样调整您的样本:
@Aggregate
@NoArgsConstructor
public class PaymentAggregate {
@AggregateIdentifier
private String paymentId;
private String userId;
private PaymentStatus status;
@CommandHandler
@CreationPolicy(AggregateCreationPolicy.ALWAYS)
public void handle(CreatedPaymentCommand cmd) {
throw new IllegalStateException("this exception was came from payment aggregates");
// AggregateLifecycle.apply(new CreatedPaymentEvent(cmd.getPaymentId(),
// cmd.getUserId(),cmd.getMoney()));
}
@ExceptionHandler(resultType = IllegalStateException.class)
public void error(IllegalStateException exp) {
System.out.println(exp.getMessage());
}
// I want this @ExceptionHandler to be invoked
@EventSourcingHandler
public void on(CreatedPaymentEvent evt) {
this.paymentId = evt.getPaymentId();
this.userId = evt.getUserId();
}
}
@YongD,请在您的应用程序中尝试一下。
我有两个申请 e.g) A, B
A有一个Saga B 只是网络应用程序
A 向 B 发送了命令消息,并且 B 将该命令的异常发送给 A 的 Saga,A 的 Saga 收到良好
B 有一个 @ExceptionHandler
,我希望它能被调用,但它不起作用
如何调用它们?
编辑
这是A应用的向B应用发送命令消息的Saga 并处理 B 发送的异常
@Saga
public class OrderSaga {
@Autowired
private transient CommandGateway commandGateway;
@StartSaga
@SagaEventHandler(associationProperty = "orderId")
public void handle(CreateOrderEvent evt) {
String paymentId = UUID.randomUUID().toString();
SagaLifecycle.associateWith("paymentId", paymentId);
commandGateway.send(new CreatedPaymentCommand(paymentId, evt.getUserId(),evt.getFoodPrice())).exceptionally(exp -> {
System.out.println("got it");
System.out.println(exp.getMessage());
return null;
});
}
}
这是为测试抛出异常的 B 应用程序
@Aggregate
@NoArgsConstructor
public class PaymentAggregate {
@AggregateIdentifier
private String paymentId;
private String userId;
private PaymentStatus status;
@CommandHandler
public PaymentAggregate(CreatedPaymentCommand cmd) {
throw new IllegalStateException("this exception was came from payment aggregates");
// AggregateLifecycle.apply(new CreatedPaymentEvent(cmd.getPaymentId(),
// cmd.getUserId(),cmd.getMoney()));
}
@ExceptionHandler(resultType = IllegalStateException.class)
public void error(IllegalStateException exp) {
System.out.println(exp.getMessage());
}
// I want this @ExceptionHandler to be invoked
@EventSourcingHandler
public void on(CreatedPaymentEvent evt) {
this.paymentId = evt.getPaymentId();
this.userId = evt.getUserId();
}
}
应用程序捕获异常如下所示
2021-08-24 11:46:43.534 WARN 14244 --- [ault-executor-2] o.a.c.gateway.DefaultCommandGateway : Command 'com.common.cmd.CreatedPaymentCommand' resulted in org.axonframework.commandhandling.CommandExecutionException(this exception was came from payment aggregates)
got it
this exception was came from payment aggregates
但 B 不是我认为 B 的 @ExceptionHandler 会捕获该异常
简而言之,如何让 B 的 @ExceptionHandler 被调用
它现在不起作用,因为异常是从聚合的构造函数中抛出的。
当您使用构造函数命令处理程序时,还没有实例存在。
如果没有实例,Axon Framework 无法识别您设置的 @ExceptionHandler
注释方法。
这是现阶段异常处理程序的唯一缺失点。老实说,参考指南应该对此更具体一些。不过,我相信这会在未来发生变化。
有一种不同的方法可以让命令处理程序构造可以使用 @ExceptionHandler
: 和 @CreationPolicy
注释的聚合 和 。参考指南有 this 顺便说一下。
因此,您可以使用 AggregateCreationPolicy.ALWAYS
设置常规命令处理程序,而不是使用构造函数命令处理程序。
这将像这样调整您的样本:
@Aggregate
@NoArgsConstructor
public class PaymentAggregate {
@AggregateIdentifier
private String paymentId;
private String userId;
private PaymentStatus status;
@CommandHandler
@CreationPolicy(AggregateCreationPolicy.ALWAYS)
public void handle(CreatedPaymentCommand cmd) {
throw new IllegalStateException("this exception was came from payment aggregates");
// AggregateLifecycle.apply(new CreatedPaymentEvent(cmd.getPaymentId(),
// cmd.getUserId(),cmd.getMoney()));
}
@ExceptionHandler(resultType = IllegalStateException.class)
public void error(IllegalStateException exp) {
System.out.println(exp.getMessage());
}
// I want this @ExceptionHandler to be invoked
@EventSourcingHandler
public void on(CreatedPaymentEvent evt) {
this.paymentId = evt.getPaymentId();
this.userId = evt.getUserId();
}
}
@YongD,请在您的应用程序中尝试一下。