Will the #Validated annotation in the DAO Interface help at all? - spring

I have seen a lot of #Validated annotations in the DAOs interface that I didn't write. For example:
#Validated
public interface CompanyDAO extends BaseDAO<Company> {
public List<Company> list();
What behaviour should I expect from this:
Validating all the objects passed to the DAO before saving them into the database?
Validating all the objects that the DAO retrieves from the database?
Both of them?
Nothing at all. This annotation should not be placed in DAO interfaces.

Just a few pointers which you might not be aware of:
8.8 Spring Validation of 8. Validation, Data Binding, and Type Conversion in the manual specifies that
In order to be eligible for Spring-driven method validation, all target classes need to be annotated with Spring’s #Validated annotation, optionally declaring the validation groups to use. Check out the MethodValidationPostProcessor javadocs for setup details with Hibernate Validator and Bean Validation 1.1 providers.
MethodValidationPostProcessor says
Applicable methods have JSR-303 constraint annotations on their parameters and/or on their return value (in the latter case specified at the method level, typically as inline annotation), e.g.:
public #NotNull Object myValidMethod(#NotNull String arg1, #Max(10) int arg2)
Target classes with such annotated methods need to be annotated with Spring's Validated annotation at the type level, for their methods to be searched for inline constraint annotations. Validation groups can be specified through #Validated as well. By default, JSR-303 will validate against its default group only.
So, maybe the answer to your question
What behaviour should I expect
is: Whatever constraints are given in the code.

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.

Does Spring #transaction work on a concrete method of abstract class

From spring reference doc
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java
annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
Though it only talks about interfaces, abstract classes are considered as non-concrete as well.
So if i have an abstract class
public abstract class BaseService{
//here is a concrete method
#Transactional
public void updateData{
//do stuff using dao layer
}
and a concrete class which extends the class
public class SpecialService extends BaseService{
//body of class
}
Now if i call specialService.updateData() from my controller class will it be transactional?
Granting that you have actually configured Spring transaction management correctly, using #Transactional on an abstract superclass will work, since #Transactional is itself annotated with #Inherited and from it's Javadoc we have:
Indicates that an annotation type is automatically inherited. If an
Inherited meta-annotation is present on an annotation type
declaration, and the user queries the annotation type on a class
declaration, and the class declaration has no annotation for this
type, then the class's superclass will automatically be queried for
the annotation type. This process will be repeated until an annotation
for this type is found, or the top of the class hierarchy (Object) is
reached. If no superclass has an annotation for this type, then the
query will indicate that the class in question has no such annotation.
Note that this meta-annotation type has no effect if the annotated
type is used to annotate anything other than a class. Note also that
this meta-annotation only causes annotations to be inherited from
superclasses; annotations on implemented interfaces have no effect.
To actually see that #Transactional is annotated with #Inherited check out it's Javadoc

Bean Validation for POST requisition in JAX-RS with Jersey implementation

I'm using the Jersey implementation for JAX-RS, and I was looking for an example where I can use the Bean Validation in POST requisitions. I have this operation, for example:
#POST
#Path("document/annotations/save")
#Produces("application/json")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Map<String, Object> saveAnnotation(
#FormParam("user") String userStr,
#FormParam("documentId") String documentId,
#FormParam("documentPage") Integer documentPage,
#FormParam("annotationContent") String annotationContent,
#FormParam("annotationId") Long annotationId,
#FormParam("isMobile") Boolean isMobile) { // the code... }
I wanna use validations constraints (#NotNull, #Pattern, etc) for each method param. I saw this doc where they're using the Seam Framework to do that.
Currently, I'm trying to use the javax.validation implementation to validate my requests, but it doesn't working.
Is there a way to use the JSR-303 specification with JAX-RS?
Tnks.
This is currently not possible using Jersey; one possible alternative is to write a customer resource filter and bind to the #NotNull, etc. annotations.
It would be simpler if it was encapsulated in a resource class because you could then bind to a #Valid annotation on your method and validate the bean in one shot.
Because JSR-303 is designed to deal with beans and not a collection of parameters then it ends up being very verbose when you try to bend it to your will.
IMHO it's better not to keep validation inside your class anyway and to either use the pipes and filters pattern, i.e. ContainerRequestFilter, or to use something like AspectJ as #Willy suggested.
It's possible. See docs for latest Jersey
https://jersey.java.net/documentation/latest/bean-validation.html#d0e9380
https://jersey.java.net/documentation/latest/bean-validation.html

How do Spring annotations work?

Motivation
As a follow-up to my previous questions on classloading
How is the Classloader for a class chosen?
How Classloader determines which classes it can load?
Where does bytecode injection happen?
I'm curious about how do annotations work in a popular Spring framework.
Possible solution
As far as I understand, two mechanisms might be used:
1. Bytecode injection on classloading
Spring could use its own classloader to load required classes. At runtime, when the class is loaded and Spring determines it has some appropriate annotation, it injects bytecode to add additional properties or behavior to the class.
So a controller annotated with #Controller might be changed to extend some controller base class and a function might be changed to implement routing when annotated with #RequestMapping.
#Controller
public class HelloWorldController {
#RequestMapping("/helloWorld")
public String helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
}
2. Reflection used for instantiation
#Autowired could be read by reflection at runtime by the BeanFactory to take care of the instantiation order and instantiate the configured properties.
public class Customer
{
private Person person;
#Autowired
public void setPerson(Person person) {
this.person = person;
}
}
Question
How do Spring annotations really work?
Spring is open source so you don't need to figure how it work, look inside:
RequestMapping annotation is handled by RequestMappingHandlerMapping, see getMappingForMethod method.
Autowired annotation is handled by AutowiredAnnotationBeanPostProcessor, see processInjection method.
Both use reflection to get annotation data and build the handler mapping info in the first case or populate the bean in the second one.
Spring context understand annotation by set of classes which implements bean post processor interface. so to handle different type of annotation we need to add different annotation bean post processors.
if you add <context:annotation-config> in you configuration xml then you need not to add any annotation bean post processors.
Post processor provide methods to do pre and post processing for each bean initialization.
you can write your own bean post processors to do custom processing by created a bean which implements BeanPostProcessor interface.

Resources