#Valid annotation works with #RequestBody but not with RequestEntity - spring

Spring MVC's #Valid annotation works as expected with #RequestBody arg but it's not working with RequestEntity arg. Is there anyway to get it working?

#Valid is not from Spring MVC, #Valid relies under package javax.validation; Maybe you meant #Validated. Nevertheless #RequestBody and RequestEntity have to be taken differently in terms of validation.
#RequestBody is used in a Spring MVC Controller to annotate the payload of a request, but has nothing to do with validation of this incoming payload object.
RequestEntity is used to wrap the actual payload in preparation for a new request. No validation is applied when you create a new RequestEntity.

The #Valid annotation worked with #RequestBody because the RequestResponseBodyMethodProcessor (which does the work of resolving this handler argument) looks for the presence of #Valid and, if it is found, applies all matching validators it finds in the WebDataBinder.
On the other hand, ResponseEntity arguments are resolved by HttpEntityMethodProcessor, which does not perform validation even if the argument is annotated with #Valid.
You can, of course, perform validation manually in the handler method by invoking a validator of your choosing. It’s certainly possible, although you might want to consider a different approach.

Related

Does #Valid work without #Validated on #RestController?

In following blog entry.
https://www.baeldung.com/spring-boot-bean-validation
The author mentioned about how Spring Boot works with #Valid annotation.
#RestController
public class UserController {
#PostMapping("/users")
ResponseEntity<String> addUser(#Valid #RequestBody User user) {
// persisting the user
return ResponseEntity.ok("User is valid");
}
// standard constructors / other methods
}
When Spring Boot finds an argument annotated with #Valid, it automatically bootstraps the default JSR 380 implementation — Hibernate Validator — and validates the argument.
Is it true that #Valid works as expected on #RestController without #Validated?
Then what kind of stereo types required to be explicitly annotated with #Validated?
Yes #Valid will work without #Validated in #RestController.
In Spring, we use JSR-303's #Valid annotation for method level
validation. Moreover, we also use it to mark a member attribute for
validation. However, this annotation doesn't support group validation.
Groups help to limit the constraints applied during validation. One
particular use case is UI wizards. Here, in the first step, we may
have a certain sub-group of fields. In the subsequent step, there may
be another group belonging to the same bean. Hence we need to apply
constraints on these limited fields in each step, but #Valid doesn't
support this. In this case, for group-level, we have to use Spring's
#Validated, which is a variant of this JSR-303's #Valid. This is used
at the method-level. And for marking member attributes, we continue to
use the #Valid annotation.
You can read more about this in this link.

Spring boot: #Valid not working with #RequestHeader

I'm really struggling to combine #Valid with #RequestHeader.
Might this be not supported or is there a way to enable it? I couldn't find useful information about that...
When I annotate the whole controller with #Validated it works, so it is not a big issue. However, I feel like it should work with #Valid as well, so I wanted to know if I'm missing something here.
Code example:
#GetMapping("/validationControllerHeader")
public String validationControllerHeader(#Valid #RequestHeader #Pattern(regexp = "[a-z]{3}[0-9]+") String someheader) {
return someheader;
}
I'm using #Valid in the same test controller for query parameters and body validation too and there it works, so the issue is only present with headers.
Using spring boot 2.3.1.RELEASE
You are definitely supposed to use #Validated in your controller class, as it indicates that the validation is meant to be performed in that class. From the documentation:
To be eligible for Spring-driven method validation, all target classes need to be annotated with Spring’s #Validated annotation, which can optionally also declare the validation groups to use.
And, as you are using #Pattern (which is a Bean Validation annotation), you don't need #Valid.

Spring annotations #ModelAttribute and #Valid

