我们有一个应用程序,我们试图从仅仅使用Axon框架转移到同时使用Axon服务器。我们遇到了一个问题,查询响应是一个类型的多个实例,无法正确地传输。以下详细说明的问题在服务器未被使用时不会发生。
我们发送一个查询,并期待一个特定类型的列表作为响应。
queryGateway.query(new MyQuery(...), ResponseTypes.multipleInstancesOf(MyResponse.class));
// elsewhere
@QueryHandler
public List<MyResponse> handle(MyQueryquery) {
return List.of(new MyResponse(...));
}在没有服务器的情况下运行时,工作正常。令人感兴趣的是,MultipleInstancesResponseType#convert(Object)只被调用一次,参数是List<MyResponse>实例。这里不需要转换。
当在服务器上运行时,MultipleInstancesResponseType#convert(Object)会被调用两次。第一次,如前所述,参数是预期的List<MyResponse>,同样,不需要转换。但是,将再次调用MultipleInstancesResponseType#convert(Object),参数为List<LinkedHashMap>。这需要转换,这是失败的,因为List<MyResponse>不能转换为List<MyResponse>。
我在调试器中看到了两个convert调用,因为在我的测试中,相同的JVM同时进行和处理查询。
我相信正在发生的事情是,查询处理程序正在返回List<MyResponse>,而框架按照正常情况调用MultipleInstancesResponseType#convert(Object)。然后对响应进行序列化(gRPC?)并发送到服务器,然后服务器将响应发送给原始调用方。然后,原始调用方尝试转换有效负载,但失败。因此,在gRPC序列化/反序列化过程中,某些类型信息已经丢失。
最终的结果是,原始调用方将获得一个IllegalArgumentException语句
检索到的响应类java.util.ArrayList不能转换为预期响应类型MyResponse的列表。
在GrpcPayloadSerializer上设置一个断点表明,在将响应有效负载序列化到服务器时,它正确地是一个List<MyResponse>。
文档似乎清楚地表明,List<of-something>是一个受支持的查询处理程序返回类型。
发布于 2020-05-28 07:31:33
正如@ptomli已经发现的,这更像是杰克逊的问题,而不是Axon的问题。
但为了补充这一点,AxonFramework在这个公关上提供了一个修复程序。它还没有发布(我相信它将是4.4版本的一部分),但是您可以自己查看解决方案,编写自己的解决方案,或者等待上述版本的发布。
发布于 2020-05-27 15:18:41
事实证明,这是由于我们使用JacksonSerializer的消息。如果我们更改为XStreamSerializer,那么一切都按预期的方式工作。
我认为这是JSON文档Jackson生成的不包含类型信息的结果,反序列化end不知道预期的查询返回类型。
因此,如果您使用的是Axon,那么对您的消息使用XStream或可能是一个主意。
https://stackoverflow.com/questions/62045461
复制相似问题