如何处理Java 8 CompletableFuture中的错误?
我正试图在Java中的WebSocket上实现一个简单的类似RPC(或请求-响应)的系统(前端将有JS,但现在我正在后端工作) 我正在尝试应用Java如何处理Java 8 CompletableFuture中的错误?,java,multithreading,concurrency,java-8,completable-future,Java,Multithreading,Concurrency,Java 8,Completable Future,我正试图在Java中的WebSocket上实现一个简单的类似RPC(或请求-响应)的系统(前端将有JS,但现在我正在后端工作) 我正在尝试应用JavaCompletableFuture模式来处理异步发送消息。但我现在被错误处理所困扰 我有一个类(我们称之为rpc类),负责通过WebSocket会话发送消息(这里使用SpringWebSocket支持类),然后等待“回复”类型的消息,并将它们与挂起的请求相匹配,并将内容返回给调用者 流程是: 客户端代码调用rpc类上的方法,指定要在远程进程上调用
CompletableFuture
模式来处理异步发送消息。但我现在被错误处理所困扰
我有一个类(我们称之为rpc类),负责通过WebSocket会话发送消息(这里使用SpringWebSocket支持类),然后等待“回复”类型的消息,并将它们与挂起的请求相匹配,并将内容返回给调用者
流程是:
- 客户端代码调用rpc类上的方法,指定要在远程进程上调用的过程的名称、要将消息发送到的会话以及要发送的参数映射
- rpc类使用另一个较低级别的类使用
执行器(线程池)异步发送消息,并接收“发送消息”操作的
CompletableFuture
- 它将挂起的请求存储在映射中,构建一个
,并将其与挂起的请求关联,然后将它们存储在映射中。它返回可完成的未来CompletableFuture
- 当收到“reply”类型的消息时,在同一类上调用一个方法,该方法尝试将响应与一个挂起的请求(它们对此有一个ID)匹配,然后使用响应中接收的内容完成
CompletableFuture
completableFuture
也失败(或者可能实施重试策略和超时
以下是发送消息的rpc类方法的代码:
/**
* Invoke a remote procedure over WS on the specified session, with the given arguments.
* @param session The target session on which to send the RPC message
* @param target The name of the procedure to call
* @param arguments The arguments to be sent in the message
* @return
*/
public CompletableFuture<Map<String,Object>> invoke(WebSocketSession session, String target, Map<String, Object> arguments){
Invocation invocationMessage = new Invocation(target, arguments);
invocationMessage.setId(getNextId());
// completeable future for the result. It does nothing, will be completed when reply is received which happen in a different thread, see completeInvocation
CompletableFuture<Map<String, Object>> invocationFuture = new CompletableFuture<>();
CompletableFuture<Void> senderFuture = sender.sendMessage(session, invocationMessage);
// handle problem in the sending of the message
senderFuture.exceptionally(e -> {
// is this correct ??
invocationFuture.completeExceptionally(e);
return null;
});
// store the pending invocation in the registry
registry.addPendingInvocation(new PendingInvocation(invocationMessage, session, invocationFuture));
// return the future so the caller can have access to the result once it is ready
return invocationFuture;
}
/**
*在指定会话上使用给定参数通过WS调用远程过程。
*@param session发送RPC消息的目标会话
*@param target要调用的过程的名称
*@param arguments消息中要发送的参数
*@返回
*/
公共CompletableFuture调用(WebSocketSession会话、字符串目标、映射参数){
调用调用消息=新调用(目标、参数);
调用message.setId(getNextId());
//结果的可完成未来。它不做任何事情,当在不同线程中收到回复时将完成,请参阅completeInvocation
CompletableFuture invocationFuture=新的CompletableFuture();
CompletableFuture senderFuture=sender.sendMessage(会话,调用消息);
//处理发送消息时出现的问题
发件人未来。例外(e->{
//这是正确的吗??
除(e)项外,完成;
返回null;
});
//将挂起的调用存储在注册表中
addPendingJournal(新的PendingJournal(调用消息、会话、调用未来));
//返回future,以便调用者可以在结果准备好后访问它
回归未来;
}
最简单的方法是使用然后组合()
简单地链接期货:
//结果的可完成未来。它什么也不做,在收到回复时会完成,这发生在不同的线程中,请参阅completeInvocation
CompletableFuture invocationFuture=新的CompletableFuture();
CompletableFuture senderFuture=sender.sendMessage(会话,调用消息);
//将挂起的调用存储在注册表中
addPendingJournal(新的PendingJournal(调用消息、会话、调用未来));
//返回future,以便调用者可以在结果准备好后访问它
返回senderFuture.thencomose(\uuuu->invocationFuture);
如果异常完成了发送者未来
,则返回的未来也将异常完成,完成异常
将异常作为其原因(c.f.)
请注意,您可能还需要解决其他问题:
- 如果出现异常,您不应该取消挂起的调用吗
- 如果响应在调用
之前到达,会发生什么情况?您不应该在调用addPendingJournal
之前调用它以避免出现问题吗sendMessage
- 既然您不使用
做任何事情,那么在invocationFuture
中创建它不是更好吗addpenidnginaction
// completeable future for the result. It does nothing, will be completed when reply is received which happen in a different thread, see completeInvocation
CompletableFuture<Map<String, Object>> invocationFuture = new CompletableFuture<>();
CompletableFuture<Void> senderFuture = sender.sendMessage(session, invocationMessage);
// store the pending invocation in the registry
registry.addPendingInvocation(new PendingInvocation(invocationMessage, session, invocationFuture));
// return the future so the caller can have access to the result once it is ready
return senderFuture.thenCompose(__ -> invocationFuture);