This project aims to ease operations on collections where failure should be allowed.
The main problem I wanted solved was to call close on all items of a collection, aggregating exceptions and adding them to the first one as suppressed exceptions.
libraryDependencies += "me.jeffshaw.tryutils" %% "tryutils" % "2.0.0"
import me.jeffshaw.tryutils._
import me.jeffshaw.tryutils.TryForeachException;
import me.jeffshaw.tryutils.TryIterable;
val closeables: Seq[AutoCloseable] = null
try {
closeables.tryClose()
} catch {
case e: TryForeachException[AutoCloseable] =>
// recover using `e.failures`
}
final Iterable<AutoCloseable> closeables = null;
try {
TryIterable.tryClose(closeables);
} catch (TryForeachException e) {
// recover using `e.getFailures()`
}
The underlying mechanism for tryClose
is tryForeach
. It is the same, exception instead of calling AutoCloseable#close()
,
it will call a function of your choosing.
val ints: Seq[Int] = null
try {
ints.tryForeach(i => if (i == 0) throw new Exception())
} catch {
case e: TryForeachException[AutoCloseable] =>
// recover using `e.failures`
}
final Iterable<Object> closeables = null;
try {
TryIterable.tryForEach(
(Object o) -> {
if (isInvalid(o)) {
throw new RuntimeException();
}
},
closeables);
} catch (TryForeachException e) {
// recover using `e.getValues()`
}
There are also specialized methods for primitives.
final int[] ints = null;
try {
TryIterable.tryForEachInt(
(int i) -> {
if (isInvalid(i)) {
throw new RuntimeException();
}
},
ints);
} catch (TryForeachException e) {
// recover using `e.getFailures()`
}
TryForeachException
now directly ties the throwable to the value that caused it. Before you had to iterate through the cause and its suppressed exceptions.