I'm having issues implementing two validators using @InitBinder annotation.
Controller code:
@Autowired
private SessionValidator sessionValidator;
@Autowired
private ChannelValidator channelValidator;
@InitBinder
public void initBinder(WebDataBinder binder){
binder.addValidators(sessionValidator, channelValidator);
}
@RequestMapping(method = RequestMethod.GET)
public UserInfo findBySession(
@Valid @ModelAttribute Session session,
@Valid @ModelAttribute Channel channel){
//...
}
Session validator:
@Component
public class SessionValidator implements Validator {
@Override
public boolean supports(Class<?> aClass){
return Session.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors){
//...
}
}
Channel validator:
@Component
public class ChannelValidator implements Validator {
@Override
public boolean supports(Class<?> aClass){
return Channel.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors){
//...
}
}
I'm receiving the following exception when calling the controller:
Caused by: java.lang.IllegalStateException: Invalid target for Validator [com.almundo.p13n.dna.validators.ChannelValidator@4e642ee1]: Session(null, null)
Anyone knows how to solve it? Thanks in advance!
You binds two validators but for each parameter to validate only one of them will be supported.
SessionValidator
support the Session
parameter but doesn't support the Channel
parameter and reversely ChannelValidator
supports the Channel
parameter but doesn't support the Session
parameter.
Whereas the exception.
As first alternative you could support both parameter types in each Spring Validator subclass. It is a little clumsy but it should work :
@Override
public boolean supports(Class<?> aClass){
return Channel.class.equals(aClass) || Session.class.equals(aClass);
}
You should of course check the type in validate()
and perform the validation only if it matched with the validator class.
As second alternative, use the standard validation API by implementing javax.validation.ConstraintValidator
for each class to validate and by validating the parameters explicitly in the controller.
As third alternative, if it makes sense you could annotate directly the constraints on the Session
and the Channel
classes. So, you could still use @Valid
in the parameter declaration to keep the automate validation.