1

I have implemented controller with method:

public Page<EventDto> search(@ModelAttribute @Valid EventsCriteria criteria){...}

It works. EventsCriteria did not have special separate validator for itself, because it has inner annotation checkers like @NotNull @NotEmpty. Right now situation is changed and it's not enough to have only this validators. so I've added and registered correspond service to verify some sates.

I want service to verify additional composite cases and single validation like before. But my single inner annotation checkers like @NotNull @NotEmpty do not work any more.

Am I configured something incorrectly or it can't work in in same time(specified service and inner checkers)?

My validator example (as it was asked in comments)

There are nothing special, if you know spring, so I missed this part like unimportant to concentrate your attention on my question.

@Component
public class EventsCriteriaValidator implements Validator {

    public static final String INVALID_RAGE_PARAMETERS_SPECIFIED = "Invalid rage parameters: please specify " +
            "'from' and 'to' or page 'size";

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz.isAssignableFrom(EventsCriteria.class);
    }

    @Override
    public void validate(Object target, Errors errors) {
        EventsCriteria toValidate = (EventsCriteria) target;
        validateComplexRestriction(toValidate, errors);
    }

    private void validateComplexRestriction(EventsCriteria toValidate, Errors errors) {
        if (toValidate.isRangeEmpty() && toValidate.getSize() == 0) {
            errors.rejectValue(SIZE_FIELD, null, INVALID_RAGE_PARAMETERS_SPECIFIED);
        }
    }

}
Sergii
  • 7,044
  • 14
  • 58
  • 116

3 Answers3

1

Let assume that your EventsCriteria contains two fields so inside your validate method you can validate those field using : ValidationUtils (org.springframework.validation.ValidationUtils)

 @Override
    public void validate(Object target, Errors errors) {
        EventsCriteria eventsCriteria= (EventsCriteria) target;
        ValidationUtils.rejectIfEmpty(errors, "field1", "eventsCriteria.field1.empty");
        ValidationUtils.rejectIfEmpty(errors, "field2", "eventsCriteria.field2.empty");
    }

and in your messages.properties

eventsCriteria.field1.empty = Enter a valid value for field 1.
eventsCriteria.field2.empty = Enter a valid value for field 2.

and in your configuration class add this bean:

 @Bean
   public MessageSource messageSource() {
      ResourceBundleMessageSource source = new ResourceBundleMessageSource();
      source.setBasename("messages");
      return source;
   }
e2rabi
  • 4,728
  • 9
  • 42
  • 69
  • Yea, that works, but it's workaround. I do not want implement behavior if same can be used by default, because of bad practice. but thanks for your attention. – Sergii Dec 06 '17 at 17:08
0

Edited:

If you want both custom and default validation you can use addValidators in initBinder to add your custom validations. This way default validations will not be deleted.

@Controller
public class MyController
{
    @Autowired
    private EventsCriteriaValidator validator;

    @InitBinder
    protected void initBinder(final WebDataBinder binder)
    {
         binder.addValidators(validator);
    }

  public Page<EventDto> search(@ModelAttribute @Valid EventsCriteria   criteria, BindingResult result){

     if (result.hasErrors()) {
        // validation failed

     } else {
        //validation passed   
     }
  }

}
gkatiforis
  • 1,588
  • 9
  • 19
  • I need both validations buy default. I expected they'll used both because of `@Valid` marker. – Sergii Dec 06 '17 at 14:22
0

Just make your Validator extend LocalValidatorFactoryBean and then call super.validate(target, errors) in your validate method like this:

@Override
public void validate(Object target, Errors errors) {
   super.validate(target, errors);

   EventsCriteria toValidate = (EventsCriteria) target;
   validateComplexRestriction(toValidate, errors);
}
vl4d1m1r4
  • 1,688
  • 12
  • 21