Suppose I have this very simple Book
model that I want to validate that its title is not blank.
public class Book {
@NotBlank
public String title;
}
On the service layer I perform validation like this (using the Hibernate validator quarkus-hibernate-validator
):
public class BookService {
public void validateBook(@Valid Book book) {
// your business logic here
}
}
My resource is:
@Path("/books")
public class BookResource {
@Inject
BookService bookService;
@Path("/service-method-validation")
@POST
public String tryServiceMethodValidation(Book book) {
try {
bookService.validateBook(book);
return "Book is valid! It was validated by service method validation.";
} catch (ConstraintViolationException e) {
return "Book invalid";
}
}
@Path("/private-method-validation")
@POST
public String tryMethodValidation(MessedTitleBook book) {
try {
Book book = translate_title(book);
method(book);
return "Book is valid! It was validated by method validation.";
} catch (ConstraintViolationException e) {
return "Book invalid";
}
}
private void method(@Valid Book book) {
// your method logic here
}
}
When I post a Book
on the /service-method-validation
everything works as expected and my book
gets checked by the service method for violations.
Now suppose I have a second endpoint (/method-validation
) which receives another object, MessedTitleBook
, (think of it as book that has the author embedded on the title as well) on which I need to perform a translation to remove the author and then pass that book to a private method to perform some actions. In the private method I need to check that the translated book is valid but the @Valid
annotation doesn't seem to work on private methods.
Question:
- Does
@Valid
work on private methods? If not, please provide me a resource to study. - Is there a way to achieve validation automatically without having to do manual validation, i.e. inject
validator
and performvalidator.validate(book)
?
EDIT
I forgot to mention that changing the method scope from private to public makes the validation work.
CodePudding user response:
Here you have a guide about Javax Validation api, javax validation will be invoked automatically on any public method with a parameter that has the @Valid
annotation.
Its quite flexible though because you can choose to use this validation or the manual one, which you already found.
It is possible to write custom validator instead of using annotations for more complex validations.
As for your question, you already know that it works in public methods.
Javax validation has an integration with Jax-RS which allows you yo annotate your rest methods parameter with the @Valid
annotation and it automatically will generate a 400 response with a detailed summary of the errors in the model.
Here its also a quarkus guide.
CodePudding user response:
I can't vouch for this being the 100% correct answer for the library you used, but I'd go ahead and assume it works similarly to the way Spring handles such validation.
Short answer to your question 1.: No, it doesn't work.
The way this kind of validation is usually handled is by the concept of AOP Proxy instances, which sort of wrap around your actual object instances and intercept all calls made to it, and that way being able to add additional logic to the execution, like validating parameters, before passing the call on to the actual object instance. This means that the AOP proxy instance would (and should) only be able to handle the public interface of the class.
Think about it, once the call has "made it" to the actual implementation instance, your instance will then make the call to the private method "internally" inside that instance. That way the AOP proxy has no way to intercept that call to add its logic that you want.
I would assume that there might be some way to still achieve it, with the help of some very heavy usage of Java Reflection, but I would advise against that and go the route with the injected validator
instance instead.
Or, as you already described in your example, a sort of validator service that handles the validation on public interfaces.