title: How to parallel execute multiple database calls using spring?
body: <p>I am trying to improve the performance of the spring applications which invokes about 8-10 queries and combined it will take about 15 to 120 seconds depending on the amount of data it queries for, i'm proposing a CompletableFuture / Future way of doing it in the Java 8. But, i have been stuck at the point where the main thread does not wait for the async threads to be completed. Thefollowing is the code which I have implemented so far.</p>
  
  <p>I've contemplated to go back and implement it using the 'Future' and ThreadPoolExecutor and have a thread that waits for the completion of the spawned callable threads in the threadPoolExecutor to return the data. </p>
  
  <p><strong>Question:</strong> Any easy way to implement the CompletableFuture in java and the main thread waits for all the threads in the thread pool to be completed before returning the data to the client? </p>
  
  <p><strong>InvokeCallable .java</strong></p>
  
  <pre><code>package net.sampleSpring.service;
  
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.context.ApplicationContext;
  import org.springframework.stereotype.Component;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.CompletableFuture;
  import java.util.concurrent.ExecutionException;
  import java.util.function.Supplier;
  
  @Component
  public class InvokeCallable {
  
      @Autowired
      private ApplicationContext context;
  
  //    @Autowired
  //    @Qualifier("threadPoolExecutor")
  //    private ThreadPoolTaskExecutor executorThreadPool;
  
  
      public void invokeCallables() throws InterruptedException, ExecutionException {
          List&lt;CompletableFuture&lt;Integer&gt;&gt; lst = new ArrayList&lt;&gt;();
          CallableOne callableOne = context.getBean(CallableOne.class);
          CallableTwo callableTwo = context.getBean(CallableTwo.class);
  
          CompletableFuture&lt;Integer&gt; completableFuture1 = CompletableFuture.supplyAsync(new Supplier&lt;Integer&gt;() {
                                                                                            @Override
                                                                                            public Integer get() {
                                                                                                try {
                                                                                                    return callableOne.call();
                                                                                                } catch (Exception e) {
                                                                                                    e.printStackTrace();
                                                                                                }
                                                                                                return 1;
                                                                                            }
                                                                                        }
          );
  
          CompletableFuture&lt;String&gt; completableFuture2 = CompletableFuture.supplyAsync(new Supplier&lt;String&gt;() {
                                                                                           @Override
                                                                                           public String get() {
                                                                                               try {
                                                                                                   return callableTwo.call();
                                                                                               } catch (Exception e) {
                                                                                                   e.printStackTrace();
                                                                                               }
                                                                                               return "1";
                                                                                           }
                                                                                       }
          );
  
          CompletableFuture.allOf(completableFuture1, completableFuture2).thenApply(
                  i -&gt; {
                      System.out.println("Completed running the futures");
                      System.out.println("future 1" + completableFuture1.join().toString());
                      System.out.println("future 2" + completableFuture2.join().toLowerCase());
                      return i;
                  }
          );
  
      }
  }
  </code></pre>
  
  <p><strong>CallableTwo.java</strong></p>
  
  <pre><code>import org.springframework.context.annotation.Scope;
  import org.springframework.stereotype.Component;
  
  import java.util.concurrent.Callable;
  
  @Component
  @Scope("prototype")
  public class CallableTwo {
  
      public String call() throws Exception {
          Thread.sleep(2000);
          return "1000";
      }
  }
  </code></pre>
  
  <p><strong>CallableOne.java</strong></p>
  
  <pre><code>import org.springframework.context.annotation.Scope;
  import org.springframework.stereotype.Component;
  
  @Component
  @Scope("prototype")
  public class CallableOne {
  
      public Integer call() throws Exception {
          Thread.sleep(2000);
          return 1;
      }
  }
  </code></pre>
  
  <p><strong>sampleSpringResource.java</strong> Code that invokes the InvokeCallable.java using restful service</p>
  
  <pre><code>import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  import org.springframework.dao.DataAccessException;
  import org.springframework.stereotype.Service;
  
  import javax.inject.Inject;
  import javax.ws.rs.GET;
  import javax.ws.rs.Path;
  import javax.ws.rs.PathParam;
  import javax.ws.rs.Produces;
  import javax.ws.rs.core.Response;
  
  import java.util.concurrent.ExecutionException;
  
  import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
  import static org.json.XMLTokener.entity;
  
  /* ItemValue Web service
   *
   */
  @Path("/")
  @Service
  public class sampleSpringResource {
  
      @Inject
      private InvokeCallable callable;
  
      private static final Logger LOG = LogManager.getLogger();
  
      @GET
      @Path("/changeme/")
      @Produces(APPLICATION_JSON)
      public Response getsampleSpring() throws ExecutionException, InterruptedException {            
          callable.invokeCallables();               
  
      }
  
  }
  </code></pre>