Перейти к содержанию

EJB

Спецификация для написания серверной бизнес-логики, которая работает внутри контейнера приложений.

EJB = упакованный бэкэнд-сервис с кучей инфраструктуры из коробки.

EJB из коробки дает:

  1. Транзакции
    • Декларативно: @TransactionAttribute(REQUIRED) и т.п.
    • Контейнер сам начинает/коммитит/откатывает транзакции.
  2. Безопасность
    • Роли и доступ: @RolesAllowed("admin"), @PermitAll, @DenyAll.
    • Контейнер проверяет права до входа в метод.
  3. Пул объектов
    • Для @Stateless и MDB контейнер держит пул, чтобы быстро обслуживать много запросов.
  4. Таймеры
    • Планировщик задач: @Schedule(hour="*", minute="0", second="0") и т.п.
  5. Remote / Local вызовы
    • Можно объявить интерфейс как @Local или @Remote:
    • Local — вызовы внутри того же приложения/процесса.
    • Remote — через сеть (другое приложение, другой сервер).

Основные задачи

Вынести бизнес-логику в отдельный слой (отдельно от JSF/Servlet и т.п.)

пишутся просто классы с аннотациями, а контейнер EJB:

  • создаёт/удаляет объекты,
  • раздаёт их по пулу,
  • включает транзакции,
  • рулит безопасностью,
  • даёт удалённый доступ (RMI, HTTP и т.п.),
  • может обрабатывать сообщения (JMS).

Типы EJB

Session Beans - СИНХРОННЫЕ

  • @Stateless
    • Не хранит состояние между вызовами.
    • Контейнер держит пул экземпляров и кидает любой на любой запцуирос.
    • Подходит для типичных сервисов: UserService, OrderService и т.д.
  • @Stateful
    • Хранит состояние между вызовами для одного клиента (как “session”).
    • Используется, когда логика зависит от последовательности шагов (wizard, корзина и т.п.).
  • @Singleton
    • Один экземпляр на приложение.
    • Для кэшей, глобальных конфигов, счётчиков и т.п.

Message-Driven Beans - АСИНХРОННЫЕ

  • @MessageDriven — слушатель очереди (JMS).
  • Не вызывается напрямую, а реагирует на сообщения из брокера.

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

  1. Жизненный цикл EJB по типам

2.1. Stateless Session Bean

Суть: не хранит состояние между вызовами; контейнер держит пул экземпляров.

Состояния:

  1. Does Not Exist Бина ещё нет.
  2. Pooled (Ready) Контейнер создал объект, вызвал @PostConstruct, положил в пул.
  3. Method Invocation Приходит вызов от клиента → контейнер берёт любой экземпляр из пула, оборачивает в транзакцию/безопасность → вызывает метод → возвращает в пул.
  4. Removed При остановке приложения или сокращении пула контейнер вызывает @PreDestroy и удаляет бин.

Жизненный цикл в картинке:

Does Not Exist → (create) → @PostConstruct → Pooled → (method call) → Pooled → ... → @PreDestroy → Removed

Особенности под капотом: • Клиент видит прокси, а не конкретный объект. • Никакой гарантии, что два вызова пойдут к одному и тому же экземпляру. • Контейнер может создать от 0 до N экземпляров, динамически увеличивая/уменьшая пул.

2.2. Stateful Session Bean

Суть: хранит состояние для конкретного клиента (один клиент → один бин).

Состояния:

  1. Does Not Exist
  2. Method-Ready (Active) Создан, прошёл @PostConstruct, готов обслуживать вызовы этого клиента.
  3. Passive (опционально) Контейнер может “усыпить” бин: • вызывает @PrePassivate, • сериализует состояние на диск/в память, • позже при необходимости: • десериализует, • вызывает @PostActivate.
  4. Removed • по @Remove-методу, • по тайм-ауту, • при остановке приложения → @PreDestroy.

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

Does Not Exist → (create) → @PostConstruct → Active → [@PrePassivate → Passive → @PostActivate → Active]* → @PreDestroy → Removed

Главное отличие от Stateless: • идентичность: конкретный клиент привязан к конкретному экземпляру, пока не будет @Remove; • возможна пассивизация, чтобы не держать их всех в памяти; • никакого пула “анонимных” экземпляров — каждый бин привязан к клиентскому “диалогу”.

2.3. Singleton Session Bean

Суть: один экземпляр на всё приложение.

Состояния:

  1. Does Not Exist
  2. Initialized • создаётся один раз, • вызывается @PostConstruct, • если стоит @Startup, создаётся при запуске приложения.
  3. Method-Ready Обслуживает запросы.
  4. Removed При остановке приложения → @PreDestroy.

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

Does Not Exist → @PostConstruct → Method-Ready → @PreDestroy → Removed

Особенности: • Конкурентность управляется аннотациями: • @Lock(READ) / @Lock(WRITE) — блокировки на уровне методов; • @ConcurrencyManagement(CONTAINER) (по умолчанию) или BEAN. • Часто используется как: • кэш, • глобальный сервис/реестр.

2.4. Message-Driven Bean (MDB)

Суть: слушатель очереди / топика (JMS).

Состояния похожи на Stateless:

  1. Does Not Exist
  2. Pooled Несколько экземпляров, каждый прошёл @PostConstruct.
  3. Message Delivery Приходит сообщение → контейнер выбирает бин из пула → вызывает onMessage() (или аналог).
  4. Removed При остановке или сокращении пула → @PreDestroy.

