Axon @QueryHandler与Spring @ExceptionHandler

时间:2019-02-08 08:19:03

标签: spring axon

使用注解为Spring @ResponseStatus的Axon @QueryHandler中引发的异常时遇到麻烦。原始异常被QueryHandler吞没,并且特定于Axon的AxonServerRemoteQueryHandlingException被抛出,当spring响应客户端时实际上会给出500。

仍然有可能从Axon异常中获取一些信息,例如原始的“找不到实体”消息,但没有异常类型,也没有原始异常所保存的其他任何信息。

Q1:有什么方法可以将在查询处理程序中引发的异常提升为404的Spring响应

Spring异常处理程序

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class NotFoundException extends ServiceException() {
  ...
}

轴突查询处理程序

@QueryHandler
public Application getApplicationById(ApplicationByIdQuery query) {
  return applicationRepository.findById(query.getId())
      .orElseThrow(() -> new NotFoundException(Application.class, query.getId()));
}

弹簧控制器

@Autowired
QueryGateway queryGateway;

@GetMapping(path = "/{applicationId}")
public CompletableFuture<Application> getApplication(@PathVariable String applicationId) {
  return queryGateway.query(new ApplicationByIdQuery(applicationId), ResponseTypes.instanceOf(Application.class));
}

实际结果json:

{
  "timestamp": "2019-02-08T08:04:03.629+0000",
  "status": 500,
  "error": "Internal Server Error",
  "message": "An exception was thrown by the remote message handling component.",
  "path": "/api/applications/dff59c46-baf1-40f5-8a21-9286d1f8e36fx"
}

Q2:我的另一个问题是,为什么不直接使用常规的JPA Query API,而是使用Axon的QueryHandler。投影表是常规的JPA表,可以通过功能非常强大的Spring JPA进行质疑。是因为直接查询不能确保投影数据的一致性?我浏览了许多示例,其中大多数使用直接访问(请参见下面的内容),其余示例无法解决底层QueryHandler引发的异常

@Autowired
ApplicationRepository applicationRepository;

public CompletableFuture<Application> getApplication(@PathVariable String applicationId) {
  return CompletableFuture.supplyAsync(() -> applicationRepository.findById(applicationId)
                .orElseThrow(() -> new NotFoundException(Application.class, applicationId)));   
}

1 个答案:

答案 0 :(得分:3)

希望我能在这个领域为您提供一些建议。

问题1的答案:

Axon Server将始终将命令,事件或查询的调度/处理异常包装到其他内容中。

因此,如果您想对远程查询处理异常有条件地做出反应,我认为您必须在代码中添加一个带有@ExceptionHandler(AxonServerRemoteQueryHandlingException.class)注释的函数。 AxonServerRemoteQueryHandlingException包含有关其包装的异常的更多信息,从而在必要时为您提供发送特定响应的句柄。

但是,包装的异常的格式目前尚不理想。从Axon Framework / Server 4.1开始,该计划也将包含异常中的类。在处理异常时,这将使您更轻松,更精细地进行控制。

问题2的答案:

使用专用查询消息和查询处理程序的想法是,您可以将对某些数据感兴趣的一方与实现答案的方式脱钩。

在框架中拥有专用的QueryBus@QueryHandler解决方案之前,您所建议的是唯一的选择。 但是,为此使用专用查询消息的概念使您能够拥有一个完全独立的(微型)服务来回答您的查询,而无需查询发送者知道该服务在哪里。

在Axon应用程序中利用查询和查询处理程序是为您提供“ Location Transparency”的支柱之一。您完全可以不使用框架提供的查询逻辑,但是我个人认为这是进化微服务的强大推动力。

希望这可以帮助您解决Tomáš!