2017. október 5., csütörtök

Custom validator for REST parameter in Spring Boot


Using Spring boot applications, it is very easy to let the Spring framework to do the validation of the REST input parameter. You only need to add the corresponding validation annotations to the properties of the parameter class, and mark the parameter with @Valid annotation in the method header.


@RequestMapping(value = "/register", method = { RequestMethod.POST })
public RestResponse register(HttpServletRequest httpServletRequest, 
       @Valid @RequestBody PushRegistrationRequest registrationRequest) {



In case of your REST input object is validated with the @Valid annotation, most of the time, it is enough to  use default validations, like @NotNull, @Pattern, @Size, etc. Sometimes though you need to do more complex validations, considering multiple properties. To achieve this, you need to write your own annotation, and a corresponding validation class.

The annotation looks like this:


@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = { HasCorrectAppIdValidator.class })
public @interface HasCorrectAppId {
 String message() default "App id is incorrect";

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

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

  As you can see above, in the validatedBy attribute, you can define a validation class. the validator class needs to implement the javax.validation.ConstraintValidator interface.


import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class HasCorrectAppIdValidator implements ConstraintValidator<HasCorrectAppId, PushRegistrationRequest> {

 @Override
 public void initialize(HasCorrectAppId constraintAnnotation) {
  // do nothing
 }

 @Override
 public boolean isValid(PushRegistrationRequest value, ConstraintValidatorContext context) {
  if (IOS.equals(value.getOs()) && value.getAppId().length() != 64) {
   String errorMessage = "length must be 64 for " + ClientOperationSystem.IOS;
   createErrorInContext(context, errorMessage);
   return false;

  } else if (ANDROID.equals(value.getOs()) && value.getAppId().length() < 65) {
   String errorMessage = "length must be greater than 65 for " + ClientOperationSystem.ANDROID;
   createErrorInContext(context, errorMessage);
   return false;
  }
  return true;
 }

 private void createErrorInContext(ConstraintValidatorContext context, String errorMessage) {
  context.disableDefaultConstraintViolation();
  context.buildConstraintViolationWithTemplate(errorMessage)
    .addPropertyNode("appId")
    .addConstraintViolation();
 }
}


That's it. In order to use tell to the framework to use the validator is, to annotate the parameter class with the new annotation.




@HasCorrectAppId
public class PushRegistrationRequest implements Serializable {
    ...
}


Nincsenek megjegyzések:

Megjegyzés küldése