Interactor

Interactor — внутренний механизм ERP для описания данных сущности Java/Kotlin-интерфейсом. Методы интерфейса связываются с параметрами, свойствами и привязками сущности аннотациями @Bind*, а реализация создаётся во время выполнения через java.lang.reflect.Proxy.

Механизм полезен, когда бизнес-коду нужен небольшой типизированный API над процессом, контрагентом, пользователем или другой поддерживаемой сущностью без повторения DAO- и сервисного кода.

interface InstallationProcess : ProcessInteractor {
    @BindAddressParam(90)
    @NotNull(message = "В процессе #objectId не указан адрес")
    fun getAddress(): ParameterAddressValue

    @BindProcessStatusSwitch(2)
    @DropCache
    fun close(comment: String?)
}

val process = Interactor.create<InstallationProcess>(processId)
val address = process.getAddress()
process.close("Работы завершены")

Что происходит при вызове

Interactor.create(id, type, context) собирает цепочку обработчиков:

  1. ValidationProxyHandler проверяет аргументы метода до вызова и результат после вызова.

  2. CacheProxyHandler обслуживает @EnableCache и @DropCache.

  3. InteractionDispatcher определяет фабрику по интерфейсу, на котором объявлен метод.

  4. Зарегистрированный InteractionHandler выполняет чтение или изменение данных для объекта с переданным id.

Сам proxy не загружает сущность целиком. Каждый вызов выполняет только операцию, связанную с конкретным методом. Обработчик метода создаётся лениво и затем повторно используется внутри этого экземпляра proxy.

Interactor не является ORM и не проверяет, что переданный id относится к ожидаемому типу сущности. Правильный интерфейс и идентификатор выбирает вызывающий код.

Разделы

Ограничения

  • Интерфейс должен наследовать один из зарегистрированных корневых интерфейсов, перечисленных на странице «Поддерживаемые сущности».

  • Метод должен иметь ровно одну поддерживаемую @Bind*-аннотацию и подходящую обработчику сигнатуру. Ошибка обнаруживается только во время вызова.

  • Изменяющие методы не очищают кеш автоматически: для интерфейсов с @EnableCache требуется @DropCache.

  • Default-методы интерфейсов специально не обрабатываются; в Interactor это отмечено как незавершённая возможность.

  • Методы equals, hashCode и toString не имеют отдельной реализации: их вызов также попадает в dispatcher и завершается ошибкой поиска фабрики. Не используйте proxy как ключ коллекции и не полагайтесь на его строковое представление.

  • @ProcessInteractorReference хранит соответствие интерфейса типам процессов для внешнего поиска, но сам Interactor.create эту аннотацию не проверяет.