title: How to handle exceptions in SpringBoot ListenableFuture
body: <p>so I have a SpringBoot end point controller that starts like this:</p>
  
  <pre><code>@RequestMapping(value = "/post", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
  public Response post(@Valid @RequestBody Message message) throws FailedToPostException {
      message.setRecieveTime(System.currentTimeMillis());
  
      return this.service.post(message);
  }
  </code></pre>
  
  <p>And the post function:</p>
  
  <pre><code>public Response post(Message message) throws FailedToPostException{
  
  
      ListenableFuture&lt;SendResult&lt;String, Message&gt;&gt; future = kafkaTemplate.send("topicName", message);
      future.addCallback(new ListenableFutureCallback&lt;SendResult&lt;String, Message&gt;&gt;() {
  
          @Override
          public void onSuccess(SendResult&lt;String, Message&gt; result) {
              LOGGER.info("Post Finished. '{}' with offset: {}", message,
                          result.getRecordMetadata().offset());
          }
  
          @Override
          public void onFailure(Throwable ex) {
              LOGGER.error("Message Post Failed. '{}'", message, ex);
  
              long nowMillis = System.currentTimeMillis();
              int diffSeconds =  (int) ((nowMillis - message.getRecieveTime()) / 1000);
  
              if (diffSeconds &gt;= 10) {
                  LOGGER.debug("timeout sending message to Kafka, aborting.");
                  return;
              }
              else {
                  post(message);
              }
          }
      });
  
      LOGGER.debug("D: " + Utils.getMetricValue("buffer-available-bytes", kafkaTemplate));
  
      return new Response("Message Posted");
  }
  </code></pre>
  
  <p>Now you can see, that we are trying to make sure, if a <code>kafkaTemplate.send</code> failed, we are going to recursively invoke <code>post(message)</code> again for up to 10 seconds, until the producer memory buffer clears and the message gets through.</p>
  
  <p>The problems are:</p>
  
  <ol>
  <li>We want to be able to return failure response to the endpoint's client (eg: "Failed to acknowledge the message").</li>
  <li>Is there any better way to handle exceptions from a Future in a piece of code like that above?</li>
  <li>Is there a way to avoid using a recursive function here? We did that, because we wanted to attempt delivery of the message to Kafka for like 10 seconds, before sending it as an email to look at.</li>
  </ol>
  
  <p>Side note: I still didnt use <code>buffer-available-bytes</code> attribute from kafkaTemplate.metrics(), I intend to use it to minimize the chance of this problem, but still need to handle the above just in  case of some race conditions</p>