1

I have an REST endpoint, which takes an object in the request body and a request parameter. When the request parameter is passed, I need to validate all the attributes of the object, if not the parameter takes the default value assigned and only 2 attributes needs to be validated. The path needs to be same for both the case. How can this be achieved?

Currently I have pattern, length and possibles values check for the objects, validated with the help of annotations.

----- Updating the Class -------

@ValidateParent(parent = "parent ", child= "child")
public class anClass{

    @NotNull(groups = {FrstValidator.class, SndValidator.class})
    @Pattern(regexp = "^[a-zA-Z]{3}$",
            groups = {FrstValidator.class, SndValidator.class})
    String str1;

    @NotNull(groups = {FrstValidator.class, SndValidator.class})
    @Pattern(regexp = "^[a-zA-Z]{3}$",
            groups = {FrstValidator.class, SndValidator.class})
    String str2;

    @Pattern(regexp = "^[a-zA-Z]{10}$",
            groups =  SndValidator.class)
    String child;

    @Pattern(regexp = "^[a-zA-Z]{10}$",
            groups = SndValidator.class)
    String parent;

    @Pattern(regexp = "^[a-zA-Z]{10}$",
            groups = SndValidator.class)
    String str3;


}

ValidateParent, checks if the parent is also passed when the child is passed in the request body.

Ace
  • 700
  • 7
  • 37
  • Hello, if the request parameter is passed (by user) and its value is the same as the default value, which validation should take place for the `@RequestBody`: all attributes because parameter provided, or only 2 - because it's the same as default? :) – Nowhere Man Oct 16 '20 at 21:00
  • These might help you: https://stackoverflow.com/questions/59422883/spring-boot-custom-validation-in-request-params and https://stackoverflow.com/questions/57154986/is-there-a-way-to-validate-fields-in-a-request-object-that-am-using-as-a-wrapper/57158650#57158650 – YoManTaMero Oct 16 '20 at 21:28
  • I have updated the request class and the validations applied. I think this can give you a better idea of the issue. – Ace Oct 18 '20 at 20:44

1 Answers1

1

You can achieve your goal in an elegant "Spring way", using validation groups and two separate endpoints, distinguished by presence of the request parameter:

Validation groups:

// Validation groups are just marker interfaces
private interface PartialValidation {}
private interface FullValidation {}

Request DTO:

@Data
private static class Request {
    // This field will be validated only for FullValidation validation group
    @NotNull(groups = FullValidation.class)
    String field1;
    // This field will be validated for both validation groups
    @NotNull(groups = {FullValidation.class, PartialValidation.class})
    String field2;
}

Controller:

// This endpoint is executed only if there is no myParam preprovided
@PostMapping(
    value = "/validation",
    params = "!myParam")
public void partialValidation(
    @RequestParam(defaultValue = "DEFAULT") String myParam,
    // Request is validated against the PartialValidation group
    @RequestBody @Validated(PartialValidation.class) Request request) {

    System.out.println("Partial validation");
}

// This endpoint is executed only if there is myParam preprovided
@PostMapping(
    value = "/validation",
    params = "myParam")
public void fullValidation(
    @RequestParam String myParam,
    // Request is validated against the FullValidation group
    @RequestBody @Validated(FullValidation.class) Request request) {

    System.out.println("Full validation");
}
Mafor
  • 9,668
  • 2
  • 21
  • 36