Search code examples
vert.xvertx-verticlevertx-httpclient

Vertx java - sequencing code using compose


I have a logic where I need to save data in two tables(one-to-many). I have created two methods in my Java and I am trying to using Vertx Future with compose to implement the logic in sequence. But I have got half way and don't understand how to implement the compose when the first future is done. I mean code runs for the first future anAsyncAction_1(materialToAdd);, and the record is saved in the DB but now how do I call my second method in the compose

public Future<Void> anAsyncAction_2(final SendToCompanyFromSupplier rawmaterialToAdd, Integer id)
{
    //code to get the id from the first future and save data in the table
}

Below is my code

public Future<Void> adddetails(final Supplier materialToAdd)
    {
        final Promise<Void> added = Promise.promise();
        
        Future<Integer> fut1 = anAsyncAction_1(materialToAdd);
        
        LOG.debug(" future.result()  "+fut1.result());
        
        fut1.compose((outcome) -> {
            LOG.debug(" future.result()  "+outcome);
             
        });

        CompositeFuture.all(fut1, fut2).onComplete(ar ->
        {
            System.out.println("BOTH OPERATION COMPLETED!! 1 " + ar.succeeded());
            try
            {
                System.out.println("BOTH OPERATION COMPLETED!! 2 " + ar.result().list());
                added.complete();
                System.out.println("BOTH OPERATION COMPLETED!!");
            } catch (Exception e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        });

        return added.future();

    }

Solution

  • If you just want to compose both the futures, the implementation can be simplified without using CompositeFuture or Promise.

    Sample code:

    public Future<Void> adddetails(final Object materialToAdd) {
        Object rawMaterialToAdd = new Object();
    
        return anAsyncAction_1(materialToAdd).compose(i -> anAsyncAction_2(rawMaterialToAdd, i))
                                             .onComplete(ar -> {
                                               if (ar.succeeded()) {
                                                 System.out.println("Both operations completed");
                                               } else {
                                                 ar.cause()
                                                   .printStackTrace();
                                               }
                                             });
    
    
      }
    
      private Future<Integer> anAsyncAction_1(Object materialToAdd) {
        Promise<Integer> promise = Promise.promise();
        Vertx.currentContext()
             .runOnContext(v -> promise.complete(1)); //Async Call. Replace with async DB call 1
        return promise.future();
      }
    
      public Future<Void> anAsyncAction_2(final Object rawmaterialToAdd, Integer id) {
        Promise<Void> promise = Promise.promise();
        Vertx.currentContext()
             .runOnContext(v -> {
               System.out.println("Id received:" + id);
               promise.complete();
             }); //Async Call. Replace it with the async DB call 2
        return promise.future();
      }
    

    Below is the sequence

    1. Async DB call within anAsyncAction_1 will complete. The id returned will be used to complete the promise. The promise will inturn complete the first future.
    2. The future will trigger anAsyncAction_2 with the id. Async DB call 2 on completion will complete the second future. Post the second future completion the onComplete handlers will be executed.