Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bean validation group sequence not working

I'm using spring 4.1, hibernate validator 5.1.3 for my project. I've been trying to get the GroupSequence to work from last 2 days. I've referred the validation doc, blogs and a few questions posted on stackoverflow.

Please see the below class. When I remove the GroupSequence and groups from the annotations, all the validation messages come up together, i.e, all the checks on name and other fields are fired together. Lets say for name field - I want @NotBlank and @Size to be validated first, then the name should be matched with the Pattern and at last it should be checked for @UniqueName because of the database calls.

For that, I created the GroupSequence, as suggested in the docs and answers. But when the validations are fired, only @NotBlank and @Size are fired for name. When I remove the groups value from the remaining annotations, they start working but all the error messages are shown at once, which I don't want.

I want the annotation specified with groups First.class are fired together and before Second.class validations. I don't get why the validations specified with groups aren't getting fired.

Can someone please guide me.


@GroupSequence({MyForm.class, OrderedChecks.class})
public class MyForm {

  @NotBlank
  @Size(min = 2, max = 40)
  @Pattern(regexp = "^[\\p{Alnum} ]+$", groups = First.class)
  @UniqueName(groups = Second.class)//Custom validation
  private String name;

  @NotBlank
  @Size(min = 2, max = 40)
  private String url;

  @NotBlank
  @Size(max = 100)
  private String imagePath;

  //Custom Validation
  @CheckContent(acceptedType = <someString>, allowedSize=<someval>, dimensions=<someval> groups = Second.class)
  private MultipartFile image

...
}

@GroupSequence(value = {Default.class, First.class, Second.class})
public interface OrderedChecks {}

@Controller
@RequestMapping(value = "/myForm")
public class MyFormController {

    @RequestMapping(method = POST)
    public String completeSignUp(@Valid @ModelAttribute("myForm") final MyForm myForm,
                            BindingResult result, RedirectAttributes redirectAttributes, Model model) {

        if(result.hasErrors()) {
            model.addAttribute(companyDetailsForm);
            //ERROR_VIEW="myForm";
            return ERROR_VIEW;
        }
       // Doing something else.
      return <success view>;
   }
}
like image 631
jay Avatar asked Dec 23 '14 19:12

jay


People also ask

What is the difference between @valid and @validated?

The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.

What does @validated do?

@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. @Valid annotation on method parameters and fields to tell Spring that we want a method parameter or field to be validated. Hope this helps.

What is ConstraintValidatorContext?

public interface ConstraintValidatorContext. Provides contextual data and operation when applying a given constraint validator. At least one ConstraintViolation must be defined (either the default one, of if the default ConstraintViolation is disabled, a custom one).

What is @validated in spring boot?

When Spring Boot finds an argument annotated with @Valid, it automatically bootstraps the default JSR 380 implementation — Hibernate Validator — and validates the argument. When the target argument fails to pass the validation, Spring Boot throws a MethodArgumentNotValidException exception.


1 Answers

Use Spring's @Validated instead of @Valid. This will allow you specify the group and control the sequence.

Change your controller method to:

@RequestMapping(method = POST)
public String completeSignUp(@Validated(OrderedChecks.class) @ModelAttribute("myForm") final MyForm myForm,
                        BindingResult result, RedirectAttributes redirectAttributes, Model model) {
...
}

Note that you don't need @GroupSequence({MyForm.class, OrderedChecks.class}) on top of MyForm bean.

like image 159
Khalid Avatar answered Nov 08 '22 18:11

Khalid