Краткое введение в технологию Enterprise JavaBeans

Сергей Семихатов,
Оригинал статьи опубликован на сайте Javable.com

Введение

Основная идея, лежавшая в разработке технологии Enterprise JavaBeans -- создать такую инфраструктуру для компонент, чтобы они могли бы легко ``вставляться'' (``plug in'') и удаляться из серверов, тем самым увеличивая или снижая функциональность сервера. Технология Enterprise JavaBeans похожа на технологию JavaBeans в том смысле, что она использует ту же самую идею (а именно, создание новой компоненты из уже существующих, готовых и настраиваемых компонент, аналогиично RAD-системам), но во всем остальном Enterprise JavaBeans -- совершенно иная технология.

Отличие от JavaBeans

Технология Enterprise JavaBeans описывается не спецификацией JavaBeans Component Specification, а совсем другим документом -- Enterprise JavaBeans Specification. Если JavaBeans имеют дело лишь с клиентскими компонентами (как правило, это GUI-компоненты, или компоненты, с ними связанные), то EJB описывает каким образом внутри EJB-системы взаимодействуют между собой клиенты и серверы, как EJB-системы взаимодействуют с другими системами и какова роль различных компонент этой системы.

Цели, лежащие в основе технологии EJB

Опубликованная в марте 1998 года EJB-спецификцаия версии 1.0 (Недавно была опубликована версия 1.1 спецификации) определяет следующие цели:

Основы технологии EJB

Для того чтобы понять, как работает и как устроена EJB-система, сначала необходимо рассмотреть ее основные части: EJB-компоненту (component), EJB-контейнер (container) и EJB-объект (object).

EJB-компонента (The Enterprise JavaBeans component)

Отдельная EJB-компонента представляет цобой компоненту в том же смысле что и традиоционный JavaBeans ``bean'' (``зерно''). Компоненты EJB выполняются внутри EJB-контейнера, который, в свою очередь, выполняется внутри EJB-сервера. Любой сервер, который в состоянии поддерживать EJB-контейнеры и предоставлять им необходимые сервисы, может быть EJB-сервером (то есть многие из существующих серверов могут быть просто расширены до поддержки Enterprise JavaBeans).

EJB-компонента представляет из себя Java-класс, который реализует некоторую бизнес-логику. Все остальные классы в EJB-системе либо реализуют поддержку клиент/сервер взаимодйествий между компонентами, либо реализуют некоторые сервисы для компонент.

EJB-контейнер (The Enterprise JavaBeans container)

EJB-контейнер -- это то место, где ``живет'' EJB-компонент. EJB-контейнер реализует для находящихся в нем компонент такие сервисы как транзакции (transaction), управление ресурсами, управление версиями компонент, их мобильностью, настраиваемостью, мобильностью, жизненным циклом. Так как EJB-контейнер реализует все эти функции, то разработчик EJB-компонент может не реализовывать их самостоятельно, а просто вызывать соответсвующие методы у контейнера (правила вызова методов у контейнера описываются в спецификации). Как правило, в одном EJB-контейнере живет несколько однотипных EJB-компонент.

EJB-объект (EJB-object) и удаленный интерфейс (remote interface)

Клиентские приложения вызывают методы на удаленных EJB-компонентах через EJB-объект (EJB-object). EJB-объект реализует ``удаленный интерфейс'' EJB-компоненты на сервере. Суть в том, что находящаяся на сервере EJB-компонента, помимо бизнес-функций, ради которых она была разработана, должна реализовывать также некоторые функции, определяемые спецификацией, которые служат для ``управления'' EJB-компонентой со стороны контейнера. EJB-объект реализует лишь бизнес-интерфейс для EJB-компоненты, являясь, в некотором смысле, ``промежуточным'' звеном между клиентом и EJB-компонентой.

