0

My Annotation class:

public @interface CustomAnnotation {

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = { })
    @Pattern(regexp="^[0-9]{12}", message="Validate Number Must be 12 Digit.")
    public @interface ValidateNumber {

        String message() default "{javax.validation.constraints.Size.message}";

        Class<?>[] groups() default { };

        Class<? extends Payload>[] payload() default { };

        @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
        @Retention(RUNTIME)
        @Documented
        @interface List {

            Size[] value();
        }
    }

    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @Constraint(validatedBy = {AccountLocation.class })
    public @interface ValidateVisitLocation {

        String message() default "Invalid Site Location.";

        Class<?>[] groups() default { };

        Class<? extends Payload>[] payload() default { };
    }
}

On ValidateVisitLocation class, I have created custom annotation AccountLocation.

public class AccountLocation implements ConstraintValidator<ValidateVisitLocation, String> {

    @Value("${siteLocation}")
    String siteLocation;

    @Override
    public void initialize(ValidateVisitLocation constraintAnnotation) {
        // TODO Auto-generated method stub
    }

    @Override
    public boolean isValid(String contactField, ConstraintValidatorContext cxt) {
        return contactField != null && siteLocation.contains(contactField.substring(0, 3));
    }

}

In my property file:

siteLocation=001,002,003,004,005

My controller class:

@Controller
@Validated
public class WelcomeController {

    @GetMapping("/v1")
    public ResponseEntity<String> get(@RequestParam String name) {
        return new ResponseEntity<String>(name, HttpStatus.OK);
    }

    @GetMapping("/v2")
    public String getAccount(@ValidateNumber @ValidateVisitLocation @RequestParam String accountId) {
        return "welcome";
    }

    @PostMapping("/v3")
    public ResponseEntity<Customer> post(@RequestBody @Valid Customer customer) {
        return new ResponseEntity<Customer>(customer, HttpStatus.CREATED);
    }
}

I have controller advice exception handling:

@ControllerAdvice
public class DataValidationExceptionHandler {


     @ExceptionHandler
        @ResponseBody
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public Map handle(MethodArgumentNotValidException exception) {
            return error(exception.getBindingResult().getFieldErrors()
                    .stream()
                    .map(FieldError::getDefaultMessage)
                    .collect(Collectors.toList()));
        }

    @ExceptionHandler
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map handle(ConstraintViolationException exception) {
        return error(exception.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.toList()));
    }

    private Map error(Object message) {
        return Collections.singletonMap("error", message);
    }
}

When I hit the GET request http://127.0.0.1:8080/v2?accountId=999000 I am getting both error message

{"error":["Invalid Site Location.","Validate Number Must be 12 Digit."]}

I am looking for if @ValidateNumber failed, do not look for @ValidateVisitLocation.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42

0 Answers0