Сервисы ServerContext

Сервис — интерфейс, наследующий маркер ru.bgcrm.context.core.service.Service и зарегистрированный в ServiceFactory. Сервисы являются публичной точкой бизнес-операций для action, listener, task, динамического кода и других компонентов ERP.

Жизненный цикл

ServerContext хранит пользователя, режим транзакции, соединения, repositories и созданные сервисы. Первый запрос интерфейса создаёт реализацию и proxy; последующие запросы того же интерфейса в этом контексте возвращают тот же экземпляр proxy.

Proxy выполняет инфраструктурные обработчики вызова и после успешного вызова подтверждает и освобождает соединения в нетранзакционном режиме. Поэтому реализацию сервиса не следует создавать вручную в прикладном коде.

Режим контекста Поведение

transactional = true

Все сервисы разделяют соединения контекста. Изменения подтверждаются явным commit

transactional = false

После сервисного вызова соединения освобождаются автоматически; режим подходит для независимых операций чтения и коротких записей

После закрытия контекста полученный сервис использовать нельзя.

Получение сервиса

Kotlin

import ru.bgcrm.context.core.ServerContext
import ru.bgcrm.context.core.getService
import ru.bgcrm.model.param.service.ParameterService

val parameterService = ServerContext.get().getService<ParameterService>()

Java

ParameterService parameterService =
    ServerContext.lookup(ParameterService.class);

Если объект ServerContext уже передан явно:

ParameterService parameterService =
    context.getService(ParameterService.class);

Передавайте сервис в конструктор компонента, если это упрощает тестирование. Значением по умолчанию может быть lookup текущего контекста, но бизнес-метод не должен многократно искать один сервис.

Создание отдельного контекста

HTTP-запросы и штатные обработчики уже выполняются в контексте. Для команды или интеграционного callback без контекста используйте withContext/runWithContext:

withContext(user, transactional = true) {
    getService<ProcessService>().addDescription(processId, message)
}

withContext подтверждает транзакцию после успешного завершения блока и всегда закрывает контекст. Не прикрепляйте один ServerContext одновременно к нескольким потокам. Полный жизненный цикл описан на странице GlobalContext и ServerContext, режимы соединений — на странице Соединения и транзакции.

Основные доменные сервисы

Интерфейс Пакет Назначение

ProcessService

ru.bgcrm.model.process.service

Процессы, статусы, группы, исполнители и привязки

ParameterService

ru.bgcrm.model.param.service

Значения параметров с проверками и событиями

EventlessParameterService

ru.bgcrm.model.param.service

Те же операции с параметрами без событий изменения

ParameterForExternalService

ru.bgcrm.model.param.service

Чтение типа и сериализованного значения, когда внешний клиент заранее не знает тип параметра; поддержка типов неполная

CustomerService

ru.bgcrm.model.customer.service

Операции с контрагентами

UserService

ru.bgcrm.repository.user

Поиск и получение пользователей

WorkTypeService

ru.bgcrm.model.work.service

Справочник типов работ

ParamCopierService

ru.bgcrm.model.param.service.copier

Копирование наборов параметров между объектами

NodeLinkService

ru.bgcrm.context.core.node.service

Связи узлов/объектов контекста

ProcessService также разделён на узкие сервисы: CommonProcessService, ProcessCreatorService, ProcessGroupsService, ProcessExecutorsService, LinkService, ProcessLinkService, LinkedCustomerService, LinkedContractService, LinkedCommonContractService и CommonLinkService. Запрашивайте узкий интерфейс, если компоненту не нужен весь фасад.

Задачи и планировщик

Интерфейс Назначение

TaskService

Определения задач: создание, изменение, поиск и удаление

ProcessTaskService

Планирование и состояние запусков задачи для процесса

ProcessTaskExecutor

Исполнение готового запуска задачи

SchedulerTaskService

Определения задач планировщика

SchedulerTaskRunService

История и состояние запусков планировщика

Модуль Task и планировщик решают разные задачи: первый создаёт отложенную работу для процесса, второй запускает периодические служебные задачи.

Инфраструктурные сервисы

Интерфейс Назначение

ApiClientFactory

Создание HTTP-клиентов Retrofit

AuthenticationProviderFactory

Провайдеры авторизации HTTP-клиентов

TokenRepositoryFactory

Хранение токенов интеграций

ContextVariableCatalog

Каталог контекстных переменных

ContextVariableBuilderFactory

Построение значений контекстных переменных

TextTemplateProcessor

Обработка текстовых шаблонов с контекстными переменными

FileInfoService

Метаданные файлов

TemporaryFileService

Временные файлы

FileStorage

Асинхронное файловое хранилище

EntityLogServiceFactory

Журналы изменений сущностей

ReleaseHistoryService

История версий ERP

Плагины регистрируют дополнительные сервисы. Актуальный полный список статических привязок находится в ru.bgcrm.context.core.ServiceModule и DI-модулях плагинов. Правила регистрации и кэширования приведены в разделе DI: RepositoryModule и ServiceModule.

Когда нужен repository

Repository является внутренним слоем хранения. Вызывающий код должен предпочитать сервис, если соответствующая операция существует: сервис добавляет проверки, события, telemetry и согласованную транзакцию.

Прямой repository оправдан внутри реализации сервиса или для новой операции, для которой сервисный контракт ещё проектируется. SQL размещается только в DAO/repository-пакетах.

Добавление сервиса

  1. Создайте интерфейс с узким контрактом и унаследуйте Service.

  2. Реализацию разместите в impl либо оформите фасадом принятого в модуле типа.

  3. Передавайте repositories и другие зависимости через конструктор.

  4. Зарегистрируйте интерфейс в ServiceModule ядра или DI-модуле плагина.

  5. Добавьте unit-тесты реализации и сценарий получения через ServerContext при изменении DI.

  6. Задокументируйте назначение, транзакционные границы, события, ошибки и нетривиальные побочные эффекты.

Не регистрируйте реализацию вместо интерфейса и не сохраняйте сервис в глобальном singleton: его жизненный цикл ограничен ServerContext.