EJB-объекты и EJB-компоненты представляют собой разные классы, хотя ``снаружи'' (при взгляде на их интерфейсы), они выглядят одинаково. Это происходит потому, что они реализуют один и тот же интерфейс (а именно, интерфейс, описанный для EJB-компоненты). Однако при этом они выполняют совершенно разные функции. EJB-компонента выполняется на сервере, внутри EJB-контейнера и реализует бизнес-логику, в то время как EJB-объект выполняется у клиента и удаленно вызывает методы у EJB-компоненты.

В качестве поясняющего примера рассмотрим видеомагнитофон. Предположим, что он является EJB-компонентой. EJB-объект, в таком случае, является аналогом пульта управления (remote control) этого магнитофона. У пульта управления есть все те же кнопки, что и на передней панели видеомагнитофона. Нажатие кнопки на пульте управления приведет к такому же эффекту, что и нажатие кнопки, расположенной на самом магнитофоне, но в результате только магнитофон, а не пульт управления, начнет выполнять функции.

Как работает система

Разработчику, однако, не нужно самому реализовывать EJB-объект. Этот класс создается специальным кодогенератором, поставляемым вместе в EJB-контейнером. Как уже было сказано, EJB-объект (созданный с помощью сервисов контейнера) и EJB-компонента (созданная разработчиком), реализуют один и тот же интерфейс. В результате, когда приложение-клиент хочет вызвать метод у EJB-компоненты, то сначала вызывается аналогичный (по имени) метод у EJB-объекта, что находится на стороне клиента, а тот, в свою очередь, связывается с удаленной EJB-компонентой и вызывает у нее этот метод (с теми же аргументами).

Session и Entity beans

Существует два различных типа ``бинов'': session и entity. Рассмотрим их более подробно.

Session bean

Session bean представляет собой EJB-компоненту, связанную с одним клиентом. ``Бины'' этого типа, как правило, имеют ограниченный срок жизни (хотя это и не обязательно), и редко участвуют в транзакциях. В частности, они обычно не восстанавливаются после сбоя сервера. В качестве примера session bean можно взять ``бин'', который живет в веб-сервере и динамически создает HTML-страницы клиенту, при этом следя за тем, какая именно страница загружена у клиента. Когда же пользователь покидает вэб-узел, или по истечении некоторого времени, session bean уничтожается. Несмотря на то, что в процессе своей работы, session bean мог сохранять некоторую информацию в базе данных, его предназачение заключается все-таки не в отображении состояния или в работе с ``вечными объектами'', а просто в выполнении некоторых функций на стороне сервера от имени одного клиента.

Entity bean

Entity bean, наоборот, представляет собой компоненту, работающую с постоянной (persistent) информацией, хранящейся, например, в базе данных. Entity beans ассоциируются с элементами баз данных и могут быть доступны одновременно нескольким пользователям. Так как информация в базе данных является постоянной, то и entity beans живут постоянно, ``выживая'', тем самым, после сбоев сервера (когда сервер восстанавливается после сбоя, он может восстановить ``бин'' из базы данных).

Например, entity bean может представлять собой строку какой-нибудь таблицы из базы данных, или даже результат операции SELECT. В объектно-ориентированных базах данных, entity bean может представлять собой отдельный объект, со всеми его атрибутами и связями.

Клиент создает на EJB-сервере объекты и работает с ними так же, как если бы это были локальные объекты. Это до предела упрощает разработку клиентов -- практически нет разницы между написанием клиента для локальной машины и для клиента EJB-сервера. Разработчик может легко создавать, использовать и уничтожать объекты, а эти объекты, в свою очередь, выполняются на сервере. Итак, session beans в большинстве своем работают с информацией, относящейся к ``диалогу'' между клиентом и сервером, в то время как entity beans представляют собой экземпляры данных и работают с ``постоянными'' данными из баз данных.

Каждый экземпляр ``бина'' имеет свой уникальный идентификатор. Для entity объектов уникальный идентификатор, как правило, совпадает с (или каким-либо образом получается из) уникального идентификатора данных, которые он представляет. То есть в данном случае существует нечто вроде первичного ключа для всех entity beans. Идентификатор же session beans может быть практически любым -- например он может состоять из имени сервера и порта удаленного соединения, а может создаваться случайным образом.

