title: How to implement asynchronous call with callback?
body: <p>I need to make a library in which I will have synchronous and asynchronous methods in it.</p>
  
  <p><strong>Core Logic of my Library -</strong></p>
  
  <p>The customer will use our library and they will call it by passing <code>DataKey</code> builder object. We will then construct a URL by using that <code>DataKey</code> object and make a HTTP client call to that URL by executing it and after we get the response back as a JSON String, we will send that JSON String back to our customer as it is by creating <code>DataResponse</code> object.</p>
  
  <p>I will have synchronous and asynchronous methods. Some customer will call the <code>executeSynchronous</code> method to get the same feature and some customer will call our <code>executeAsynchronous</code> method and with the <code>executeAsynchronous</code> method, they will call <code>future.get</code> in there code itself.</p>
  
  <p>Below is my interface -</p>
  
  <pre><code>public interface Client {
  
      // for synchronous
      public DataResponse executeSynchronous(DataKey dataKey);
  
      // for asynchronous
      public Future&lt;DataResponse&gt; executeAsynchronous(DataKey dataKey);
  }
  </code></pre>
  
  <p>Below is my <code>DataResponse</code> class -</p>
  
  <pre><code>public class DataResponse {
  
      private String response;
      private DataErrorEnum error;
      private DataStatusEnum status;
  
      // constructor here
  
      // and getters here
  }
  </code></pre>
  
  <p>Below is my <code>DataStatusEnum</code> class -</p>
  
  <pre><code>public enum DataStatusEnum {
      SUCCESS, ERROR;
  }
  </code></pre>
  
  <p>Below is my <code>DataErrorEnum</code> class -</p>
  
  <pre><code>public enum DataErrorEnum {
      NONE(200, "NONE", "Response is success."),
      SERVER_DOWN(3145, "Server Down", "some long message here which can give more details."),
      CLIENT_ERROR(3123, "Client Error", "some long message here which can give more details."),
      TIMEOUT_ON_CLIENT(3187, "Client Timeout", "some long message here which can give more details.");
  
      private final int code;
      private final String status;
      private final String description;
  
      // constructor and getters here
  }
  </code></pre>
  
  <p>And then I have my <code>DataClient</code> which implements the above <code>Client</code> interface.</p>
  
  <pre><code>public class DataClient implements Client {
  
      private RestTemplate restTemplate = new RestTemplate();
      private ExecutorService service = Executors.newFixedThreadPool(10);
  
      // for synchronous call
      @Override
      public DataResponse executeSynchronous(DataKey dataKey) {
          DataResponse dataResponse = null;
  
          try {
              Future&lt;String&gt; future = executeAsynchronous(dataKey);
              dataResponse = future.get(dataKey.getTimeout(), TimeUnit.MILLISECONDS);
          } catch (TimeoutException ex) {
              PotoLogging.logErrors(ex, DataErrorEnum.TIMEOUT_ON_CLIENT, dataKey);
              dataResponse = new DataResponse(null, DataErrorEnum.TIMEOUT_ON_CLIENT, DataStatusEnum.ERROR);
          } catch (Exception ex) {
              PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, dataKey);
              dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
          }
  
          return dataResponse;
      }
  
      //for asynchronous call
      @Override
      public Future&lt;DataResponse&gt; executeAsynchronous(DataKey dataKey) {
          Future&lt;DataResponse&gt; future = null;
  
          try {
              Task task = new Task(dataKey, restTemplate);
              future = executor.submit(task);
          } catch (Exception ex) {
              PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, dataKey);
          }
  
          return future;
      }
  }
  </code></pre>
  
  <p>Now below is my simple class which will perform the actual task -</p>
  
  <pre><code>public class Task implements Callable&lt;DataResponse&gt; {
  
      private DataKey dataKey;
      private RestTemplate restTemplate;
  
      public Task(DataKey dataKey, RestTemplate restTemplate) {
          this.dataKey = dataKey;
          this.restTemplate = restTemplate;
      }
  
      @Override
      public DataResponse call() throws Exception {
          DataResponse dataResponse = null;
          String response = null;
  
          try {
              String url = createURL();
              response = restTemplate.getForObject(url, String.class);
  
              // it is a successful response
              dataResponse = new DataResponse(response, DataErrorEnum.NONE, DataStatusEnum.SUCCESS);
          } catch (RestClientException ex) {
              PotoLogging.logErrors(ex, DataErrorEnum.SERVER_DOWN, dataKey);
              dataResponse = new DataResponse(null, DataErrorEnum.SERVER_DOWN, DataStatusEnum.ERROR);
          } catch (Exception ex) {
              PotoLogging.logErrors(ex, DataErrorEnum.CLIENT_ERROR, dataKey);
              dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
          }
  
          return dataResponse;
      }
  
      // create a URL by using dataKey object
      private String createURL() {
          String url = somecode;
  
          return url;
      }
  }
  </code></pre>
  
  <p><strong>Problem Statement:-</strong></p>
  
  <p>As I mentioned above, some customers will call <code>executeSynchronous</code> method to get the data for that user id which they are passing in <code>DataKey</code> object and some customers will call <code>executeAsynchronous</code> method with <code>DataKey</code> object but in latter case, they will do <code>future.get</code> in their code base.</p>
  
  <p>If you see my <code>executeSynchronous</code> method, I am doing <code>future.get</code> after calling <code>executeAsynchronous</code> method and if there is any <code>TimeoutException</code>, then I am logging using <code>PotoLogging</code> class which is specific in our company and that logs will go to some other service here which we use to look all our error logs on the dashboard. And it mainly depends how we are logging it with what names so that we can see those names in the dashboard.</p>
  
  <p>Now the problem is customer within our company can also call <code>executeAsynchronous</code> method but that means, they will do <code>future.get</code> in their code base and that can also result in <code>TimeoutException</code> in their code but I cannot force them to log the same way as I am doing it. So my question is - Is there any way that I can get callback if there is any <code>TimeoutException</code> so that I can log it like this if anyone is calling <code>executeAsynchronous</code> method of my library in their code base - </p>
  
  <pre><code>PotoLogging.logErrors(ex, DataErrorEnum.TIMEOUT_ON_CLIENT, dataKey);
  </code></pre>
  
  <p>I need to do this so that my library can log <code>TimeoutException</code> in the tool we have in our company in the way we want it. Otherwsie, I need to tell each of the customer to do log it like this so that we can see it in our dashboard. How can I get the callback from asynchronous call and still leverage all the feature of being asynchronous?</p>
  
  <p>What is the best way to do this?</p>