MDB не вызывается напрямую клиентом, только брокером/контейнером сообщения.

  1. Чем это отличается от CDI-жизненного цикла

CDI-бин: • Живёт по scope: • @RequestScoped → от начала до конца HTTP-запроса; • @SessionScoped → от начала до конца HTTP-сессии; • @ApplicationScoped → всё время жизни приложения; • @Dependent → живёт ровно столько, сколько его владелец. • Lifecycle обычно: • new → @PostConstruct (при первом использовании в своём scope) → рабочее состояние → @PreDestroy (при завершении scope). • Контейнер не обязан: • делать пулы, • пассивировать, • обеспечивать удалённый доступ, • автоматически оборачивать каждый метод в транзакции.

В EJB всё это входит в контракт: • чёткие правила, когда и сколько экземпляров может быть; • что происходит при конкуренции; • где проходят границы транзакций; • как ведут себя методы с @Remove, @PrePassivate, @PostActivate, @Schedule, и т.д.

Если хочешь, дальше можем взять, например, @Stateless и @RequestScoped CDI-бин и прямо по шагам сравнить: • кто создаётся когда, • кто кем кэшируется/пулится, • как ведут себя при нагрузке и многопоточности.


модель работы EJB

жизненный цикл singleton stateful stateless

вызов бина local remote

что имеется ввиду под транзакцией, безопасностью, пуллингом, удаленными вызовами, таймерами и JMS и контексте бина? подробне про то как работает: транзакцией, безопасностью, пуллингом, удаленными вызовами, таймерами и JMS.


Карта типов «бинов» в Jakarta EE

EJB (Enterprise Java Beans) — бизнес-компоненты с «тяжёлым» рантаймом: транзакции, безопасность, таймеры, асинхронность, пуллинг, (опционально) удалённые вызовы — «из коробки».

@Stateless — без состояния между вызовами; контейнер держит пул экземпляров. Хорошо для «сервисов».
@Stateful — состояние на клиента (сеанс); подходит для пошаговых/мастер-сценариев.
@Singleton — один экземпляр на приложение; есть управление конкурентным доступом.
@MessageDriven — обработчик сообщений JMS (асинхронный consumer).

Интерфейсы доступа: @Local, @Remote (для ремоута), @LocalBean (без интерфейса).
Транзакции: @TransactionAttribute(REQUIRED|REQUIRES_NEW|MANDATORY|SUPPORTS|NOT_SUPPORTED|NEVER),
@TransactionManagement(BEAN|CONTAINER).
Безопасность: @RolesAllowed, @PermitAll, @DenyAll, @RunAs.
Асинхронность: @Asynchronous (возврат Future/CompletionStage или void).
Таймеры: @Schedule(cron-like), @Schedules, @Timeout.
Жизненный цикл: @PostConstruct, @PreDestroy; для @Stateful — @Remove.
Для @Singleton: конкурентность @Lock(READ|WRITE), таймаут @AccessTimeout(ms).

CDI-бины (Context and Dependency Injection) — универсальные управляемые контейнером классы: DI, скоупы, квалификаторы, события, продьюсеры, перехватчики, декораторы. Лёгкие, гибкие, часто основной выбор.

Внедрение: @Inject (в поля/конструкторы/сеттеры).
Именование для EL/JSF: @Named("name") (или без имени — берётся по умолчанию).
Квалификаторы (маркировка реализаций): @Qualifier + собственные аннотации (например, @PrimaryDb, @Mock).
Продьюсеры/диспозеры: @Produces (создание бина/ресурса), @Disposes (закрытие).
Стереотипы: @Stereotype — собрать набор аннотаций в одну.

Скоупы (контексты)
@ApplicationScoped — один на приложение.
@SessionScoped — на HTTP-сессию.
@RequestScoped — на запрос.
@ConversationScoped — управляемая «длинная» беседа (JSF use-case).
@Dependent — «без собственного контекста»: живёт столько, сколько потребитель (по умолчанию).

Перехватчики/декораторы/события
Перехватчики: @Interceptor + @AroundInvoke / @AroundConstruct; включение через @Priority или beans.xml.
Декораторы: @Decorator для прокидывания вызовов и добавления поведения.
События: Event<T>/@Observes/@ObservesAsync.
Транзакции и безопасность в CDI
Можно добавлять @Transactional (из jakarta.transaction) на методы CDI-бина для контейнерных транзакций.
Безопасность — через Jakarta Security или интеграцию сервера (также есть аннотации на методах/классах).

JSF Managed Beans — устаревающее именование для Faces-бинов; сейчас вместо @ManagedBean почти всегда используют CDI + @Named.

Старый стиль: @ManagedBean, @RequestScoped/@SessionScoped из jakarta.faces.bean.*, @ViewScoped и т.д.
Современный стиль: CDI + @Named + JSF-скоупы (например, @ViewScoped из jakarta.faces.view.ViewScoped) или обычные CDI-скоупы.
Практика сегодня: не использовать @ManagedBean; использовать CDI-бины, чтобы иметь полноценный DI и кросс-интеграцию.

JAX-RS ресурсы — классы-ресурсы REST (не «бины» по названию, но управляются контейнером и дружат с CDI).

JPA Entities — сущности данных (POJO), не «бины» бизнес-логики, но часто инжектятся в бины через EntityManager.