Difference between @Valid and @Validated in Spring
Asked Answered
W

7

186

Spring supports two different validation methods: Spring validation and JSR-303 bean validation. Both can be used by defining a Spring validator that delegates to other delegators including the bean validator. So far so good.

But when annotating methods to actually request validation, it's another story. I can annotate like this

@RequestMapping(value = "/object", method = RequestMethod.POST)
public @ResponseBody TestObject create(@Valid @RequestBody TestObject obj, BindingResult result) {

or like this

@RequestMapping(value = "/object", method = RequestMethod.POST)
public @ResponseBody TestObject create(@Validated @RequestBody TestObject obj, BindingResult result) {

Here, @Valid is javax.validation.Valid, and @Validated is org.springframework.validation.annotation.Validated. The docs for the latter say

Variant of JSR-303's Valid, supporting the specification of validation groups. Designed for convenient use with Spring's JSR-303 support but not JSR-303 specific.

which doesn't help much because it doesn't tell exactly how it's different. If at all. Both seem to be working pretty fine for me.

Williwaw answered 23/3, 2016 at 8:41 Comment(4)
Might be interesting: #18911654Pruter
"supporting the specification of validation groups" is a very explicit statement.Akeylah
I should think that Valid is tightly coupled with JSR 303 validations (NotNull, etc). Whereas you can create other validation/groups and have them checked in Validated.Unfrequented
@zeroflagL, true, but since I have never used it, I missed the point and fixated instead on the “not JSR-303 specific” part. Now it's clear.Williwaw
D
120

As you quoted from the documentation, @Validated was added to support "validation groups", i.e. group of fields in the validated bean. This can be used in multi step forms where you may validate name, email, etc.. in first step and then other fields in following step(s).

The reason why this wasn't added into @Valid annotation is because that it is standardized using the java community process (JSR-303), which takes time and Spring developers wanted to allow people to use this functionality sooner.

Go to this jira ticket to see how the annotation came into existence.

Dame answered 23/3, 2016 at 9:12 Comment(0)
F
206

A more straight forward answer. For those who still don't know what on earth is "validation group".

Usage for @Valid Validation

Controller:

@RequestMapping(value = "createAccount")
public String stepOne(@Valid Account account) {...}

Form object:

public class Account {

    @NotBlank
    private String username;

    @Email
    @NotBlank
    private String email;

}

Usage for @Validated Validation Group
Source: http://blog.codeleak.pl/2014/08/validation-groups-in-spring-mvc.html

Controller:

@RequestMapping(value = "stepOne")
public String stepOne(@Validated(Account.ValidationStepOne.class) Account account) {...}

@RequestMapping(value = "stepTwo")
public String stepTwo(@Validated(Account.ValidationStepTwo.class) Account account) {...}

Form object:

public class Account {

    @NotBlank(groups = {ValidationStepOne.class})
    private String username;

    @Email(groups = {ValidationStepOne.class})
    @NotBlank(groups = {ValidationStepOne.class})
    private String email;

    @NotBlank(groups = {ValidationStepTwo.class})
    @StrongPassword(groups = {ValidationStepTwo.class})
    private String password;

    @NotBlank(groups = {ValidationStepTwo.class})
    private String confirmedPassword;

}
Fanchet answered 30/8, 2018 at 8:59 Comment(2)
To keep in mind. \@Validated doesn't validate nested DTOs, you need to put \@Valid on those nested fields (Account#user for example) in order to propagate validation for them.Doublethink
@Validated also can be used on classes to enable validation of @Min/@Max that reside next to method arguments of that class, which doesn't happen by default. public void update(@Min(10) Long count) {}Doublethink
D
120

As you quoted from the documentation, @Validated was added to support "validation groups", i.e. group of fields in the validated bean. This can be used in multi step forms where you may validate name, email, etc.. in first step and then other fields in following step(s).

The reason why this wasn't added into @Valid annotation is because that it is standardized using the java community process (JSR-303), which takes time and Spring developers wanted to allow people to use this functionality sooner.

Go to this jira ticket to see how the annotation came into existence.

Dame answered 23/3, 2016 at 9:12 Comment(0)
B
23

In the example code snippets of the question, @Valid and @Validated make no difference. But if the @RequestBody is annotated with a List object, or is a string value annotated by @RequestParam, the validation will not take effect.

We can use the @Validated's method-level validation capability to make it work. To achieve this, the key point is to place @Validated on the class. This may be another important difference between @Valid and @Validated in spring framework.

Refrence

Ballonet answered 28/8, 2019 at 15:52 Comment(4)
Could you explain why the annotation has no effect for List objects? I assume that this will also not work for other collections like Map? Maybe you could give me a more detailed explanation in my question: #60168461Falsecard
@Falsecard As you wishBallonet
What I was looking for!Hy
This is actually a more important distinction than validation groups. No one uses validation groups.Flogging
B
12

Just for simplifying:

@Validated annotation is a class-level annotation that we can use to tell Spring to validate parameters that are passed into a method of the annotated class.

and

@Valid annotation on method parameters and fields to tell Spring that we want a method parameter or field to be validated.

Brownlee answered 22/7, 2022 at 17:31 Comment(0)
A
3

besides above, you can only apply @Valid on a domain/field for nested validation, not with a @validated.

Apoloniaapolune answered 18/6, 2019 at 2:26 Comment(0)
P
1

@Validated at the class level of @Controller/@RestController is used to validate the @PathVariable/@RequestParam parameters

While @Valid won't work for @PathVariable/@RequestParam parameters

If validation fails for @PathVariable/@RequestParam it throws ConstraintViolationException

Parturition answered 4/2 at 13:16 Comment(1)
G
-2

@Validated can be used for a class:

@Validated
public class Person {
    @Size(min=3)
    private String name;
...
Gdynia answered 16/8, 2021 at 11:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.