What are the advantages of using #ModelAttribute and #Valid?
Which are the differences?
Is it possible to use them together?
#ModelAttribute is used to map/bind a a method parameter or method return type to a named model attribute. See #ModelAttributes JavaDoc. This is a Spring annotation.
#Valid is an annotation that marks an object for JSR-303 bean validation. See #Valids JavaDoc. It is part of JavaEE 6, but I think Hibernate has an earlier implementation that most people use instead.
The advantage of using #ModelAttribute is that you can map a form's inputs to a bean. The advantage of #Valid is that you can utilize JSR-303 bean validation to ensure that the bean that is made is validated against some set of rules.
Yes you can use #ModelAttribute and #Valid together.
The best way to transfer data from a form (sic View) to the a Model object is to follow the typical/traditional MVC design pattern using Spring. My personal preferred way is to have a form in a JSP with Spring JSTL <form:*> tags, with a modelAttribute set. On the Controller, have a handler to accept the POST from the form that has a matching #ModelAttribute that is a bean that represents the form's input. I would then pass that "Form Bean" to a service layer to do some things, including translating the "Form Bean" into any models if needed (not necessary if the form is creating your model objects directly) and saving/updating/etc via a DAO. This is but one way to do things, but it's probably the bulk of what I do with Spring in my day-to-day job.
I would highly recommend reading the Spring reference materials and following the tutorials. The reference materials are very well written, easy to follow, and includes lots of examples on the various ways you can do things in Spring, and there are usually quite a few options on how you do things in Spring.
please check the below part fro spring reference documentation:
In addition to data binding you can also invoke validation using your own custom validator passing the same BindingResult that was used to record data binding errors. That allows for data binding and validation errors to be accumulated in one place and subsequently reported back to the user:
#RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(#ModelAttribute("pet") Pet pet, BindingResult result) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}
// ...
}
Or you can have validation invoked automatically by adding the JSR-303 #Valid annotation:
#RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)
public String processSubmit(#Valid #ModelAttribute("pet") Pet pet, BindingResult result) {
if (result.hasErrors()) {
return "petForm";
}
// ...
}

How do I use #Valid with Spring MVC's #RequestBody parameters?

I'm having an issue with using #Valid on a parameter to a handler method on my #Controller. My code looks like this:
#RequestMapping(value=BIBBLE_BOBBLE_URI_PATTERN + "/widgets", method=RequestMethod.POST)
#ResponseBody
#ResponseStatus(HttpStatus.CREATED)
public Widget saveNewWidget(
#PathVariable final String username,
#PathVariable final String bibbleBobbleName,
#Valid #RequestBody final Widget widget,
final BindingResult results,
final HttpServletRequest request,
final HttpServletResponse response)
where Widget is the class for one of my domain objects. I'm using the #RequestBody annotation to indicate that the payload of the request maps to widget (in my tests, the requests are JSON, though Jackson is on my classpath so I could also use XML).
As you can see, the BindingResult parameter follows directly after the Widget parameter, but I get the following error:
java.lang.IllegalStateException: Errors/BindingResult argument declared without preceding model attribute. Check your handler method signature!
How do I apply the #Valid annotation to a #RequestBody parameter and then get the results?
P.S. I'm using annotation-driven to handle wiring up the controllers, do content-negotiation, etc.
Are you using Spring 3.1? It is a newly added feature in Spring version 3.1. Please see Validation For #RequestBody Method Arguments
This is an issue in spring 3.0 and it is fixed in 3.1 M2.
https://jira.springsource.org/browse/SPR-6709
If you are using spring 3.0, based on some threads and extensive reading, here is the best approach for this problem. An aspect oriented approach so that we can back out when you upgrade it to the version of spring which fixes this issue.
An aspect which intercepts calls to method which uses #RequestMapping annotation and for each parameter which has #Valid annotation on it, call the corresponding validator in the aspect.

Handling JSON and form data request with Spring MVC

I'm working on simple Spring-MVC application and I love new Spring REST features. I'd like to use the same method to process regular form and JSON data. It seems to be a little tricky, however. For example, method
public #ResponseBody String process(#RequestBody Bean bean);
will work for JSON request (Content-type: application/json), and
public #ResponseBody String process(Bean bean);
will match request with Content-type: application/x-www-form-urlencoded.
These methods are obviously will have almost the same content, so I'd prefer to avoid such duplication. With Jersey it's possible with #Consumes annotations, but I can't figure out how to do it with Spring.
First, the above declaration won't compile, because you are having duplicate signature.
Btw, #Consumes wouldn't help, I think, because it only designates what content type the method can handle.
In spring you can specify the content-type with
#RequestMapping(headers="Content-Type=application/json")
Just add #RestController annotation for the controller class.

Resources