I would like to use @Valid
from SpringBoot to perform request validation on a particular field.
However, I would like the validation on the field to be configurable. I.e, with one configuration, enable the validation or disable it.
Here is the code:
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
class FieldValidationController {
@PostMapping("/validate")
String question(@Valid @RequestBody SomeRequest someRequest) {
return "please validate the field only if a property is on";
}
}
import jakarta.validation.constraints.NotNull;
record SomeRequest(
@NotEmpty
String alwaysValidateMe,
//How can I validate this property against @NotEmpty based on a property?
String onlyVaidateMeIfIamConfigured
) {
}
application.properties
validate.field.onlyVaidateMeIfIamConfigured=true
#to have the possibility between validate.field.onlyVaidateMeIfIamConfigured=true and validate.field.onlyVaidateMeIfIamConfigured=false
How to perform validation on a field only if a property is on?
To validate a field based on an application property value, it seems that there is no option except creating a custom constraint annotation and a corresponding constraint validator. How it can look like:
record SomeRequest(
@NotEmpty(message = "Please enter the title")
String title,
@ConditionalNotEmpty(property = "validate.isEmpty") // in properties it will be validate.isEmpty=true
String string) {
}
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Constraint(validatedBy = ConditionalNotEmptyStringValidator.class)
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConditionalNotEmpty {
String property();
String message() default "Field is invalid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
and validator:
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.core.env.Environment;
public class ConditionalNotEmptyStringValidator implements ConstraintValidator<ConditionalNotEmpty, String> {
private final Environment environment; // autowire to get property value
private String propertyKey;
public ConditionalNotEmptyStringValidator(Environment environment) {
this.environment = environment;
}
@Override
public void initialize(ConditionalNotEmpty constraintAnnotation) {
this.propertyKey = constraintAnnotation.property();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
boolean isValidationEnabled = Boolean.parseBoolean(environment.getProperty(this.propertyKey, "false")); // find validate.isEmpty value in properties, if not found - false
if (isValidationEnabled) {
return value != null && !value.isEmpty();
} else {
return true;
}
}
}