Throw Exception in Function apply for CompletableFutures












0















I'm having some tasks created like follows (this is just for demonstration normally network calls):



public class RandomTask implements Function<String, String> {
private int number;
private int waitTime;
private boolean throwError;

public RandomTask(int number, int waitTime, boolean throwError) {
this.number = number;
this.waitTime = waitTime;
this.throwError = throwError;
}

@Override
public String apply(String s) {
System.out.println("Job " + number + " started");
try {
Thread.sleep(waitTime);

if (throwError) {
throw new InterruptedException("Something happened");
}

} catch (InterruptedException e) {
System.out.println("Error " + e.getLocalizedMessage());
}

return "RandomTask " + number + " finished";
}
}


Then I have a Chain class where I chain some tasks together per job.



static CompletableFuture<String> start(ExecutorService executorService) {
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Foo", executorService)
.thenApplyAsync(new RandomTask(3, 100, false), executorService)
.thenApplyAsync(new RandomTask(4, 100, false), executorService);

return future2;
}


I then start 2 chains as follows:



  CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool));
try {
combinedFuture.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}


That way the two chains start off at the same time.



Now I want to throw an exception in a task and catch it where I call combinedFuture.get() so that I know which task has failed in my chain.



The thing is dat I can't adapt the Function because CompletableFutures complains about this. I tried with:



@FunctionalInterface
public interface CheckedFunction<T, R> {
R apply(T t) throws InterruptedException;
}


But this doesn't work. Is this not possible or how can I achieve my goal?










