Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Throwable functional interfaces #28417

Closed
philwebb opened this issue May 5, 2022 · 6 comments
Closed

Add Throwable functional interfaces #28417

philwebb opened this issue May 5, 2022 · 6 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@philwebb
Copy link
Member

philwebb commented May 5, 2022

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.

@philwebb philwebb self-assigned this May 5, 2022
@philwebb philwebb added the type: enhancement A general enhancement label May 5, 2022
@philwebb philwebb added this to the 6.0.0-M4 milestone May 5, 2022
@quaff
Copy link
Contributor

quaff commented May 5, 2022

Please consider throwing generic exception like this

@FunctionalInterface
public interface CheckedFunction<T, R, E extends Throwable> {

	R apply(T t) throws E;

}

@sbrannen
Copy link
Member

sbrannen commented May 5, 2022

@quaff, can you please expound on your proposal with a rationale for needing the generic type declaration for the exception?

@sbrannen
Copy link
Member

sbrannen commented May 5, 2022

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..

@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label May 5, 2022
@quaff
Copy link
Contributor

quaff commented May 6, 2022

@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
		}
	}
}

@quaff
Copy link
Contributor

quaff commented May 6, 2022

some JDK internals

Many projects use Checked*, for example vavr elasticsearch

@sbrannen
Copy link
Member

sbrannen commented May 6, 2022

@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 example vavr elasticsearch

Indeed, that would be another option, but we've gone with Throwing*.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants