вторник, 18 июня 2013 г.

Spring Validation as ValidationUtils way

Нужно реализовать

public interface Validator {
 boolean supports(Class clazz); 
 void validate(Object target, Errors errors);
}

Во время валидации мы пользуемся статическими методами org.springframework.validation.ValidationUtils:

public static void invokeValidator(Validator validator, Object obj, Errors errors)
public static void rejectIfEmpty(Errors errors, String field, String errorCode)
public static void rejectIfEmpty(Errors errors, String field, String errorCode, String defaultMessage)
public static void rejectIfEmpty(Errors errors, String field, String errorCode, Object[] errorArgs)
public static void rejectIfEmpty(Errors errors, String field, String errorCode, Object[] errorArgs, String defaultMessage)
public static void rejectIfEmptyOrWhitespace(Errors errors, String field, String errorCode)
public static void rejectIfEmptyOrWhitespace(Errors errors, String field, String errorCode, String defaultMessage)
public static void rejectIfEmptyOrWhitespace(Errors errors, String field, String errorCode, Object[] errorArgs)
public static void rejectIfEmptyOrWhitespace(Errors errors, String field, String errorCode, Object[] errorArgs, String defaultMessage)
Когда у нас что-то не стандартное, тогда проверяем сами и если что не так то вызываем:
@Override
  public void validate(Object target, Errors errors) {    
    GalaxyGateway typedTarget = (GalaxyGateway) target;
    if(typedTarget.getPingInterval() > typedTarget.getTimeout())
      errors.rejectValue("timeout", "invalid", "It would be greater or equal to ping interval");      
  }
При этом важно обратить внимание на второй параметр errors.rejectValue, если пользоваться errors.reject, то у нас не ставится в ерроркод обьекта еррор, который в обьекте еррорс:), префиксы формы на котором была присвоена модель. Тоесть мы обычно валидируем поле формы, которое может состоять из бинов, которые рекурсивно и валидируются, и если у нас поточная валидация, какого-то дальнего бина, то весь путь к нему потерятся и form:error во вьюхе не заметит никакой ошибки. Значение "invalid" в принципе может быть любым, если нас удовлетворяет дефолтное сообщение (3-й параметр), если же мы хотим перегрузить, то нужно знать что это значение выступает префиксом перед еррор кодом, и нам нужно создавать ленгу на такой ключ.

А и да если на нужно провалидировать из валидатора бина, бины которые являются полями в этом, нам нужно во первых при создании валидатора в контрутор передать подвалидаторы, при этом такие валидаторы обычно сохраняются полями. И потом делегировать валидацию:


private final Validator galaxyGatewayValidator;

@Override
public void validate(Object target, Errors errors) {
  GalaxyConfiguration typedTarget = (GalaxyConfiguration) target;

  ListIterator<galaxygateway> gatewaysIter = typedTarget.getGateways().listIterator();
  while(gatewaysIter.hasNext()) {
      try {
        errors.pushNestedPath("gateways[" + gatewaysIter.nextIndex() + "]");
        invokeValidator(this.galaxyGatewayValidator, gatewaysIter.next(), errors);
      } finally {
        errors.popNestedPath();
      }
   }
}
И чтобы этим всем пользоваться делаем в контроллере:

@Autowired
private GalaxyConfigurationValidator configurationValidator;

@ActionMapping(params = "action=galaxyConfigSave")
  public void saveGalaxyConfiguration(ActionRequest request, ActionResponse response,
                                      @ModelAttribute("galaxyConfiguration") GalaxyConfiguration galaxyConfiguration, BindingResult result ) throws PortalException, SystemException {
    configurationValidator.validate(galaxyConfiguration, result);
    if (result.hasErrors()){
      response.setRenderParameter("action", "renderSpecificView");
      response.setRenderParameter("viewName", "galaxy");
    } else {
      saveGalaxyConfig(request, galaxyConfiguration);
      response.setRenderParameter("action", "success");
    }

  }

Комментариев нет:

Отправить комментарий