Search code examples
javaspringasynchronouscallbackapollo

How can I get a hold of the argument of an asynchronous callback 'onResponse'?


I'm implementing a GraphQL client in a Java application using Apollo's auto generation of queries, and so far I've been able to chain calls and I also get the data I want. The issue is that Apollo makes me implement the anonymous method ApolloCall.Callback<>() which overrides void onResponse(Response response) and void onFailure(), but I'm unable to find a way to get a hold of this Response object, which I want to collect and make sure I have.

This is a Spring Boot project on Java 11, I've tried to make use of CompletableFuture but with limited knowledge of it and how to use it for this particular problem I feel out of luck. I've also tried to implement the RxJava support that Apollo is supposed to have but I couldn't resolve dependency issues with that approach.

I'm pretty sure that futures will solve it but again I don't know how.

  public void getOwnerIdFromClient() {
    client
        .query(getOwnerDbIdQuery)
        .enqueue(
            new ApolloCall.Callback<>() {
              @Override
              public void onResponse(@Nonnull Response<Optional<GetOwnerDbIdQuery.Data>> response) {
                int ownerId =
                    response
                        .data()
                        .get()
                        .entities()
                        .get()
                        .edges()
                        .get()
                        .get(0)
                        .node()
                        .get()
                        .ownerDbId()
                        .get();

                System.out.println("OwnerId = " + ownerId);
              }

              @Override
              public void onFailure(@Nonnull ApolloException e) {
                logger.error("Could not retrieve response from GetOwnerDbIdQuery.", e);
              }
            });
  }

Since I wish to work with this int ownerId outside of the onResponse this isn't a sufficient solution. I'd actually like to make this call x amount of times, and create a list of all the id's I actually got, since this might return a null id as well, which means I need some way to wait for them all to finish.


Solution

  • You are right, this can be done using Futures:

    • change return type to Future
    • complete the future in onResponse

    Approximately:

    public Future<Integer> getOwnerIdFromClient(){
        Future<Integer> result=new CompletableFuture<Integer>();
    
        client
        .query(getOwnerDbIdQuery)
        .enqueue(
        new ApolloCall.Callback<>(){
            @Override
            public void onResponse(@Nonnull Response<Optional<GetOwnerDbIdQuery.Data>>response){
                    // get owner Id
                    System.out.println("OwnerId = "+ownerId);
                    result.complete(ownerId)
                    }
    
            @Override
            public void onFailure(@Nonnull ApolloException e){
                    logger.error("Could not retrieve response from GetOwnerDbIdQuery.",e);result.completeExceptionally(e);
    
    
                    }
            });
    
        return result;
    

    }