title: CompletableFuture exceptionally breaks the work chain
body: <p>The idea of using <code>CompletableFuture</code> is because it offers a chain, while the first several steps encapsulate beans before the last step uses it. Because any exception may happen in these steps and <code>exceptionally</code> is used to handle error. However, <code>exceptionally</code> only accepts <code>Throwable</code> argument and so far I haven't found a way to grab those encapsulated beans. </p>
  
  <pre><code>CompletableFuture.supplyAsync(this::msgSource)
              .thenApply(this::sendMsg).exceptionally(this::errorHandler).thenAccept(this::saveResult)
  public List&lt;Msg&gt; msgSource() // take message from somewhere.
  public List&lt;Msg&gt; sendMsg(List&lt;Msg&gt;) // exceptions may happen like 403 or timeout
  public List&lt;Msg&gt; errorHandler() // set a success flag to false in Msg.
  public void saveResult(List&lt;Msg&gt;) // save send result like success or false in data center.
  </code></pre>
  
  <p>In the above example, comments are the working flow. However, since <code>errorHandler</code> neither accepts <code>List&lt;Msg&gt;</code> nor passes it on, so the chain is broken. How to get the return from <code>msgSource</code>? </p>
  
  <p>EDIT</p>
  
  <pre><code>public class CompletableFutureTest {
  
      private static Logger log = LoggerFactory.getLogger(CompletableFutureTest.class);
      public static void main(String[] args) {
          CompletableFutureTest test = new CompletableFutureTest();
          CompletableFuture future = new CompletableFuture();
          future.supplyAsync(test::msgSource)
              .thenApply(test::sendMsg).exceptionally(throwable -&gt; {
              List&lt;String&gt; list = (List&lt;String&gt;) future.join(); // never complete
              return list;
          }).thenAccept(test::saveResult);
          try {
              future.get();
          } catch (InterruptedException e) {
              e.printStackTrace();
          } catch (ExecutionException e) {
              e.printStackTrace();
          }
      }
  
      private List&lt;String&gt; saveResult(List&lt;String&gt; list) {
          return list;
      }
  
      private List&lt;String&gt; sendMsg(List&lt;String&gt; list) {
          throw new RuntimeException();
      }
  
      public List&lt;String&gt; msgSource() {
          List&lt;String&gt; result = new ArrayList&lt;&gt;();
          result.add("1");
          result.add("2");
          return result;
      }
  }
  </code></pre>
  
  <p><a href="https://i.stack.imgur.com/nRMJA.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/nRMJA.png" alt="enter image description here"></a></p>