Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8211010

Add exception handling methods to CompletionStage and CompletableFuture

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P4
    • Resolution: Approved
    • Fix Version/s: 12
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Compatibility Kind:
      source, behavioral
    • Compatibility Risk:
      minimal
    • Compatibility Risk Description:
      Hide
      It is conceivable but very unlikely that the new methods overlap existing methods defined in other CompletionStage implementations in ways that would lead to overload ambiguities. Also, the new methods have default implementations in CompletionStage in terms of other existing methods (they also have more efficient implementations in CompletableFuture), in ways that might uncover existing errors.
      Show
      It is conceivable but very unlikely that the new methods overlap existing methods defined in other CompletionStage implementations in ways that would lead to overload ambiguities. Also, the new methods have default implementations in CompletionStage in terms of other existing methods (they also have more efficient implementations in CompletableFuture), in ways that might uncover existing errors.
    • Interface Kind:
      Java API

      Description

      Summary

      People have complained about lack of some exception-handling methods. This CR adds them.

      Problem

      The CompletionStage interface and CompletableFuture implementation lack some methods for dealing with exceptional outcomes that users need and expect based on presence of related non-exception-handling methods.

      Solution

      Add methods to cover all variants of exceptionally{Compose}{Async}:

      exceptionally(Function<Throwable, ? extends T> f) // already exists
      exceptionallyAsync(Function<Throwable, ? extends T> f);
      exceptionallyAsync(Function<Throwable, ? extends T> f, Executor e);
      exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>> f);
      exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> f);
      exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>> f, Executor e);

      Specification

      /**
       * Returns a new CompletionStage that, when this stage completes
       * exceptionally, is executed with this stage's exception as the
       * argument to the supplied function, using this stage's default
       * asynchronous execution facility.  Otherwise, if this stage
       * completes normally, then the returned stage also completes
       * normally with the same value.
       *
       * @implSpec The default implementation invokes {@link #handle},
       * relaying to {@link #handleAsync} on exception, then {@link
       * #thenCompose} for result.
       *
       * @param fn the function to use to compute the value of the
       * returned CompletionStage if this CompletionStage completed
       * exceptionally
       * @return the new CompletionStage
       * @since 12
       */
      public default CompletionStage<T> exceptionallyAsync
          (Function<Throwable, ? extends T> fn) {
          return handle((r, ex) -> (ex == null)
                        ? this
                        : this.<T>handleAsync((r1, ex1) -> fn.apply(ex1)))
              .thenCompose(Function.identity());
      }
      
      /**
       * Returns a new CompletionStage that, when this stage completes
       * exceptionally, is executed with this stage's exception as the
       * argument to the supplied function, using the supplied Executor.
       * Otherwise, if this stage completes normally, then the returned
       * stage also completes normally with the same value.
       *
       * @implSpec The default implementation invokes {@link #handle},
       * relaying to {@link #handleAsync} on exception, then {@link
       * #thenCompose} for result.
       *
       * @param fn the function to use to compute the value of the
       * returned CompletionStage if this CompletionStage completed
       * exceptionally
       * @param executor the executor to use for asynchronous execution
       * @return the new CompletionStage
       * @since 12
       */
      public default CompletionStage<T> exceptionallyAsync
          (Function<Throwable, ? extends T> fn, Executor executor) {
          return handle((r, ex) -> (ex == null)
                        ? this
                        : this.<T>handleAsync((r1, ex1) -> fn.apply(ex1), executor))
              .thenCompose(Function.identity());
      }
      
      /**
       * Returns a new CompletionStage that, when this stage completes
       * exceptionally, is composed using the results of the supplied
       * function applied to this stage's exception.
       *
       * @implSpec The default implementation invokes {@link #handle},
       * invoking the given function on exception, then {@link
       * #thenCompose} for result.
       *
       * @param fn the function to use to compute the returned
       * CompletionStage if this CompletionStage completed exceptionally
       * @return the new CompletionStage
       * @since 12
       */
      public default CompletionStage<T> exceptionallyCompose
          (Function<Throwable, ? extends CompletionStage<T>> fn) {
          return handle((r, ex) -> (ex == null)
                        ? this
                        : fn.apply(ex))
              .thenCompose(Function.identity());
      }
      
      /**
       * Returns a new CompletionStage that, when this stage completes
       * exceptionally, is composed using the results of the supplied
       * function applied to this stage's exception, using this stage's
       * default asynchronous execution facility.
       *
       * @implSpec The default implementation invokes {@link #handle},
       * relaying to {@link #handleAsync} on exception, then {@link
       * #thenCompose} for result.
       *
       * @param fn the function to use to compute the returned
       * CompletionStage if this CompletionStage completed exceptionally
       * @return the new CompletionStage
       * @since 12
       */
      public default CompletionStage<T> exceptionallyComposeAsync
          (Function<Throwable, ? extends CompletionStage<T>> fn) {
          return handle((r, ex) -> (ex == null)
                        ? this
                        : this.handleAsync((r1, ex1) -> fn.apply(ex1))
                          .thenCompose(Function.identity())
          ).thenCompose(Function.identity());
      }
      
      /**
       * Returns a new CompletionStage that, when this stage completes
       * exceptionally, is composed using the results of the supplied
       * function applied to this stage's exception, using the
       * supplied Executor.
       *
       * @implSpec The default implementation invokes {@link #handle},
       * relaying to {@link #handleAsync} on exception, then {@link
       * #thenCompose} for result.
       *
       * @param fn the function to use to compute the returned
       * CompletionStage if this CompletionStage completed exceptionally
       * @param executor the executor to use for asynchronous execution
       * @return the new CompletionStage
       * @since 12
       */
      public default CompletionStage<T> exceptionallyComposeAsync
          (Function<Throwable, ? extends CompletionStage<T>> fn,
           Executor executor) {
          return handle((r, ex) -> (ex == null)
                        ? this
                        : this.handleAsync((r1, ex1) -> fn.apply(ex1), executor)
                          .thenCompose(Function.identity())
          ).thenCompose(Function.identity());
      }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                martin Martin Buchholz
                Reporter:
                dl Doug Lea
                Reviewed By:
                Chris Hegarty, Martin Buchholz
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: