How to handle exception in Java 8 Stream?
I have a method where I loop through a list and create a List. When doing this, I call the (createResult) method to give the result, it also throws a CustomException, which I wrap as a ResultClassException. But I keep getting Unhandled Exception error.
My code:
private List<Result> getResultList(List<String> results) throws ResultClassException {
List<Result> resultList = new ArrayList<>();
results.forEach(
(resultName) -> {
if (!resultRepository.contains(resultName)) {
try {
final Result result = createResult(resultName);
resultList.add(result);
} catch (CustomException e) {
throw new ResultClassException("Error",e);
}
} else {
resultList.add(resultRepository.get(resultName));
log.info("Result {} already exists.", resultName);
}
}
);
return Collections.unmodifiableList(resultList);
}
Can someone tell me what I am doing wrong?
source to share
You probably have too many responsibilities in your method. You should consider splitting it into a method that only displays and another that collects them.
private List<Result> getResultList(List<String> names) throws ResultClassException {
try {
return names.stream()
.map(this::getOrCreateResult)
.collect(collectingAndThen(toList(), Collections::unmodifiableList));
} catch (RuntimeException e) {
if (e.getCause() instanceof CustomException) {
throw new ResultClassException("Error", e.getCause());
}
throw e;
// Or use Guava propagate
}
}
private Result getOrCreateResult(String name) {
if (!resultRepository.contains(name)) {
try {
return createResult(name);
} catch (CustomException e) {
throw new RuntimeException(e);
}
} else {
log.info("Result {} already exists.", name);
return resultRepository.get(name);
}
}
source to share
You cannot handle checked exception from within threads
One way would be throwing RuntimeException
out createResult
or writing a wrapping method createResult
that will catch and handle the checked exception.
source to share
With lambda expressions in Java 8, you represent inner classes. This way the exception will be thrown inside your anonymous inner class. try adding this when you add your throw new ResultClassException ("Error", e);
Thread.getAllStackTraces()
.keySet()
.stream()
.map(Thread::getStackTrace)
.map(Arrays::asList)
.forEach(list -> System.out.println(list.stream()
.map(i -> i.toString())
.collect(Collectors.joining("\n\t"))));
and watch the thread that calls it. You will see that your exception is out of scope that you would expect from a lambda. You will see that the thread creates many threads and your exception is not part of the thread you want. You can wrap your method like this: Java 8: How can I work with exception metadata methods in streams?
source to share