making/yavi

Self-validation on request objects

rogersantos77 opened this issue · 4 comments

First of all congratulations for this repository, I'm a fan of fluent resources.

I was wondering how to force self-validation on request objects in controllers. As Bean Validation does, but without those annotations

Is there any way to auto-validate them without invoking some "validate" method manually? (An example could be a service locator that matches the incoming object with the validator).

Can you elaborate "self-validation" ?

Any example code would be helpful

My last experience with libraries for this purpose was FluentValidation in C# (https://github.com/FluentValidation/FluentValidation.AspNetCore#aspnet-core-integration-for-fluentvalidation).

In this documentation above, there is a load at application startup (Automatic Validation) that matches the entry object class (in the controller) with its validator, forcing self validation and being optional to call a "validate" method.

Do you mean using @Valid or @Validated in a Spring MVC controller method?

making commented

Since Spring 6.1, it became easier to use @Valid/@Validated with Spring MVC
spring-projects/spring-framework#29890

as follws:

package com.example.validatingforminput;

import am.ik.yavi.builder.ValidatorBuilder;
import am.ik.yavi.core.Validator;

public class PersonForm {

    public static Validator<PersonForm> validator = ValidatorBuilder.<PersonForm>of()
            .constraint(PersonForm::getName, "name", c -> c.notNull().greaterThanOrEqual(2).lessThanOrEqual(30))
            .constraint(PersonForm::getAge, "age", c -> c.notNull().greaterThanOrEqual(18))
            .build();

    // ...
}
package com.example.validatingforminput;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;


@Controller
public class WebController {

    @InitBinder
    void initBinder(WebDataBinder binder) {
        Validator personValidator = Validator.forInstanceOf(PersonForm.class, PersonForm.validator.toBiConsumer(Errors::rejectValue));
        binder.addValidators(personValidator);
    }

    @GetMapping("/")
    public String showForm(PersonForm personForm) {
        return "form";
    }

    @PostMapping("/")
    public String checkPersonInfo(@Validated PersonForm personForm, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {
            return "form";
        }

        return "redirect:/results";
    }
}