Not sure if you're asking about Spring or my workaround.
Is Spring worth it? The only reason I'd reach for it over something like http://sparkjava.com/ is because of its good integration with https://swagger.io/tools/swagger-ui/. It's the easiest way I know to help out your front-end devs.
Whether you like the workaround really depends on how much you dislike Spring, and how much you buy into that whole frameworks-bad-libraries-good argument.
As an example of a feature, here's how Spring might validate receiving a book as a POST body. It's as simple as adding @Valid:
@PostMapping("/books")
Book newBook(@Valid @RequestBody Book newBook) {
return repository.save(newBook);
}
My thoughts on the above:
1) Did i import the right @Valid. There's no compile-time checking, I'll only know it works by trying it.
2) How can I test it? Not in a unit test. Calling newBook and expecting @Valid to fire is a rookie error. I need to spin up some Spring machinery to be able to test anything.
3) Is validation enabled? How do I know?
4) OK, the validator appeared to work in test. Do I have the same Spring config in the test and prod profiles (check yaml, environment variables, CLI args, and @Config objects)? Does validation also work in prod?
5) What does it look like when it rejects input? I assume Spring will return a 400, but what's the error message. Can I set it? Is it plaintext or json? Is it logged? Is it metred? How?
6) Its return type is Book. It always returns a Book? Not an Either<Error, Book>? Not a CompletableFuture<Book>?
7) It accepts a Book. This means that an INVALID BOOK IS INSTANTIATED, and then checked (I think?) after instantiation. This means when you write your Book class, you need to deliberately make invalid state representable, so that Spring has something to validate!
Here's the gist of what I'd write instead. (Not a direct comparison, I added features I wouldn't know how to integrate with @Valid)
@PostMapping("/books")
Response<Book> newBook(@RequestBody String strBook) {
return Book.parse(strBook)
.handle( (Book book) -> {
metrics.something();
logger.something();
repository.save(book)
.map(Response::new);
},
(Error err) -> {
metrics.registerError(err);
logger.logError(err);
return Response.of(400, "Invalid book submitted: " + err.msg);
});
}
The method that I wrote can be 'just run' and tested - no need to fire up Spring. You only have a Book immutable and type-safe again.
I didn't detail the workaround, but it's essentially this:
//SpringBookController extends BookController
@PostMapping("/books")
Response<Book> newBook(@RequestBody String strBook) {
super.newbook(strBook);
}
// BookController
Response<Book> newBook(String strBook) {
... // basically the big example from above minus the @RequestBody and @PostMapping
}