So Java's checked exceptions force you to write verbose and pointless code in all the wrong places (the "in the middle" code that can't handle and doesn't care about the exception).
It doesn't, you can just declare that the function throws these as well, you don't have to handle it directly.
This is annoying enough to deal with in concrete code, but interfaces make it a nightmare.
To solve this, Rust does allow you to just Box<dyn Error> (or equivalents like anyhow). And Go has the Error interface. People who list out all concrete error types are just masochists.
It took until version 1.13 to have something better, and even now too many people still do errors.New("....."), because so is Go world.
A problem easily solved by writing business logic in pure java code without any IO and handling the exceptions gracefully at the boundary.