Reputation: 1132
I have a DTO class that takes customer information. Many of the fields are annotated with validation retrictions. @NotNull @Length @Min @Max @Pattern... and so on. We have the need as it seems many do for loading regex's for validation from properties files, so @CustomPattern was created, along with CustomerValidationAdvice.
@Before("@annotation(customPattern)")
public void validateWithPropertyFileValue(JoinPoint joinPoint, CustomPattern customPattern) throws Throwable {
if(applicationProps==null) {
applicationProps = (Properties) ApplicationContextProvider.getApplicationContext().getBean(
"applicationProps");
}
Object[] paramValues = joinPoint.getArgs();
String valueToValidate="";
if (!ArrayUtils.isEmpty(paramValues)) {
valueToValidate = paramValues[0] != null ? (String) paramValues[0] : valueToValidate;
}
if (!serverValidationUsingRegexPattern(valueToValidate, applicationProps.getProperty(customPattern.regexp()))) {
throw new ValidationException("Validation Failed");
}
}
The problem is that this executes when setting the values on the DTO from the incoming request even though the method is not Annotated with @Valid. The other validation parameters do not execute unless object is passed to validator or @valid is on the method. Are there things i can look at in the joinPoint to figure out where it was called from and skip validation?
Upvotes: 0
Views: 2131
Reputation: 1132
Seems it's just better to go with how normal validation works. So instead of trying to modify legacy code using aspects. i created 2 files
the annotation:
@Documented
@Retention(RUNTIME)
@Target({METHOD,FIELD})
@Constraint(validatedBy=PropertyPaternValidator.class)
public @interface PropertyPatern {
String property();
String message() default "{validator.propertypatern}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
and the processor:
public class PropertyPaternValidator implements ConstraintValidator<PropertyPatern, CharSequence> {
private Map<String, Pattern> patterns = new HashMap<>();
private Pattern pattern;
@Override
public void initialize(PropertyPatern propPattern) {
String property = propPattern.property();
pattern = patterns.computeIfAbsent(property, prop -> {
Properties applicationProps = (Properties) ApplicationContextProvider.getApplicationContext()
.getBean("applicationProps");
String p = applicationProps.getProperty(prop);
return Pattern.compile(p);
});
}
@Override
public boolean isValid(CharSequence inputToValidate, ConstraintValidatorContext ctx) {
CharSequence input = inputToValidate != null ? inputToValidate : "";
Matcher m = pattern.matcher(input);
return m.matches();
}
}
This will work just like @Pattern but allow the loading of the regex from application properties. Usage annotate field like so @PropertyPatern(property = "pattern.zip")
and ensure there is a regex in application properties with that key.
Upvotes: 0