Un problème a été détecté dans l'environnement de production en ce qui concerne le CompletableFuture.supplyAsync()
Nous disposons d'une méthode de traitement par lots comme ci-dessous :
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
public class CompletableFutureProblem {
public void batchOperation(){
List<String> stringList = new ArrayList<>();
stringList.add("task1");
stringList.add("task2");
List<CompletableFuture<String>> futures = new ArrayList<>();
stringList.parallelStream().forEach(str -> {
CompletableFuture<String> response = restApiCall(str);
futures.add(response);
});
//futures.add(null);
CompletableFuture<Void> result = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
CompletableFuture<List<String>> convertedResult = result.thenApply(v ->
futures.stream().map(CompletableFuture::join).collect(Collectors.toList())
);
try {
List<String> finishedTask = convertedResult.get();
System.out.println(finishedTask.toString());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public CompletableFuture<String> restApiCall(String str){
return CompletableFuture.supplyAsync(() -> {
return "Complete-" + str;
});
}
public static void main(String[] args) {
CompletableFutureProblem problem = new CompletableFutureProblem();
problem.batchOperation();
}
}
Lorsqu'il fonctionne correctement, il s'imprime : [Terminer-tâche2, Terminer-tâche1].
Cependant, il arrive qu'une exception soit levée comme ci-dessous dans la production :
Exception in thread "main" java.lang.NullPointerException
at java.util.concurrent.CompletableFuture.andTree(CompletableFuture.java:1320)
at java.util.concurrent.CompletableFuture.allOf(CompletableFuture.java:2238)
at third.concurrent.CompletableFutureProblem.batchOperation(CompletableFutureProblem.java:20)
at third.concurrent.CompletableFutureProblem.main(CompletableFutureProblem.java:40)
J'ai enquêté sur les CompletableFuture.allOf()
Le code source a permis de constater que si la liste avenirs contient null, par exemple, futures.add(null) l'exception sera levée, mais je ne sais vraiment pas dans quels scénarios l'exception sera levée. CompletableFuture.supplyAsync()
en restApiCall
retour de la méthode null
?
Je vous remercie de votre patience et de la lecture de ce long message.