augenss
augenss

Reputation: 71

Custom validation for 2 request params in Spring

Is there a way to custom validate 2 of request parameters coming into endpoint in Spring? I would like to be able to validate them with my custom function. Something like add annotation to the request params or on the function where these params are and force these params to be validated by another custom written function.
I need to take both params at the same time, because the validation output of one is dependent on the value of the other one.
I have searched and found some solutions with custom constraint annotations but from what I've read it doesn't seem to solve my problem.

Upvotes: 1

Views: 2544

Answers (4)

rahul shrivastava
rahul shrivastava

Reputation: 21

As rightly mentioned, using valiktor is the best option. I have used it in our product as well and it works like a charm.

Below is a snippet example as how you are use it to compare two properties of the same class.

fun isValid(myObj: Myobj): Boolean {
    validate(myObj) {
    validate(MyObj::prop1).isGreaterThanOrEqualTo(myobj.prop2)
}

Valiktor throws exception with proper message if the validation fails. It also enables you to create custom exception messages if you want to.

Now all you need to do is, create a class for your requestBody and check your conditions with isValid() method explicitly or move it into init block and do it implicitly.

Valiktor has a large number of validations as compared to JSR380, where creating custom validation is a little messy as compared to Valiktor.

Upvotes: 2

CodeWalker
CodeWalker

Reputation: 2378

If you're going to use the request params to create a POJO, then you can simply use the Javax Validation API.

public class User {

    private static final long serialVersionUID = 1167460040423268808L;

    @NotBlank(message = "ID cannot be to empty/null")
    private int id;

    @NotBlank(message = "Group ID cannot be to empty/null")
    private String role;

    @NotBlank(message = "Email cannot be to empty/null")
    private String email;

    @NotNull(message = "Password cannot be to null")
    private String password;
}

To validate -

@PostMapping("/new")
public String save(@ModelAttribute @Validated User user, BindingResult bindingResult, ModelMap modelMap) throws UnknownHostException {
if (!bindingResult.hasErrors()) {
    // Proceed with business logic
} else {
        Set<ConstraintViolation<User>> violations = validator.validate(user);
        List<String> messages = new ArrayList<>();
        if (!violations.isEmpty()) {
            violations.stream().forEach(staffConstraintViolation -> messages.add(staffConstraintViolation.getMessageTemplate()));
            modelMap.addAttribute("errors", messages);
            Collections.sort(messages);
        }
        return "new~user";
    }
}

Upvotes: 1

Luke
Luke

Reputation: 516

valiktor is really good library to validate.

You can do somenthing like:

data class ValidatorClass(val field1: Int, val field2: Int) {
    init {
        validate(this) {
            validate(ValidatorClass::field1).isPositive()
            validate(ValidatorClass::field2).isGreaterThan(field1)
        }
    }
}

make request parameter not required:

@RequestMapping(path = ["/path"])
fun fooEndPoint(@RequestParam("field1", required = false) field1: Int,
                @RequestParam("field2", required = false) field2: Int) {
    ValidatorClass(field1, field2) //it will throw an exception if validation fail
}

You can handle exception using try-catch or using and ExceptionHandler defined by valiktor.

Using valiktor you can validate fields depending on other fields. You can create one kotlin file where you write all classes that you use to validate fields from requests and in the same way you can use valiktor in you @RequestBody models to validate it.

Upvotes: 0

Related Questions