Using a response from an actor in current actor process

I am confused about how I should resolve this scenario in a non-blocking manner.

Consider two actors Actor1 and Actor2

Within Actor1

Map<Int, Int> foo() {
     List<String> finalList = foo_2();
     Map<Int, Int> finalMap = // do stuff with finalList to get Map<Int, Int>;

     return finalMap;
}

List<String> foo_2() {
    
     CompletableFuture<List<String>> Querylist = ask(Actor2)
     Querylist.get();
     
     return QueryList;
}

Currently within foo_2, Querylist.get() is a blocking call. I want to somehow resolve this in a non-blocking manner. I created a message adapter for Actor2 inside Actor1 so any messages that Actor2 sends will be handled by Actor1.

I used the following approach to modify the blocking call

Map<Int, Int> foo() {
     CompletionStage<List<String>> finalList = foo_2();
     finalList.whenComplete(
        // what to do here? 
     )
     // Map<Int, Int> finalMap = // do stuff with finalList to get Map<Int, Int>;

     return finalMap;
}

CompletionStage<List<String>> foo_2() {
    
     CompletionStage<List<String>> Querylist = ask(Actor2)
     
     
     return QueryList;
}

I am not sure how to correctly use the CompletionStage construct to get the same result I was getting with a blocking futures.get() call.

Answer

If you’re using Akka Typed (implied from the tag), you shouldn’t need a future or a message adapter at all. Just use ActorContext.ask.

See the documentation for request-response with ask between two actors.

Broadly, you’d get rid of the foo and foo_2 methods, move the message adapter you’ve set up into the ActorContext.ask call, and replace the instances where you’ve previously called foo with a call to ActorContext.ask. If the reply your actor sends to the message which led to the ask depends on the response to the ask, then a good practice is to embed the required portions of state into the message the adapter generates.