I have a ConstraintValidator that needs to validate the input parameter (periodDays) depending on another parameter (id). To do this, I implemented validation logic based on ElementType.METHOD. My interface:
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { DaysPeriodValidator.class })
public @interface ValidDaysPeriod {
// ...
and Validator:
@SupportedValidationTarget(ValidationTarget.PARAMETERS)
public class DaysPeriodValidator implements ConstraintValidator<ValidDaysPeriod, Object[]> {
@Override
public boolean isValid(Object[] objects, ConstraintValidatorContext context) {
Integer testValue;
String id;
try {
testValue = (Integer) objects[1];
id = validateTenantId((String) objects[0]);
} catch (Exception e) {
return false;
}
// ... validation logic
return valid;
}
}
It works well for controller methods like
@ValidDaysPeriod
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public MyData getMyData(@Nullable String id,
@NotNull Integer periodDays) {
where parameters order is expected. But I'm not immune if somebody would write a new endpoint where parameters are not in this order. The Validator gets them in nameless Object[] objects, and if there are more Integer or String parameters, I can't recognize id and periodDays among them.
Is there a way to detect these parameters inside the Validator? For example:
Eventually, I found an ability to get parameter names from the context. Their order is strictly the same as for values in Objects[].
public boolean isValid(Object[] objects, ConstraintValidatorContext context) {
Integer testValue;
String id;
try {
List<String> methodParameterNames = ((CrossParameterConstraintValidatorContextImpl) context).getMethodParameterNames();
int idIdndex = methodParameterNames.indexOf(idParameterName);
int periodDaysIndex = methodParameterNames.indexOf(periodDaysParameterName);
testValue = (Integer) objects[periodDaysIndex];
id = validateTenantId((String) objects[idIndex]);
} catch (Exception e) {
return false;
}
// validator logic
}
P.S. Guy who dislikes w/o comments, you can f*ck yourself:)