```java
 public Result thenApplyWithContext(Function<Result, Result> fn) {
        this.thenApply(fn.compose(beforeContext).andThen(afterContext));
        // You may need to return a new Result instance representing the next async stage,
        // like thenApply will return a new CompletableFuture.
        return this;
    }
```

to

```java
```java
 public Result thenApplyWithContext(BiFunction<Throwable, Result> fn) {
        this.handle(fn);
        // You may need to return a new Result instance representing the next async stage,
        // like thenApply will return a new CompletableFuture.
        return this;
    }
```
```
/**
     * RpcContext may already have been changed when callback happens, it happens when the same thread is used to execute another RPC call.
     * So we should keep the reference of current RpcContext instance and restore it before callback being executed.
     */
    private RpcContext storedContext;
    private RpcContext storedServerContext;
    private Invocation invocation;
    public AsyncRpcResult(Invocation invocation) {
        this.invocation = invocation;
        this.storedContext = RpcContext.getContext();
        this.storedServerContext = RpcContext.getServerContext();
    }
    public AsyncRpcResult(AsyncRpcResult asyncRpcResult) {
        this.invocation = asyncRpcResult.getInvocation();
        this.storedContext = asyncRpcResult.getStoredContext();
        this.storedServerContext = asyncRpcResult.getStoredServerContext();
    }
    /**
     * Notice the return type of {@link #getValue} is the actual type of the RPC method, not {@link AppResponse}
     *
     * @return
     */
    @Override
    public Object getValue() {
        return getAppResponse().getValue();
    }
    @Override
    public void setValue(Object value) {
        AppResponse appResponse = new AppResponse();
        appResponse.setValue(value);