title: Java 8 CompletionStage exceptionally rethrow exception
body: <p>Rethrowing an exception inside of <code>exceptionally</code> method of CompletionStage seems not to be allowed. </p>
  
  <p>I need to check for a certain kind of exception and if not I need to rethrow it back : </p>
  
  <pre><code>Future&lt;JsonNode&gt; futureSite = someClient.getSite(siteId, queryParams);
  
  CompletionStage&lt;JsonNode&gt; outcome = FutureConverters.toJava(futureSite);
  
  return outcome.thenApplyAsync((siteJson) -&gt; {
              Site site = Json.fromJson(siteJson, Site.class);
              try {
                  return function.apply(site);
              } catch (RequestException e) {
                  return e.result;
              }
          }, httpExecutionContext.current()).exceptionally(throwable -&gt; {
              if(throwable instanceof SomeClientException) {
                  if(((SomeClientException) throwable).httpStatusCode == 404) {
                     return entityNotFound("Site", siteId);
                  }
              }
  
  
   // let JSON parsing failures and other errors bubble up, TODO play2.5
  
  
           throw throwable;
          });
  </code></pre>
  
  <p><code>throw throwable</code> errors out saying unhandledException <code>java.lang.Throwable</code></p>
  
  <p>What interface would possibly allow to rethrow back the exception ? Or is there a better way around ?</p>
  
  <p>Update : </p>
  
  <p>I tried with advice from Holger as below, but I am still not sure at what point could I actually rethrow this :</p>
  
  <pre><code>BaseController.java : 
         protected class RequestException extends Exception {
              private static final long serialVersionUID = -2154871100650903869L;
  
              public Result result;
  
              public RequestException(Result result) {
                  this.result = result;
              }
          }
  
          @FunctionalInterface
          protected interface RequestFunction&lt;T, R&gt; {
              R apply(T t) throws RequestException;
          }
  
      protected CompletionStage&lt;Result&gt; performWithSite(final Long siteId, RequestFunction&lt;Site, Result&gt; function) {
              QueryParams queryParams = QueryParams.create();
              Future&lt;JsonNode&gt; futureSite = someClient.getSite(siteId, queryParams);
  
              CompletionStage&lt;JsonNode&gt; outcome = FutureConverters.toJava(futureSite);
  
              return handleSpecific(
                      outcome.thenApplyAsync(siteJson -&gt; {
                          Site site = Json.fromJson(siteJson, Site.class);
                          try {
                              return function.apply(site);
                          } catch (RequestException e) {
                              return e.result;
                          }
                      }, httpExecutionContext.current()),
                      throwable -&gt; throwable instanceof SomeClientException
                              &amp;&amp; ((SomeClientException)throwable).httpStatusCode == 404,
                      () -&gt; entityNotFound("Site", siteId));
          } 
  
        protected Result entityNotFound(String entityName, String id) {
      // building our custom error model. 
    Error e = new Error(
                      Http.Status.NOT_FOUND,
                      ErrorCode.ENTITY_NOT_FOUND,
                      ErrorCodes.NOT_FOUND, new String[]{entityName, id});
  
              return notFound(e.asJson());
          }
  </code></pre>
  
  <p>So, the essence of above code is I need to reach out to someClient to check if the site exists and the client can throw a SomeClientException. </p>
  
  <pre><code> Controller.java
  
         public Result destroy(Long siteId, Long productId){
              return performWithSite(siteId, site -&gt; {
                  productWriter.deleteProduct(siteId, productId);
                  return noContent();
              }).toCompletableFuture().exceptionally(e -&gt; {
                Logger.error(e+"exception");
                 throw e.getCause(); 
                // above line errors out as unhandledException java.lang.throwable, I need the NotFoundException which is contained within the CompletionException to be thrown.
             });
          }
  </code></pre>
  
  <p>// In the above controller code, after I do the remote call to the client to check if the site exists, I need to go ahead and delete the product. </p>
  
  <p><code>productWriter.deleteProduct(siteId, productId)</code> might still throw a <code>NotFoundException</code> or something else which I need to rethrow it back ... 
  so that any exception which is re-thrown from the controller code is picked up our custom exception handler in the call chain. </p>
  
  <p>Here is my test case : </p>
  
  <pre><code>  "return 404 when deleting a nonexistent Product" {
        when(productDAO.findBySiteAndProductId(anyLong(), anyLong())) thenReturn null
  
        a[NotFoundException] should be thrownBy { controller.destroy(0L, 1L) }
      }
  </code></pre>