Валидация Interactor
ValidationProxyHandler проверяет аннотации на аргументах перед вызовом обработчика и аннотации на методе после получения результата. При нарушении ограничения выбрасывается BGMessageException.
@BindTextParam(120)
@NotNull(message = "В процессе #objectId не указан номер")
fun getNumber(): String
@BindTextParam(120)
fun setNumber(@NotEmpty(message = "Номер не должен быть пустым") value: String)
В пользовательском message последовательность #objectId заменяется идентификатором, переданным в Interactor.create. Если сообщение не задано и осталось стандартным сообщением javax.validation, формируется техническое сообщение с именем метода или аргумента.
| Это собственная точечная реализация ограничений, а не полный запуск Bean Validation. Проверяются только перечисленные ниже аннотации и типы. |
Стандартные ограничения
| Аннотация | Поддерживаемые значения | Проверка |
|---|---|---|
|
Любой тип |
Значение не равно |
|
Любой тип |
Значение равно |
|
|
Значение не пустое. |
|
|
Длина, размер коллекции либо |
|
|
Вся строка соответствует |
|
|
Строка соответствует |
|
|
Сравнение с нулём; |
|
|
Значение равно ожидаемому; |
|
|
Сравнение с текущим временем; |
Стандартные аннотации импортируются из javax.validation.constraints.
Даты с заданной точностью
Пакет ru.bgcrm.util.interactor.annotation содержит собственные Future, FutureOrPresent, Past и PastOrPresent. У них обязательный message и параметр accuracy, по умолчанию ChronoUnit.MILLIS.
@BindDateTimeParam(451)
@ru.bgcrm.util.interactor.annotation.FutureOrPresent(
message = "Дата не может быть в прошлом",
accuracy = ChronoUnit.MINUTES
)
fun getPlannedAt(): LocalDateTime?
Поддерживаются MILLIS, SECONDS, MINUTES, HOURS, HALF_DAYS и DAYS. Полученная и текущая даты усекаются до выбранной единицы перед сравнением. Для неподдерживаемой единицы проверка не выполняется.
Особенности одиночных результатов
Несколько обработчиков связей и TMC сначала получают коллекцию, вызывают SizeValidator.assert, а затем возвращают первый элемент. Поэтому @Size(max = 1) на методе с одиночным результатом проверяет размер исходной коллекции, а не объект результата. Это используется в готовых аспектах WithSingleCustomer и WithSingleCctvContract.
@BindProcessLinkedCustomers
@Size(max = 1, message = "К процессу привязано больше одного контрагента")
@NotNull(message = "К процессу не привязан контрагент")
fun getCustomer(): Customer
Порядок общий: входные ограничения → обработчик → выходные ограничения. Если проверка аргумента не пройдена, чтение или изменение данных не начинается.