У меня установлена аннотация над объектами типа dto, такая же как и над объектами типа Entity. Над сущностями аннотация срабатывает, а над объектами типа dto - нет.
Работаю в SrpingBoot.
application.properties
# ===============================
# NAME_TABLE
# ===============================
validate.packageid.size = "The field 'PACKAGEID' can contain only {max} symbols.";
Конфигурационный файл
@Configuration
public class ServiceConfig implements WebMvcConfigurer {
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setDefaultEncoding("UTF-8");
source.setBasename("classpath:ValidationMessages");
return source;
}
@Nullable
@Override
public Validator getValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource());
return validator;
}
}
dto
@Size(message = "{validate.packageid.size}", max = 36)
private String documentId;
entity
@Column(name = "DOCUMENTID")
@Size(message = "{validate.packageid.size}", max = 36)
private String documentId;
Я не в контроллере их заполняю, я работаю с тестами и заполняю эти dto с помощью рефлексии.
Если бы это был контроллер, тогда аннотация @Valid указывала бы на то, что прежде чем передать разобранный json в dto, то нужно произвести валидацию.
У меня вот так наполняется dto
/*подготовка объекта на сохранение*/
private DTO prepareDto(String uuid){
DTO dto = fillObjectData(new DTO ());
dto.setPackageId(uuid);
return dto;
}
/**
* Формируется объект с заполненными полями
* @param source - объект, который нужно заполнить случайными значениями
* @param <T> - тип целевого объекта который нужно вернуть с заполенными значениями
*/
public static <T> T fillObjectData(T source) {
List<Object> values = new ArrayList<>();
T dto;
dto = fillData(source, values);
getData(dto, values);
return dto;
}
/**
* Заполнение полей объекта.
* @param object - обрабатываемый объект, любого типа данных
* @param values - коллекция значений, которые будут сгенерированы для полей обрабатываемого объекта
* @param <S> - универсальный параметр, указывает на тип данных передаваемого объекта
* @return - возвращает обработанный объект. S - универсальный параметр, хранит информацию об текущем
* обрабатываемом объекте
*/
public static <S> S fillData (S object, List<Object> values){
return obtainMetadataOfObject(object, values);
}
/**
* Извлечение метаданных из полученного объекта, для дальнейшей обработки
* @param object - обрабатываемый объект
* @param values - коллекция значений, которые будут сгенерированы для полей обрабатываемого объекта
* @param <S> - универсальный параметр, указывает на тип данных передаваемого объекта
* @return - возвращает обработанный объект. S - универсальный параметр, хранит информацию об текущем
* обрабатываемом объекте
*/
private static <S> S obtainMetadataOfObject(S object, List<Object> values){
Class<?> objectClass = object.getClass();
Class superClazz = objectClass.getSuperclass();
String nameObjectClass = "Object";
String simpleNameObjectExpected = superClazz.getSimpleName();
boolean isObjectClass = Objects.equals(simpleNameObjectExpected, nameObjectClass);
if(!isObjectClass){
return manageParseListArrFields( object, values, objectClass);
}
return manageParseArrFields( object, values, objectClass);
}
.......
" .. Если бы это был контроллер, тогда аннотация @Valid указывала бы на то, что прежде чем передать разобранный json в dto, то нужно произвести валидацию .. " - Я наполняю объект dto с помощью рефлексии и аннотация @Valid, в методах где используется рефлексия и разбираются поля объекта, - не работает.
Здесь не применим подход, когда используется @Valid при обработке запроса в rest-контроллере и где эта аннотация ставиться в параметрах метода, обрабатывающего запрос
Возможно, из-за того, что сущность имеет аннотацию , согласно которой Spring при инициализации Application сontext создал bean данного класса. А в случае с dto, валидация происходит в момент, когда контроллер обрабатывает запрос, чтобы передать данные из json в dto-объект и в момент передачи данных, аннотация @Valid указывает на то, что нужно обратиться к полям, которые имееют аннотации-ограничения и провалидировать добавляемые данные.
Но в моем случае, данные в dto добавляются в тестовых методах.
Oбновление (частичное решение)
Нужно указать аннотацию @Validated. Эта аннотация от Spring и тогда Spring при обращение к объектам типа dto (на уровне бизнес-логики) валидирует добавление значений.
Но это не работает почему то для объекта, который разделен на несколько классов. Хотя такого рода объект (уровень dao - где сущности расположены) валидируется спокойно, но там уже Hibernate управляет этим процессом.
Я же не использую клиента.
Я написал тесты, которые проверяют создание записи в таблицу, обращаясь на сервис-слой.
На сервис-слое я формирую объект с помощью рефлексии, чтобы 30 полей не собирать вручную. Я поставил проверку на аннотацию Size, чтобы вытянуть размер ограничения. И хоть я поставил аннотацию @Validated, я не получаю нужных данных. @Validated хорошо работает для отдельных классов, но у меня таблица разбита на несколько абстрактных и один производный и хоть над ними стоят аннотации @Validated , в этом случае Spring не видит что нужно валидировать данные поля.
Не срабатывает validation для DTO, почему ?
Для валидации строки можно использовать аннотацию @Length(max = 255)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class AuthRq extends BaseRq {
@JsonProperty("username")
@NotEmpty
@Length(max = 255)
private String username;
@JsonProperty("password")
@NotEmpty
@Length(max = 255)
private String password;
}
// Controller ==================================
@RequestMapping(value = AUTH_URL, method = RequestMethod.POST)
public ResponseEntity<AuthRs> createAuthenticationToken(@RequestBody @Valid AuthRq authenticationRequest) throws Exception {
....
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты