[英]How to handle errors in Java 8 CompletableFuture?
I am trying to implement a simple RPC-like (or request-response) system over WebSockets in Java (there will be JS on the front-end but I am working on the back-end for now). 我试图在Java上用WebSockets实现一个简单的类RPC(或请求 - 响应)系统(前端会有JS,但我现在正在后端工作)。
I am trying to apply the Java CompletableFuture
pattern to handle sending messages asynchronously. 我正在尝试应用Java
CompletableFuture
模式来异步处理发送消息。 But I am currnently stuck on error handling. 但我一直坚持错误处理。
I have a class (let's call it the rpc class) that is responsible to send the message over a WebSocket session (using Spring WebSocket support classes here), then to wait for "reply" type messages, and matches them with the pending request and returning the content to the caller. 我有一个类(让我们称之为rpc类)负责通过WebSocket会话发送消息(在这里使用Spring WebSocket支持类),然后等待“回复”类型的消息,并将它们与待处理的请求进行匹配。将内容返回给调用者。
The flow is : 流程是:
Executor
(thread pool), and receives a CompletableFuture<Void>
for the "send the message" operation Executor
(线程池)异步发送消息,并接收CompletableFuture<Void>
以执行“发送消息”操作 CompletableFuture<Map<String, Object>>
and associates it with the pending request, and stores them in a map. CompletableFuture<Map<String, Object>>
并将其与挂起的请求相关联,并将它们存储在映射中。 It returns the completable future. CompletableFuture
with the content received in the response. CompletableFuture
。响应。 So there are 3 threads involved : the caller thread, the thread that sends the message, and the thread that receives the message and completes the future. 因此涉及3个线程:调用者线程,发送消息的线程,以及接收消息并完成未来的线程。
Now, how should I handle an error in the sending of the message (eg IO error) in order to make the returned completableFuture
also fail (or maybe implement a retry strategy, and a time out...) ? 现在,我应该如何处理发送消息中的错误(例如IO错误)以使返回的
completableFuture
也失败(或者可能实现重试策略,以及超时......)?
Here is the code of the rpc class method that sends the message : 以下是发送消息的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;
}
The simplest way to do it would be to simply chain the futures using thencompose()
: 最简单的方法是使用
thencompose()
简单地链接期货:
// 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);
In case of exceptional completion of senderFuture
, the returned future will be completed exceptionally as well, with a CompletionException
holding the exception as its cause (cf CompletionStage
api ). 在
senderFuture
异常完成的情况下,返回的future也将异常CompletionException
, CompletionException
将异常作为其原因(cf CompletionStage
api )。
Note that there are other concerns you might want to tackle as well: 请注意,您可能还需要解决其他问题:
addPendingInvocation
is called? addPendingInvocation
之前响应到达会发生什么? Shouldn't you call it before calling sendMessage
to avoid issues? sendMessage
之前调用它来避免问题吗? invocationFuture
, wouldn't it be better to create it inside addPenidngInvocation
? invocationFuture
做任何事情,那么在addPenidngInvocation
创建它会不会更好?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.