Axon 服务器的 Axon 查询返回列表
Axon query returning list with Axon Server
我们有一个应用程序,我们试图从仅使用 Axon Framework 转变为也使用 Axon Server。我们遇到了一个问题,即查询响应(一种类型的多个实例)无法正确传输。当服务器未被使用时,不会出现下面详述的问题。
我们正在发送一个查询并期待一个特定类型的列表作为响应。
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 正在生成和处理查询。
我相信正在发生的事情是查询处理程序正在 returning List<MyResponse>
并且框架正在正常调用 MultipleInstancesResponseType#convert(Object)
。然后将响应序列化(gRPC?)并发送到服务器,然后服务器将响应发送给原始调用者。原始调用者然后尝试转换有效负载,但失败了。所以,在 gRPC serialization/deserialization 进程的某个地方,一些类型信息已经丢失。
最终结果是原始调用者得到 IllegalArgumentException
声明
Retrieved response [class java.util.ArrayList] is not convertible to a List of the expected response type [class MyResponse]
在 GrpcPayloadSerializer
上设置断点表明响应负载在序列化以发送到服务器时正确地是 List<MyResponse>
.
documentation 似乎明确表示 List<of-something>
是受支持的查询处理程序 return 类型。
原来这是因为我们使用了 JacksonSerializer
作为消息。如果我们更改为 XStreamSerializer
那么一切都会按预期进行。
我想这是 Jackson 生成的 JSON 文档不包含类型信息的结果,反序列化结束不知道预期的查询 return 类型。
因此,如果您使用的是 Axon 服务器,则对您的消息使用 XStream 或 Java 序列化可能是个好主意。
正如@ptomli 已经发现的那样,这更像是杰克逊的问题,而不是 Axon。
但除此之外,AxonFramework 在 this PR 上为此提供了修复。它尚未发布(我相信它将成为 4.4 版本的一部分)但您可以自己查看解决方案以编写自己的解决方法或等待提到的版本。
我们有一个应用程序,我们试图从仅使用 Axon Framework 转变为也使用 Axon Server。我们遇到了一个问题,即查询响应(一种类型的多个实例)无法正确传输。当服务器未被使用时,不会出现下面详述的问题。
我们正在发送一个查询并期待一个特定类型的列表作为响应。
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 正在生成和处理查询。
我相信正在发生的事情是查询处理程序正在 returning List<MyResponse>
并且框架正在正常调用 MultipleInstancesResponseType#convert(Object)
。然后将响应序列化(gRPC?)并发送到服务器,然后服务器将响应发送给原始调用者。原始调用者然后尝试转换有效负载,但失败了。所以,在 gRPC serialization/deserialization 进程的某个地方,一些类型信息已经丢失。
最终结果是原始调用者得到 IllegalArgumentException
声明
Retrieved response [class java.util.ArrayList] is not convertible to a List of the expected response type [class MyResponse]
在 GrpcPayloadSerializer
上设置断点表明响应负载在序列化以发送到服务器时正确地是 List<MyResponse>
.
documentation 似乎明确表示 List<of-something>
是受支持的查询处理程序 return 类型。
原来这是因为我们使用了 JacksonSerializer
作为消息。如果我们更改为 XStreamSerializer
那么一切都会按预期进行。
我想这是 Jackson 生成的 JSON 文档不包含类型信息的结果,反序列化结束不知道预期的查询 return 类型。
因此,如果您使用的是 Axon 服务器,则对您的消息使用 XStream 或 Java 序列化可能是个好主意。
正如@ptomli 已经发现的那样,这更像是杰克逊的问题,而不是 Axon。
但除此之外,AxonFramework 在 this PR 上为此提供了修复。它尚未发布(我相信它将成为 4.4 版本的一部分)但您可以自己查看解决方案以编写自己的解决方法或等待提到的版本。