Reputation: 1479
I have extension of org.springframework.validation.Validator.
public class MyValidator implements Validator {
@Override
public void validate(Object target, Errors errors) {
...
}
}
My goal is to pass more than one target to method.
I don't like idea with overload validate
method because it smells as bad code:
validate(Object target1, Object target1, Errors errors)
or creating map with needed targets.
It will be good to know better approach regarding this case.
Upvotes: 2
Views: 12892
Reputation: 734
i faced with a similar situation where i need to pass more arguments to the validate method so i came up with a idea of my own.in my case i wanted a String to be passed to this method
validate method implemented in the following classes CustomValidatorBean
, LocalValidatorFactoryBean
, OptionalValidatorFactoryBean
, SpringValidatorAdapter
I extended the CustomValidatorBean
and called the validate method in super class and it is working perfectly
import javax.validation.Validator;`
import org.apache.commons.lang3.StringUtils;`
import org.springframework.validation.Errors;`
importorg.springframework.validation.beanvalidation.CustomValidatorBean;`
public class MyValidator extends CustomValidatorBean {`
public void myvalidate(Object target,Errors errors,String flag,Profile profile)
{
super.validate(target,errors);
if(StringUtils.isEmpty(profile.name())){
errors.rejectValue("name", "NotBlank.profilereg.name", new Object[] { "name" }, "Missing Required Fields");
}
}
}
Upvotes: 0
Reputation: 1210
I did not try the following code, but it demonstrates a basic idea how one field of the bean could be verified against the other. Hopefully, it will help you
Let's say you have the following form bean
public class MyForm {
private String id;
private List<String> oldIds;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<String> getOldIds() {
return oldIds;
}
public void setOldIds(List<String> oldIds) {
this.oldIds = oldIds;
}
}
and the id property has to be validated against the oldIds object (if i did understand your requirements correctly). To achieve it your need to create a constraint and mark your bean. So, the first is the constraint interface
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.validation.Constraint;
import javax.validation.Payload;
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MyConstraintValidator.class)
@Documented
public @interface MyConstraint {
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String[] value();
}
next, you need to implement the constraint validator class:
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.beanutils.PropertyUtils;
public class MyConstraintValidator implements
ConstraintValidator<MyConstraint, Object> {
private String firstAttribute;
private String secondAttribute;
@Override
public void initialize(final MyConstraint constraintAnnotation) {
firstAttribute = constraintAnnotation.value()[0];
secondAttribute = constraintAnnotation.value()[1];
}
@Override
public boolean isValid(final Object object,
final ConstraintValidatorContext constraintContext) {
try {
final String id = (String) PropertyUtils.getProperty(object,
firstAttribute);
List<String> oldIds = (List<String>) PropertyUtils.getProperty(
object, secondAttribute);
// do your validation
return true;
} catch (final Exception e) {
throw new IllegalArgumentException(e);
}
}
}
finally, apply the created constraint to the form bean
@MyConstraint(value = { "id", "oldIds" })
public class MyForm {
// the code
}
For now, your mark your bean with the @Valid annotation from the javax.validation package or feed it to the validator object
Upvotes: 6
Reputation: 1910
We use a target bean which holds all the data which need to be validated. Something like
private static final class ParamsBean {
String id;
List<String> oldIds;
}
Then we simply cast the object. It's the cleanest possible solution imo, as it does not use generic Map
or List
of unknown objects (though the casting still is not nice).
Upvotes: 4