share|improve this question



























    0















    I'm having some tasks created like follows (this is just for demonstration normally network calls):



    public class RandomTask implements Function<String, String> {
    private int number;
    private int waitTime;
    private boolean throwError;

    public RandomTask(int number, int waitTime, boolean throwError) {
    this.number = number;
    this.waitTime = waitTime;
    this.throwError = throwError;
    }

    @Override
    public String apply(String s) {
    System.out.println("Job " + number + " started");
    try {
    Thread.sleep(waitTime);

    if (throwError) {
    throw new InterruptedException("Something happened");
    }

    } catch (InterruptedException e) {
    System.out.println("Error " + e.getLocalizedMessage());
    }

    return "RandomTask " + number + " finished";
    }
    }


    Then I have a Chain class where I chain some tasks together per job.



    static CompletableFuture<String> start(ExecutorService executorService) {
    CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Foo", executorService)
    .thenApplyAsync(new RandomTask(3, 100, false), executorService)
    .thenApplyAsync(new RandomTask(4, 100, false), executorService);

    return future2;
    }


    I then start 2 chains as follows:



      CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool));
    try {
    combinedFuture.get();
    } catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
    }


    That way the two chains start off at the same time.



    Now I want to throw an exception in a task and catch it where I call combinedFuture.get() so that I know which task has failed in my chain.



    The thing is dat I can't adapt the Function because CompletableFutures complains about this. I tried with:



    @FunctionalInterface
    public interface CheckedFunction<T, R> {
    R apply(T t) throws InterruptedException;
    }


    But this doesn't work. Is this not possible or how can I achieve my goal?










    share|improve this question

























      0












      0








      0








      I'm having some tasks created like follows (this is just for demonstration normally network calls):



      public class RandomTask implements Function<String, String> {
      private int number;
      private int waitTime;
      private boolean throwError;

      public RandomTask(int number, int waitTime, boolean throwError) {
      this.number = number;
      this.waitTime = waitTime;
      this.throwError = throwError;
      }

      @Override
      public String apply(String s) {
      System.out.println("Job " + number + " started");
      try {
      Thread.sleep(waitTime);

      if (throwError) {
      throw new InterruptedException("Something happened");
      }

      } catch (InterruptedException e) {
      System.out.println("Error " + e.getLocalizedMessage());
      }

      return "RandomTask " + number + " finished";
      }
      }


      Then I have a Chain class where I chain some tasks together per job.



      static CompletableFuture<String> start(ExecutorService executorService) {
      CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Foo", executorService)
      .thenApplyAsync(new RandomTask(3, 100, false), executorService)
      .thenApplyAsync(new RandomTask(4, 100, false), executorService);

      return future2;
      }


      I then start 2 chains as follows:



        CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool));
      try {
      combinedFuture.get();
      } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
      }


      That way the two chains start off at the same time.



      Now I want to throw an exception in a task and catch it where I call combinedFuture.get() so that I know which task has failed in my chain.



      The thing is dat I can't adapt the Function because CompletableFutures complains about this. I tried with:



      @FunctionalInterface
      public interface CheckedFunction<T, R> {
      R apply(T t) throws InterruptedException;
      }


      But this doesn't work. Is this not possible or how can I achieve my goal?










      share|improve this question














      I'm having some tasks created like follows (this is just for demonstration normally network calls):



      public class RandomTask implements Function<String, String> {
      private int number;
      private int waitTime;
      private boolean throwError;

      public RandomTask(int number, int waitTime, boolean throwError) {
      this.number = number;
      this.waitTime = waitTime;
      this.throwError = throwError;
      }

      @Override
      public String apply(String s) {
      System.out.println("Job " + number + " started");
      try {
      Thread.sleep(waitTime);

      if (throwError) {
      throw new InterruptedException("Something happened");
      }

      } catch (InterruptedException e) {
      System.out.println("Error " + e.getLocalizedMessage());
      }

      return "RandomTask " + number + " finished";
      }
      }


      Then I have a Chain class where I chain some tasks together per job.



      static CompletableFuture<String> start(ExecutorService executorService) {
      CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Foo", executorService)
      .thenApplyAsync(new RandomTask(3, 100, false), executorService)
      .thenApplyAsync(new RandomTask(4, 100, false), executorService);

      return future2;
      }


      I then start 2 chains as follows:



        CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool));
      try {
      combinedFuture.get();
      } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
      }


      That way the two chains start off at the same time.



      Now I want to throw an exception in a task and catch it where I call combinedFuture.get() so that I know which task has failed in my chain.



      The thing is dat I can't adapt the Function because CompletableFutures complains about this. I tried with:



      @FunctionalInterface
      public interface CheckedFunction<T, R> {
      R apply(T t) throws InterruptedException;
      }


      But this doesn't work. Is this not possible or how can I achieve my goal?







      java completable-future






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 14 '18 at 19:14









      user1007522user1007522

      3,26274592




      3,26274592
























          1 Answer
          1






          active

          oldest

          votes


















          1














          “That way the two chains start off at the same time.” indicates that you have a fundamentally wrong understanding of how CompletableFuture works.



          Asynchronous operations are submitted to the executor service right when you create them or as soon as their prerequisites are available. So in case of supplyAsync, which has no dependencies, the asynchronous operation starts right within the supplyAsync invocation.



          All, a construct like CompletableFuture.allOf(job1, job2).get() does, is to create a new stage depending on both jobs and waiting for its completion, so the net result is just to wait for the completion of both jobs. It does not start the jobs. They are already running. Waiting for a completion has no influence of the process of completing.



          Chaining a CompletableFuture with a custom function type allowing checked exceptions can be done as



          public static <T,R> CompletableFuture<R> thenApplyAsync(
          CompletableFuture<T> f, CheckedFunction<? super T, ? extends R> cf,
          Executor e) {

          CompletableFuture<R> r = new CompletableFuture<>();
          f.whenCompleteAsync((v,t) -> {
          try {
          if(t != null) r.completeExceptionally(t);
          else r.complete(cf.apply(v));
          } catch(Throwable t2) {
          r.completeExceptionally(t2);
          }
          }, e);
          return r;
          }


          To use this method, instead of chaining calls on the CompletableFuture, you have to nest them. E.g.



          static CompletableFuture<String> start(ExecutorService executorService) {
          CompletableFuture<String> future2 =
          thenApplyAsync(thenApplyAsync(
          CompletableFuture.supplyAsync(() -> "Foo", executorService),
          new RandomTask(3, 100, false), executorService),
          new RandomTask(4, 100, false), executorService);

          return future2;
          }


          given



          public class RandomTask implements CheckedFunction<String, String> {
          private int number, waitTime;
          private boolean throwError;

          public RandomTask(int number, int waitTime, boolean throwError) {
          this.number = number;
          this.waitTime = waitTime;
          this.throwError = throwError;
          }

          @Override
          public String apply(String s) throws InterruptedException {
          System.out.println("Job " + number + " started");
          Thread.sleep(waitTime);
          if (throwError) {
          throw new InterruptedException("Something happened in "+number);
          }
          return "RandomTask " + number + " finished";
          }
          }


          You can still create two tasks and wait for both like



          CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool))
          .join();





          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53307275%2fthrow-exception-in-function-apply-for-completablefutures%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            1














            “That way the two chains start off at the same time.” indicates that you have a fundamentally wrong understanding of how CompletableFuture works.



            Asynchronous operations are submitted to the executor service right when you create them or as soon as their prerequisites are available. So in case of supplyAsync, which has no dependencies, the asynchronous operation starts right within the supplyAsync invocation.



            All, a construct like CompletableFuture.allOf(job1, job2).get() does, is to create a new stage depending on both jobs and waiting for its completion, so the net result is just to wait for the completion of both jobs. It does not start the jobs. They are already running. Waiting for a completion has no influence of the process of completing.



            Chaining a CompletableFuture with a custom function type allowing checked exceptions can be done as



            public static <T,R> CompletableFuture<R> thenApplyAsync(
            CompletableFuture<T> f, CheckedFunction<? super T, ? extends R> cf,
            Executor e) {

            CompletableFuture<R> r = new CompletableFuture<>();
            f.whenCompleteAsync((v,t) -> {
            try {
            if(t != null) r.completeExceptionally(t);
            else r.complete(cf.apply(v));
            } catch(Throwable t2) {
            r.completeExceptionally(t2);
            }
            }, e);
            return r;
            }


            To use this method, instead of chaining calls on the CompletableFuture, you have to nest them. E.g.



            static CompletableFuture<String> start(ExecutorService executorService) {
            CompletableFuture<String> future2 =
            thenApplyAsync(thenApplyAsync(
            CompletableFuture.supplyAsync(() -> "Foo", executorService),
            new RandomTask(3, 100, false), executorService),
            new RandomTask(4, 100, false), executorService);

            return future2;
            }


            given



            public class RandomTask implements CheckedFunction<String, String> {
            private int number, waitTime;
            private boolean throwError;

            public RandomTask(int number, int waitTime, boolean throwError) {
            this.number = number;
            this.waitTime = waitTime;
            this.throwError = throwError;
            }

            @Override
            public String apply(String s) throws InterruptedException {
            System.out.println("Job " + number + " started");
            Thread.sleep(waitTime);
            if (throwError) {
            throw new InterruptedException("Something happened in "+number);
            }
            return "RandomTask " + number + " finished";
            }
            }


            You can still create two tasks and wait for both like



            CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool))
            .join();





            share|improve this answer




























              1














              “That way the two chains start off at the same time.” indicates that you have a fundamentally wrong understanding of how CompletableFuture works.



              Asynchronous operations are submitted to the executor service right when you create them or as soon as their prerequisites are available. So in case of supplyAsync, which has no dependencies, the asynchronous operation starts right within the supplyAsync invocation.



              All, a construct like CompletableFuture.allOf(job1, job2).get() does, is to create a new stage depending on both jobs and waiting for its completion, so the net result is just to wait for the completion of both jobs. It does not start the jobs. They are already running. Waiting for a completion has no influence of the process of completing.



              Chaining a CompletableFuture with a custom function type allowing checked exceptions can be done as



              public static <T,R> CompletableFuture<R> thenApplyAsync(
              CompletableFuture<T> f, CheckedFunction<? super T, ? extends R> cf,
              Executor e) {

              CompletableFuture<R> r = new CompletableFuture<>();
              f.whenCompleteAsync((v,t) -> {
              try {
              if(t != null) r.completeExceptionally(t);
              else r.complete(cf.apply(v));
              } catch(Throwable t2) {
              r.completeExceptionally(t2);
              }
              }, e);
              return r;
              }


              To use this method, instead of chaining calls on the CompletableFuture, you have to nest them. E.g.



              static CompletableFuture<String> start(ExecutorService executorService) {
              CompletableFuture<String> future2 =
              thenApplyAsync(thenApplyAsync(
              CompletableFuture.supplyAsync(() -> "Foo", executorService),
              new RandomTask(3, 100, false), executorService),
              new RandomTask(4, 100, false), executorService);

              return future2;
              }


              given



              public class RandomTask implements CheckedFunction<String, String> {
              private int number, waitTime;
              private boolean throwError;

              public RandomTask(int number, int waitTime, boolean throwError) {
              this.number = number;
              this.waitTime = waitTime;
              this.throwError = throwError;
              }

              @Override
              public String apply(String s) throws InterruptedException {
              System.out.println("Job " + number + " started");
              Thread.sleep(waitTime);
              if (throwError) {
              throw new InterruptedException("Something happened in "+number);
              }
              return "RandomTask " + number + " finished";
              }
              }


              You can still create two tasks and wait for both like



              CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool))
              .join();





              share|improve this answer


























                1












                1








                1







                “That way the two chains start off at the same time.” indicates that you have a fundamentally wrong understanding of how CompletableFuture works.



                Asynchronous operations are submitted to the executor service right when you create them or as soon as their prerequisites are available. So in case of supplyAsync, which has no dependencies, the asynchronous operation starts right within the supplyAsync invocation.



                All, a construct like CompletableFuture.allOf(job1, job2).get() does, is to create a new stage depending on both jobs and waiting for its completion, so the net result is just to wait for the completion of both jobs. It does not start the jobs. They are already running. Waiting for a completion has no influence of the process of completing.



                Chaining a CompletableFuture with a custom function type allowing checked exceptions can be done as



                public static <T,R> CompletableFuture<R> thenApplyAsync(
                CompletableFuture<T> f, CheckedFunction<? super T, ? extends R> cf,
                Executor e) {

                CompletableFuture<R> r = new CompletableFuture<>();
                f.whenCompleteAsync((v,t) -> {
                try {
                if(t != null) r.completeExceptionally(t);
                else r.complete(cf.apply(v));
                } catch(Throwable t2) {
                r.completeExceptionally(t2);
                }
                }, e);
                return r;
                }


                To use this method, instead of chaining calls on the CompletableFuture, you have to nest them. E.g.



                static CompletableFuture<String> start(ExecutorService executorService) {
                CompletableFuture<String> future2 =
                thenApplyAsync(thenApplyAsync(
                CompletableFuture.supplyAsync(() -> "Foo", executorService),
                new RandomTask(3, 100, false), executorService),
                new RandomTask(4, 100, false), executorService);

                return future2;
                }


                given



                public class RandomTask implements CheckedFunction<String, String> {
                private int number, waitTime;
                private boolean throwError;

                public RandomTask(int number, int waitTime, boolean throwError) {
                this.number = number;
                this.waitTime = waitTime;
                this.throwError = throwError;
                }

                @Override
                public String apply(String s) throws InterruptedException {
                System.out.println("Job " + number + " started");
                Thread.sleep(waitTime);
                if (throwError) {
                throw new InterruptedException("Something happened in "+number);
                }
                return "RandomTask " + number + " finished";
                }
                }


                You can still create two tasks and wait for both like



                CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool))
                .join();





                share|improve this answer













                “That way the two chains start off at the same time.” indicates that you have a fundamentally wrong understanding of how CompletableFuture works.



                Asynchronous operations are submitted to the executor service right when you create them or as soon as their prerequisites are available. So in case of supplyAsync, which has no dependencies, the asynchronous operation starts right within the supplyAsync invocation.



                All, a construct like CompletableFuture.allOf(job1, job2).get() does, is to create a new stage depending on both jobs and waiting for its completion, so the net result is just to wait for the completion of both jobs. It does not start the jobs. They are already running. Waiting for a completion has no influence of the process of completing.



                Chaining a CompletableFuture with a custom function type allowing checked exceptions can be done as



                public static <T,R> CompletableFuture<R> thenApplyAsync(
                CompletableFuture<T> f, CheckedFunction<? super T, ? extends R> cf,
                Executor e) {

                CompletableFuture<R> r = new CompletableFuture<>();
                f.whenCompleteAsync((v,t) -> {
                try {
                if(t != null) r.completeExceptionally(t);
                else r.complete(cf.apply(v));
                } catch(Throwable t2) {
                r.completeExceptionally(t2);
                }
                }, e);
                return r;
                }


                To use this method, instead of chaining calls on the CompletableFuture, you have to nest them. E.g.



                static CompletableFuture<String> start(ExecutorService executorService) {
                CompletableFuture<String> future2 =
                thenApplyAsync(thenApplyAsync(
                CompletableFuture.supplyAsync(() -> "Foo", executorService),
                new RandomTask(3, 100, false), executorService),
                new RandomTask(4, 100, false), executorService);

                return future2;
                }


                given



                public class RandomTask implements CheckedFunction<String, String> {
                private int number, waitTime;
                private boolean throwError;

                public RandomTask(int number, int waitTime, boolean throwError) {
                this.number = number;
                this.waitTime = waitTime;
                this.throwError = throwError;
                }

                @Override
                public String apply(String s) throws InterruptedException {
                System.out.println("Job " + number + " started");
                Thread.sleep(waitTime);
                if (throwError) {
                throw new InterruptedException("Something happened in "+number);
                }
                return "RandomTask " + number + " finished";
                }
                }


                You can still create two tasks and wait for both like



                CompletableFuture.allOf(Chain1.start(fixedThreadPool), Chain2.start(fixedThreadPool))
                .join();






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 16 '18 at 17:36









                HolgerHolger

                167k23236449




                167k23236449
































                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53307275%2fthrow-exception-in-function-apply-for-completablefutures%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Xamarin.iOS Cant Deploy on Iphone

                    Glorious Revolution

                    Dulmage-Mendelsohn matrix decomposition in Python