← Back to context

Comment by samus

2 days ago

Spring has a special error handling strategy where the whole request is allowed to fail, punting error handling off to the caller.

A lot of code that throws checked exceptions is simply dangerous to use with Java streams because the execution order of stream operation is not obvious and possibly non-deterministic. For this reason, streams were never intended to also handle errors. Reactive frameworks are much better at that.

The UncheckedIOException is for situations where you really cannot throw a checked exceptions, such as inside an iterator. Which might lead to ugly surprises for the API user;

> A lot of code that throws checked exceptions is simply dangerous to use with Java streams because the execution order of stream operation is not obvious and possibly non-deterministic.

From the type system PoV, they could have just written something like `interface Runnable<X> { void run() throws X; }` and now `forEach` would have been written like `<X> void forEach(Runnable<X> r) throws X`. And repeat that for all stream operations, promoting `X` everywhere, so if your mapper function throws SQLException, the whole pipeline will throw it.

It even works today with some limitation (there's no way for `X` to get value of `SQLException|IOException` union type), but with some generic improvements it could work.

But they decided to not touch this issue at all. So now people will fool compiler with their tricks to throw checked exceptions like unchecked (or just wrap them with UncheckedXxxException everywhere, I prefer that approach).

  • At the risk of repeating myself: streams were simply never designed with error handling in mind. Aborting everything at the first error is just the most simplistic error handling strategy. Reactive streams frameworks should be preferred for this.