Spring Boot validation - one from two not null

坚强是说给别人听的谎言 提交于 2020-08-04 10:35:21

问题


I'm trying to validate if one of two fields are not null in Spring Boot?

I have set that in the method class for the main object:

@NotNull(message = "Username field is required")
private String username;

@NotNull(message = "Email field is required")
private String email;

but that will require to have both fields not null. Then I went with custom validation described here https://lmonkiewicz.com/programming/get-noticed-2017/spring-boot-rest-request-validation/ but I wasn't able to get that example to work. I have to stuck on

User class declaration:

@CombinedNotNull(fields = {"username","email"})
public class User implements {

    private long id = 0L;
    @NotNull(message = "First name field is required")
    private String firstName;

    @NotNull(message = "Last name field is required")
    private String lastName;

    private String username;
    private String email;

    @NotNull(message = "Status field is required")
    private String status;

    ...all methods here...
    ...setters and getters...

}

CombibnedNotNull class:

@Documented
@Retention(RUNTIME)
@Target({ TYPE, ANNOTATION_TYPE })
@Constraint(validatedBy = userValidator.class)
public @interface CombinedNotNull {
        String message() default "username or email is required";
        Class<?>[] groups() default { };
        Class<? extends Payload>[] payload() default { };
}

userValidator class:

@Component
public class userValidator implements ConstraintValidator<CombinedNotNull, User> {

    @Override
    public void initialize(final CombinedNotNull combinedNotNull) {
        fields = combinedNotNull.fields();
    }

    @Override
    public boolean isValid(final User user, final ConstraintValidatorContext context) {
        final BeanWrapperImpl beanWrapper = new BeanWrapperImpl(user);

        for (final String f : fields) {
            final Object fieldValue = beanWrapper.getPropertyValue(f);

            if (fieldValue == null) {
                return false;
            }
        }

        return true;
    }
}

Is there any other way to get this done or should I go with the "complex" example from that page?


回答1:


I'll try to implement it for you (even if I'm without an IDE).
Inside ConstraintValidator#initialize you can get a hold of the configured fields' names which cannot be null.

@Override
public void initialize(final CombinedNotNull combinedNotNull) {
    fields = combinedNotNull.fields();
}

Inside ConstraintValidator#isValid you can use those fields' names to check the Object fields.

@Override
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
    final BeanWrapperImpl beanWrapper = new BeanWrapperImpl(value);
    
    for (final String f : fields) {
       final Object fieldValue = beanWrapper.getPropertyValue(f);
       
       if (fieldValue == null) {
          return false;
       }
    }

    return true;
}

Annotation:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = CombinedNotNullValidator.class)
public @interface CombinedNotNull {
    String message() default "username or email is required";

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

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

    /**
     * Fields to validate against null.
     */
    String[] fields() default {};
}

The annotation could be applied as

@CombinedNotNull(fields = {
      "fieldName1",
      "fieldName2"
})
public class MyClassToValidate { ... }

To learn how to create a Class-level constraint annotation, refer always to the official documentation. Docs




回答2:


Add this getter in User class:

@AssertTrue(message = "username or email is required")
private boolean getUsernameOrEmailRequired() {
    return username != null || email != null;
}

This have a small problem: the field name from this validation error would be usernameOrEmailRequired. If that is not a concern, this might help.



来源:https://stackoverflow.com/questions/54638255/spring-boot-validation-one-from-two-not-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!