简体   繁体   中英

How to avoid repetitive check of null value when validating fields?

I want to validate simple account data using java validator. None of account data fields can be null so all of them are annotated @NotNull. But still i have to check if provided password and its repetition are equal to each other. This forces me to avoid NullPointerException by checking null equality. Please see the code (i omitted Maven dependecies for the case of brevity as dependencies and correct libraries do not cause problems):

AccountData class:

@ValidPassword
class AccountData {

@NotNull
public String login;

@NotNull
public String password;

@NotNull
public String repeatedPassword;

@NotNull
public String emailAddress;

@NotNull
public String countryName;  
}

ValidCountry interface:

@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CountryValidatorImplementation.class)
@Documented
@interface ValidPassword {
   String message() default "Passwords don't match";
   Class<?>[] groups() default {}; 
   Class<? extends Payload>[] payload() default {};
}

PasswordValidatorImplementation (in a separate .java file):

public class CountryValidatorImplementation implements 
PasswordValidator<ValidPassword, Object> {

public PasswordValidatorImplementation() {

}

public boolean isValid(Object value, ConstraintValidatorContext context) {

    AccountData accountData = (AccountData) value;

    if(!accountData.password.equals(accountData.password)) {
      return false;  
    }
    //Not checking if account with login already exists in a DB for 
    //brevity
    return true;

}
}

Usage in main method:

  • Does not cause NullPointerException as I first set password and repeatedPassword progrmatically:

     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); AccountData accountData = new AccountData(); accountData.password = "1234"; accountData.repeatedPassword = "5678"; Set<ConstraintViolation<AccountData>> constraintViolationSet = validator.validate(accountData); 
  • Causes NullPointerException as I password on which validation is performed is null:

     ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); AccountData accountData = new AccountData(); Set<ConstraintViolation<AccountData>> constraintViolationSet = validator.validate(accountData); 

Is there any possibility to execute @NotNull indicated validation on fields and return false for isValid (or even earlier throwing an Exception) thanks to those annotations so that checking whether any of AccountData fields will not be needed anymore? *Spring related solutions are also welcome!

No, you cannot stop validation early. Every annotation will be processed, so all problems can be reported together. This is much better than forcing repeated trial-and-error as a user fixes each problem in turn.

In fact, you should write almost all of your custom validators to consider null to be valid. Then they are much more useful and can be combined with @NotNull or not as needed.

public boolean isValid(Object value, ConstraintValidatorContext context) {
    if (value == null) {
        return true;
    }
    // ...

As your validator deals with field values that may also be null, you probably want something like this.

public class PasswordValidatorImpl implements PasswordValidator<ValidPassword, AccountData> {
    public boolean isValid(AccountData value, ConstraintValidatorContext context) {
        return value == null || Objects.equals(value.password, value.repeatedPassword);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM