Email address validation isn't magic and nor is annotating fields to give more context about what they're meant to contain.

The article author believes everything should be done with types. But Java has always been able to represent an EmailAddress type. It's not like the Quarkus guys don't know about strong static typing! Bean Validation exists because:

1. Every tool knows what a string is. Very few know what your custom email address type is. In theory you can solve this with sub-typing, or duck typing, etc. But in Java the String class is final, so you can't extend from it. This has definitely had big advantages over the years - there's no proliferation of custom utility string types, and new Java versions could optimize the internal representation aggressively. It's not at all clear that Java would be better if String was an open class.

2. Bean Validation lets you validate every field at once and collect the errors together. This is extremely helpful for user interfaces where you want to be able to copy user data into an object, validate it, and then return all the problems to the UI for rendering next to the form. With the type approach he gives you'd get exactly one problem followed by an exception. The user would fix it, re-submit the form or re-execute the tool, and then get the next problem. Painful! Ditto for APIs where you want to de-serialize JSON into objects, validate them all in one go and return a single error response if there are issues.

3. Bean Validation is designed to be applied to both database entity and GUI model (e.g. config) objects, though it can be used for anything. Immutable types are useless for this use case because the database and GUI are both fundamentally about mutable state. The DB layer can generate far more optimized SQL and thus far more optimal DB resource usage if it can record what's changing (which requires some sort of "clever" stateful object), and for the UI you need to be able to hold invalid data somewhere - ideally in your model object, so the user's data can both be held in the model and also trigger validation errors.

4. It can also be used with parameters and return types on methods (with sufficient framework support from your implementation). This lets you add constraints to implementations in an API compatible way. Changing types wouldn't allow for that.

The author should really just read the intro to the Jakarta Bean Validation spec, which lays out the rationale quite clearly:

https://jakarta.ee/specifications/bean-validation/3.0/jakart...

Does anyone worry about whether reading a value out of a config object will launch rockets? No. The type system could express this, but the value of doing so would be very low. It is obvious from context. The reason it uses interfaces is because, if we check the docs:

"Under some circumstances, some data sources may change dynamically. The changed values should be fed into the client without the need for restarting the application"

If you implement config handling in the FP way he wants then a change to any part of the config requires rebuilding the entire object graph representing the entire configuration, and then re-plumbing that all through the rest of your (presumably immutable) set of objects. What you'd intuit should be a very fast operation with little memory overhead can suddenly require re-initializing large chunks of your app. A functional programmer might simply assert that being able to mutate configuration at runtime is a bad feature, but in the real world we do this sort of thing all the time and being able to handle it well is a useful feature of a config library.

The core disagreement here isn't actually anything to do with Java. More or less any imperative language would attract the ire of this author. What he's upset about is the existence of libraries and frameworks designed for mutability. But, mutability is inherent to the world. You can try to manage and constrain it but you can't remove it and sometimes you have to embrace it. That's not "Java culture", it's just life.