Дескриптор CompletableFuture и completeExceptionly не могут работать вместе? - PullRequest
0 голосов
/ 09 июня 2018

Я пытаюсь установить значение по умолчанию , когда в CompletableFuture возникают исключения * Я заставил его работать методом handle следующим образом:

private static void testHandle() {
    String name = null;
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    }).handle((s, t) -> s != null ? s : "Hello, Stranger!" + t.toString());
    out.println(completableFuture.join());
}

Но когда я попыталсяостановите CompletableFuture, используя completeExceptionally, когда случится что-то плохое, и отследите исключение следующим образом. Я не могу поймать исключение , как я это делал сейчас.

private static void testCompleteExceptionally() {
    String name = "Hearen";
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        delay(500L);
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    }).handle((s, t) -> {
        try {
            throw t.getCause(); 
        } catch (Throwable e) {
            out.println(e.toString()); // I was hoping to record the custom exceptions here;
        }
        return s != null ? s : "Hello, Stranger!" + t.toString();
    });

    if (name != null) {
        completableFuture.completeExceptionally(new RuntimeException("Calculation failed!")); // when bad things happen, I try to complete it by exception;
    }
    out.println(completableFuture.join());

}

ОБНОВЛЕНО 2018-06-09 Спасибо за помощь, @ Daniele

private static void testCompleteExceptionally() {
    String name = "Hearen";
    CompletableFuture<String> completableFuture
            = CompletableFuture.supplyAsync(() -> {
        delay(500L);
        if (name == null) {
            throw new RuntimeException("Computation error!");
        }
        return "Hello, " + name;
    });

    if (name != null) {
        completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));
    }
    out.println(completableFuture.handle((s, t) ->  s != null ? s : "Hello, Stranger!" + t.toString()).join());

}

Ручка , приложенная как раз перед join() работает как положено.Но в этом случае returned value будет null.

На основе API дескриптора

Возвращает new CompletionStage, который, когда этот этап завершается либо нормально, либо исключительно, выполняется срезультат этого этапа и исключение в качестве аргументов для предоставленной функции.

1 Ответ

0 голосов
/ 09 июня 2018

Вы строите future, создаете трубопровод с handle (таким образом, получаете другое будущее), а затем исключительно завершаете будущее, возвращаемое handle.

Вы должны выполнить исключительно внутреннее future сам по себе, вместо handle.

Дело в том, что handle возвращает другое будущее;и вы не должны завершать «внешнее» будущее исключительно, потому что это будет обходить поведение обработки.

Ниже кода;

package stackOv;

import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Supplier;

public class TestHandle {
  BiFunction<String, Throwable, String> handle2 = new BiFunction<String, Throwable, String>() {
    @Override
    public String apply(String s, Throwable t) {
      try {
        throw t.getCause(); 
      } catch (Throwable e) {
        // I was hoping to record the custom exceptions here;
        System.out.println(e.toString());
      }
      return s != null ? s : "Hello, Stranger!" + t.toString();
    }
  };

  private void testCompleteExceptionally() {
    String name = "Hearen";
    Supplier<String> supplier2 = () -> {
      delay(500L);
      if (name == null) {
        throw new RuntimeException("Computation error!");
      }
      return "Hello, " + name;
    };
    CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(supplier2);

    if (name != null) {
      // when bad things happen, I try to complete it by exception;
      completableFuture.completeExceptionally(new RuntimeException("Calculation failed!"));      
    }
    System.out.println(completableFuture.handle(handle2).join());
  }

  public static void main(String[] args) {
    TestHandle th = new TestHandle();
    th.testCompleteExceptionally();
  }

  private static void delay(long milli) {
    try { Thread.sleep(milli); } catch (InterruptedException e) {}    
  }
}
...