Within the framework and portfolio projects we often need to deal with checked exceptions inside the body of a Function
, Supplier
, Consumer
, etc. This usually involves writing try
/catch
blocks inside the body. Since exception handling is usually also handled by the framework, it would be nice if we could offer Throwing...
versions of common functional interfaces that do the wrapping for us.
Comment From: quaff
Please consider throwing generic exception like this
@FunctionalInterface
public interface CheckedFunction<T, R, E extends Throwable> {
R apply(T t) throws E;
}
Comment From: sbrannen
@quaff, can you please expound on your proposal with a rationale for needing the generic type declaration for the exception?
Comment From: sbrannen
it would be nice if we could offer
Throwing...
versions of common functional interfaces that do the wrapping for us.
I agree: such types can be very useful.
I also agree with the Throwing*
naming convention. Though I noticed you've introduced Throwable*
types in your commit.
I think we should go with Throwing*
. For example, ThrowableSupplier
implies that the supplier supplies a Throwable
, like a StringSupplier
would supply a String
.
Furthermore, the Supplier
itself is not "throwable" since it does not implement Throwable
.
What we're really talking about is a "supplier that is capable of throwing a checked exception", but we cannot convert that to a type name because it's simply too long: CheckedExceptionThrowingSupplier
. If we go with ThrowingSupplier
, that's succinct and in line with the naming convention used in several other open source projects -- for example, Spring Data, JUnit, AssertJ, Kotlin internals, some JDK internals, etc..
Comment From: quaff
@quaff, can you please expound on your proposal with a rationale for needing the generic type declaration for the exception?
@sbrannen For example we can throw Throwable inside lambda
@Aspect
public class Instrumentation {
@Around("execution(* *.*(..))")
public Object timing(ProceedingJoinPoint pjp) throws Throwable {
return Tracing.execute(pjp, ProceedingJoinPoint::proceed);
}
}
public class Tracing {
public static <T, R> R execute(T input, CheckedFunction<T, R, Throwable> function) throws Throwable {
// create new span
try {
return function.apply(input);
} finally {
// finish span
}
}
}
Comment From: quaff
some JDK internals
Many projects use Checked*
, for example vavr
elasticsearch
Comment From: sbrannen
@sbrannen For example we can throw Throwable inside lambda
The Spring Framework typically tries to avoid throwing Throwable
because that makes error handling more complex, and we don't want to have to catch Throwable
and then decide if the exception should really be swallowed/handled/rethrown (e.g., OOME).
The commit Phil pushed declares Exception
in the throws
clauses in order to allow lambdas to throw unchecked and checked Exception
types, and I think that is adequate for the needs of the framework.
Many projects use
Checked*
, for examplevavr
elasticsearch
Indeed, that would be another option, but we've gone with Throwing*
.