Java – Bean validation group sequence not working

bean-validationhibernate-validatorjavaspring-mvc

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>;
   }
}

Best Answer

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.

Related Topic