Создание серверных объектов

Итак, приложение-клиент соединяется с EJB-сервером и посылает ему запрос на создание ``бина'' (Enterprise JavaBean) для обработки своих запросов. Сервер отвечает на такой запрос созданием объекта на стороне сервера (экземпляр EJB-компоненты) и возвращает клиенту прокси-объект (EJB-объект), чей итерфейс совпадает с интерфейсом созданной EJB-компоненты и чьи методы перенаправляют вызовы собственно экземпляру компоненты. После этого приложение-клиент работает с EJB-объектом как с локальным объектом, даже и не подозревая, что всю работу выполняет не EJB-объект, а удаленная компонента на сервере. Необходимо заметить, что созданием и удалением EJB-компонент на сервере занимается EJB-контейнер.

Home interface

У каждой EJB-компоненты есть то, что называют ``родной интерфейс'' (home interface), который опеределяет методы создания, инициализации, удаления и (в случае entity beans) поиска экземпляров EJB-компонент на стороне сервера. ``Родной интерфейс'', по сути, описывает возможные взаимодействия между компонентой и контейнером, а конкретно -- описанные выше.

``Родной интерфейс'' для EJB-компоненты наследуется от интерфейса javax.ejb.EJBHome, который представляет базовую функциональность для взаимодйествия между контейнером и компонентой. Все методы этого интерфейса должны быть RMI-совместимы. Интерфейс также описывает один или более create() методов, которые все называются ключевым словом create, но тело которых различно. Все create методы возвращают объект с ``внешним'' (remote) для данной компоненты интерфейсом.

Когда приложение-клиент хочет создать ``бин'' на сервере, оно вначале использует Java naming and Directory Interface (JNDI) для нахождения объекта с искомым интерфейсом. JNDI представляет собой стандартное расширение Java-пакета и предоставляет глобальный сервис для любого Java-окружения, позволяя Java-программам находить и использовать существующие ресурсы просто по имени, а также позволяя просто извлекать информацию о ресурсах. Использование EJB сервисов, аналогичных JNDI, еще раз подчеркивает тот факт, что цель EJB-систем -- полная совместимость с Java API.

Когда клиент получил ссылку на объект с ``родным'' интерфейсом, он вызывет у этого объекта любой из методов create для создания экземпляра компоненты на сервере. При получении вызова create локальный (находящийся у клиента) объект с ``родным'' интерфейсом удаленно вызывает метод у EJB-контейнера, который и создает экземпляр ``бина'', возвращая клиенту EJB-объект. После этого приложение-клиент вызывает у EJB-объекта методы, исполнение которых перенаправляется на сервер (сначала контейнеру, а потом уже компоненте). Контейнер, при получении вызова к компоненте, просто вызывает у нее соответствующий метод. Единственное, за что ответственен при этом контейнер -- обработка некоторых ошибок (таких, например, как отсутствие искомого экземпляра класса) и соответственное возбуждение исключительных ситуаций.

Entity ``бины'', помимо упоминавшихся, имеют дополнительный интерфейс finder, который используется для поиска по уникальному ключу экземпляра ``бина''.

И, как уже говорилось, ``родной интерфейс'' включает в себя методы, сообщающие контейнеру о необходимости удалить экземпляр компонента. В этом случае сервер производит удаление экземпляра, и любая следующая попытка вызвать метод у удаленной компоненты приведет к возникновению исключительной ситуации.

Литература

  1. Mark Johnson, A beginner's guide to Enterprise JavaBeans, JavaWorld, October 1998.
  2. Sun Microsystems, Enterprise JavaBeans Specification version 1.0, 1998.
  3. Sun Microsystems, JavaBeans Component Specification.
  4. Anne Thomas, Enterprise JavaBeans Server Component Model for Java (Whitepaper), 1997.