- Выдержка
- Другие работы
- Помощь в написании
Технология Enterprise JavaBeans (EJB) (реферат, курсовая, диплом, контрольная)
EJB представляет собой высокоуровневый подход к построению распределенных приложений масштаба предприятия, основанный на модели серверных компонентов (server component model) для Java.
Данный подход позволяет изменять архитектуру сервера, расширяя или ограничивая его функциональные возможности в зависимости от решаемых задач путем добавления или удаления компонент.
Краткая история. Фирма Sun Microsystems Inc. анонсировала технологию EJB в 1996 г., а в 1998 г. была представлена первая реализация (версия 1.0). В 2006 г. появилась версия EJB 3.0, которая трансформировалась в настоящее время в версии EJB 3.1, EJB 3.2. Новые версии имеют большее число расширений и более тесно интегрируется с другими технологиями Java.
Версии. EJB 1.0. Это начальная версия, в рамках которой поддерживались stateful и sfafe/ess-компонент, с которыми можно было работать через удаленный интерфейс. В качестве желательной опции рассматривались компоненты, имеющие состояния.
EJB 1.1. В данном релизе в качестве обязательных появились компоненты с состоянием и XML-дескриптор (deployment descriptor).
EJB 2.0. В данном релизе в дополнение к удаленному интерфейсу появился локальный интерфейс, который могли использовать компоненты, работающие в том же контейнере. Появился новый тип компонентов — компоненты, управляемые сообщениями The Message-Driven Bean (MDB), которые могли принимать асинхронные сообщения. Для компонентов с сохранением была определена возможность сохранения состояния средствами контейнера. Появился язык Enterprise JavaBeans Query Language (далее — EJB QL), похожий по структуре на SQL и предназначенный для поиска компонентов.
EJB 2.1. В рамках данного релиза появилась поддержка работы с вебсервисами, расширились возможности EJB QL и в дескрипторе развертывания вместо DTD стала использоваться XML schema.
Можно заметить, что основные различия между версиями состоит в наращивании возможностей.
EJB 3.0. Данный релиз радикально отличается от предшествующих и определяет фактически новую компонентную модель. Основное отличие состоит в том, что пользователь не должен ничего знать о домашнем интерфейсе (Ноте Interface). В рамках данной спецификации используется идея Plain Old Java Objects (POJO). Идея состоит в том, что программист пишет только ту часть кода, которая реализует бизнес-логику. Для того чтобы определить, каким именно способом реализуется бизнес-код, используется механизм аннотаций. Например, если требуется определить интерфейс как локальный, то достаточно описать интерфейс обычным способом и вставить строку аннотацию @Local. Механизм аннотаций позволяет очень существенно упростить процесс разработки.
Таким образом, речь идет о двух разных компонентных моделях и разных философиях разработки компонентом.
Использование EJB позволяет упростить процесс разработки КИС за счет того, что многие функции реализуются контейнерами. Кроме того, EJB можно использовать многократно, причем для повторного использования не требуется перекомпиляция всего проекта.
EJB компоненты хорошо сопрягаются с веб-сервисами и CORBA. Архитектурная модель EJB включает в себя следующие элементы (рис. 6.10):
- • ЛЖ-контейнер;
- • EJB-контейнер;
- • веб-контейнер;
- • клиент;
- • БД.
Рис. 6.10. Архитектурная модель EJB
Одним из побудительных мотивов создания EJB-технологии были сложности CORBA. Однако эволюция технологии EJB привело к тому, что эта технология стала казаться разработчикам чрезмерно сложной, в частности:
- • чрезмерно тяжеловесная модель программирования, требующая работы с несколькими интерфейсами;
- • необходимость непосредственного взаимодействовать с Java Naming Directory Interface (JNDI);
- • необходимость работать с непомерно сложным XML DD.
Эти недостатки устранены в EJB3.0, где используется только один бизнес-интерфейс вместо home и remote интерфейсов, минимизируется использование DD (англ, dynamic document — динамический документ) за счет использования аннотаций. Кроме того, используется новый механизм для сохранения состояния для компонентов-сущностей (Entity Beans’).
Одной из новых черт EJB 3.0 является использование Java Persistence API (JPA) для реализации сохранения состояния.
Показать весь текст
Заполнить форму текущей работой
Брокер объектных запросов — Object Request Broker (ORB). Брокер объектных запросов представляет собой объектную шину, которая позволяет объектам прозрачно генерировать запросы и получать ответы от локальных или удаленных объектов, причем клиент ничего не знает о механизмах, которые используются для создания и сохранения состояния Поскольку CORBA – это только спецификация, которая может быть реализована разными поставщиками, то начиная с CORBA 2.0 определяется взаимодействие (interoperability) ORB разных производителей
CORBA ORB позволяет объектам обнаруживать друг друга во время выполнения (на лету) и вызывать сервисы друг друга, т.е. реализует типовой спектр сервисов распределенного промежуточного программного обеспечения, однако ORB намного более сложен, чем, например, вызовы удаленных процедур, в частности:
- поддерживает как статические, так и динамические вызовы методов;
- отделяет интерфейс от его реализации;
- является самоописываемой системой.
- прозрачность относительно места положения объектов.
Все ORB позволяют реализовывать как статические, так и динамические вызовы методов.
Статические и динамические вызовы методов. CORBA ORB позволяет статически определять вызовы ваших методов во время компиляции или находить их динамически во время выполнения.
К достоинствам статического вызова методом можно отнести наличие строгого контроля типов на стадии компиляции и высокая скорость работы, а динамического — максимальная гибкость при отложенном (на этапе выполнения) связывании. (Следует отметить, что большинство других видов middleware поддерживают только статическое связывание.)
Отделение интерфейса от его реализации. CORBA отделяет интерфейс от его реализации и предоставляет независимые от языка типы данных, что дает возможность вызывать объекты из любого языка и для любой операционной системы.
Самоописываемая система. CORBA предоставляет метаданные на этапе выполнения для описания каждого серверного интерфейса, известного системе. Каждый CORBA ORB должен поддерживать Репозитарий Интерфейсов (Interface Repository), который содержит текущую информацию, описывающую предоставляемые сервером функции и их параметры. Клиенты используют метаданные, чтобы определить, каким образом вызывать сервисы во время выполнения. Метаданные также помогают инструментальным средствам создавать код «на лету». Такие метаданные генерируются автоматически либо прекомпиляторами языка IDL, либо такими компиляторами, которые знают, как генерировать IDL непосредственно из объектно-ориентированного языка.
Прозрачность относительно места положения объектов. ORB может поддерживать взаимодействие между объектами, расположенными в одном процессе, на одном хосте и на разных хостах одной локальной сети. Если требуется организовать взаимодействия с другими объектами, находящимися, например в Internet, то используются сервисы протокола IIOP (Internet Inter-ORB Protocol — Internet-протокола взаимодействия ORB), причем это делается прозрачно для пользователя.
ORB может выступать посредником при взаимодействии между «мелко-зернистыми» объектами, по уровню сложности соответствующих например классам C++, так и для «крупнозернистых» объектов, в качестве которых могут выступать, например бизнес-объекты.
Рис. 10.3. Структура ORB
Структура ORB показана на рис. 10.3.
ORB позволяет устанавливать клиент-серверные отношения между объектами в распределенной компьютерной среде, при этом один и тот же объект может выступать как в качестве клиента, так и в качестве сервера.
Для обращения к серверу клиент может использовать либо статический, либо динамический вызов.
При реализации статического вызова используются стабы (Stub). определяются посредством IDL, cтабы клиента и сервера генерируются компилятором IDL. Клиент должен иметь стаб для каждого интерфейса, который содержит, в частности, код маршалинга. Для обращения к удаленному объекту клинт достаточно просто вызвать метод. С точки зрения клиента стабы — это локальный заместитель (proxy) для удаленного объекта
При реализации динамических вызовов, т.е. вызовов, не использующие предварительно скомпилированные заглушки, клиент использует интерфейс динамического вызова (ИДВ) (Dynamic Invocation Interface), который позволяет обнаруживать методы, которые необходимо вызвать, во время выполнения. CORBA предлагает стандартный API для поиска метаданных, определяющих серверный интерфейс, генерации параметров, удаленного вызова и получения результатов.
Указанные метаданные хранятся в репозитария интерфейсов (Interface Repository), который представляет собой распределенную базу данных, которая содержит в машинном формате версии определенных на IDL интерфейсов.
API Репозитария Интерфейсов (Interface Repository API) позволяет получать доступ описаниям интерфейсов зарегистрированных компонентов, поддерживаемых ими методов и их параметров. В CORBA такие описания называют сигнатурой метода (method signature).
Интерфейс ORB предлагает ряд полезных сервисов, в частности, API для преобразования ссылки на объект в строку и обратно, что может быть полезно в случае, если необходимо сохранять или пересылать ссылки.
ORB предоставляют глобальные идентификаторы — для уникальной и глобальной идентификации компонентов и их интерфейсов среди ORB разных производителей и множества репозитариев, которые генерируются системой и представляет собой уникальную строку, которая используется для поддержания целостности в соглашениях по наименованию.
Сравнивая статические, так и динамические вызовы, следует отметить, статические вызовы намного проще в программировании, они быстрее работают и самодокументируемы. Динамические вызовы предоставляют максимальную гибкость, но они сложнее в программировании, но незаменимы в случае, когда на стороне клиента невозможно установить заглушку.
Серверная часть не может определить разницу между статическим и динамическим вызовом, поскольку оба они имеют одинаковую семантику сообщения. В обоих случаях ORB находит объектный адаптер сервера, передает ему параметры, а затем передает управление коду объекта с помощью заглушки (стаба), который в CORBA называется скелетоном (skeleton) сервера.
На стороне сервера размещаются статические скелетоны, динамические скелетоны и адаптеры объектов.
Статические скелетоны предоставляют статические интерфейсы каждому из реализуемых сервисов. Эти стабы создаются компилятором IDL и определены для каждого класса объектов.
Динамические скелетоны предоставляет механизм связывания реального времени для тех серверов, которым необходимо управлять входящими вызовами методов компонентов не имеющих скомпилированных скелетонов. Динамический скелетон находит значения параметров вызова во входном сообщении и определяет, для какого объекта и метода они предназначены.
Динамические скелетоны используются, в частности, для реализации универсальных мостов между ORB, интерпретаторами и языками сценариев, чтобы динамически сгенерировать реализацию объекта. Динамический скелетон может обрабатывать как статические, так и динамические вызовы клиентов.
Объектный Адаптер (ObjectAdapter) принимает запросы к сервису со стороны серверных объектов и обеспечивает среду реального времени для создания экземпляров серверных объектов, передачи запросов объектам и назначения объектам идентификаторов. Объектный адаптер также регистрирует поддерживаемые им классы и их экземпляры этапа выполнения (т.е. объекты) в Репозитарии Реализаций РР) (Implementation Repository), который представляет собой репозитарий времени выполнения и содержит информацию о классах и объектах, экземпляры которых созданы.
CORBA предлагает два типа адаптеров объектов: базовый адаптер объектов (Basic Object Adapter, BOA) и переносимый адаптер объектов (Portable Object Adapter, POA).
Сервисы CORBA. В качестве базовых сервисов в рамках CORBA используется пятнадцать сервисов:
- сервис Именования (Naming);
- сервис Жизненного Цикла (Life Cycle);
- сервис Событий (Event Service);
- сервис Долговременного Хранения (Persistence Service);
- сервис Контроля Совместного Доступа (Concurrency Control Service);
- сервис Транзакций (Transaction Service);
- сервис Отношений (Relationship Service);
- сервис Внешнего Представления (Externalization Service);
- сервис Запросов (Query Service);
- сервис Лицензирования (Licensing Service);
- сервис Свойств (Properties Service);
- сервис Времени (Time Service);
- сервис Безопасности (Security Service);
- сервис Коммерции (trading Service);
- сервис Контейнеров (Collection Service).
Объектные сервисы являются базовыми строительными блоками для создания распределенной объектной инфраструктуры. Они представляют собой следующий этап в последовательности шагов, направленных на достижение главной цели — создания распределенных компонентов, или, как их называет OMG, бизнес-объекта (business objects).
Базовые сервисы CORBA являются инфраструктурными сервисами независимы не связаны ни с одним предметным доменом.
Объектный Сервис Именования. Сервис Именования – это механизм, используемый объектами ORB для обнаружения других ORB объектов. CORBA имена представляют собой идентификационные значения, которые определяют объект.
Сервис именования отображает CORBA имена в объектные ссылки. Контекст имен (naming context) представляет собой пространство имен (namespace), в котором имена объектов уникальны. Каждый объект имеет уникальный ссылочный идентификатор (reference ID).
Сервис Именования был разработан на основе существующих служб имен и каталогов.
Объектный Сервис Жизненного Цикла (Life Cycle) обеспечивает реализацию таких функций как создание, копирование, перемещение и удаление объектов, может выполнять данные действия над группой связанных объектов.
Сервис Событий (Event Service) позволяет компонентам, находящимся на шине, реагировать на события, происходящие в системе. Объекты имеют возможность регистрировать интерес к определенным системным событиям или отменять такую регистрацию.
Сервис Долговременного Хранения (Persistence Service) – это служба, позволяющая создавать хранилища компонентов в различных средах, включающих плоские файлы и реляционные базы данных.
Сервис Контроля Совместного Доступа (Concurrency Control Service) предоставляет собой механизм, который позволяет выполнять блокировки от имени транзакций и потоков выполнения
Сервис Транзакций (Transaction Service) позволяет организовывать двухфазное завершение (two-phase commit) транзакций для компонентов, при этом имеется возможность работать не только с простыми (flat), но и вложенные (nested) транзакции.
Сервис Отношений (Relationship Service) позволяет создавать динамические ассоциаций между компонентами, непосредственно не связанными друг с другом.
Данный сервис используется, преимущественно для обеспечения целостности.
Сервис Внешнего Представления (Externalization Service) обеспечивает стандартный способ для передачи данных компоненту и обратно, а также для пересылки самих компонентов по сети. По сути – это сервис сериализации.
Сервис Запросов (Query Service) позволяет выполнять запросы для объектов, в частности, находить объекты по их свойствам. В основе Сервиса Запросов лежит SQL3 и язык объектных запросов (Object Query Language).
Сервис Лицензирования (Licensing Service) позволяет отслеживать использование компонентов с целью получения платы.
Сервис Свойств (Properties Service) предоставляет доступ к свойствам компонентов, позволяет, в частности, читать значения свойств, изменять значения свойств, изменять состав свойств.
Сервис Времени (Time Service) предоставляет интерфейсы для синхронизации часов в распределенной среде и опеспечивает возможность управлять событиями, привязанными к астрономическому времени.
Сервис Безопасности (Security Service) позволяет поддерживать инфраструктуру для обеспечения безопасности системы распределенных объектов, включая такие механизмы как аутентификацию, списки контроля доступа и конфиденциальность и, кроме того, отвечает за делегирование прав доступа к объектам.
Сервис Коммерции или Трейдер Сервис (Trader Service) – это сервис «Желтых страниц» для объектов; позволяющий опубликовывать предлагаемые сервисы и находить их.
Сервис Контейнеров (Collection Service) позволяет создавать контейнеры, в которые можно помещать компоненты и формировать из них контейнеры.
Средства CORBA (Common Facilities) делятся на вертикальные и горизонтальные.
Горизонтальные универсальные средства определяют интерфейсы, не зависящие от предметной области.
Горизонтальные средства включают:
- средства пользовательского интерфейса (USER Interface), которые включают инструменты для разработки интерфейса, средства для автоматизации разработки интерфейса, спецификации на рабочее пространство пользователя и т.д.;
- средства управления информацией (Information management), которые предоставляют операции, с помощью которых можно моделировать, описывать, сохранять, выбирать, перемещать информацию и обмениваться ею;
- средства управления системой, включающие множество утилит, реализующих функции системного администрирования, то есть определяют интерфейсы основных операций, обеспечивающих управление, мониторинг, безопасность, конфигурирование и т.д.;
- средства управления задачами, включающие средства управления потоками работ (workflow facility), средства программных агентов (agent facility), средства управления правилами (rule management facility), средства автоматизации (automation facility).
Вертикальные средства предназначены для поддержки конкретных областей рынка: финансовой деятельности, промышленного производства, медицины и т.д. [141].
10.3. Технология Enterprise JavaBeans
Технология EnterpriseJavaBeans (EJB) представляет собой высокоуровневый подход к построению распределённых приложений масштаба предприятия. EJB — это модель серверных компонентов (servercomponentmodel) для Java.
Основная идея технологии Enterprise JavaBeans состоит в создании такой инфраструктуры для компонент, чтобы они могли легко добавляться (plugin) и удаляться из серверов, тем самым расширяя или ограничивая функциональность сервера.
Краткая история. Фирма Sun Microsystems Inc. анонсировала технологию EJB в 1996 году, а в 1998 года была представлена первая реализация (версия 1.0). На момент написания книги последней была версия EJB 3.0, которая появилась в 2006 году.
Версии. EJB 1.0. Это начальная версия, в рамках которой поддерживались stateful и stateless компонент, с которыми можно было работать через удаленный интерфейс. В качестве желательной опции рассматривались компоненты, имеющие состояния.
EJB 1.1. В данном релизе в качестве обязательных появились компоненты с состоянием и XML дескриптор (deployment descriptor).
EJB 2.0. В данном релизе в дополнение к удаленному интерфейсу появился локальный интерфейс, который могли использовать компоненты, работающие в том же контейнере. Появился новый тип компонентов – компоненты, управляемые сообщениями the message-driven bean (MDB), которые могли принимать асинхронные сообщения. Для компонентов с сохранением была определена возможность сохранения состояния средствами контейнера. Появился язык Enterprise JavaBeans Query Language
(EJB QL), похожий по структуре на SQL, и предназначенный для поиска компонентов.
EJB 2.1. В рамках данного релиза появилась поддержка работы с Web-сервисами, расширились возможности EJB QL и в дескрипторе развертывания вместо DTD стала использоваться XML schema.
Можно заметить, что основные различия между версиями состоит в наращивании возможностей.
EJB 3. Данный релиз радикально отличается от предшествующих и определяет фактически новую компонентную модель. Основное отличие состоит в том, что пользователь не должен ничего знать о домашнем интерфейсе (Home Interface). В рамках данной спецификации используется идея POJO (Plain Old Java Objects) .Идея состоит в том, что программист пишет только ту часть кода, которая реализует бизнес-логику. Для того, чтобы определить каким именно способом реализуется бизнес код, используется механизм аннотаций. Например, если требуется определить интерфейс как локальный, то достаточно описать интерфейс обычным способом и вставить строку аннотацию @Local. Механизм аннотаций позволяет очень существенно упростить процесс разработки.
Таким образом, речь идет о двух разных компонентных моделях и разных философиях разработки компонентом.
Использование EJB позволяет упростить процесс разработки КИС за счет того, что многие функции реализуются контейнерами. Кроме того, EJB можно использовать многократно, причем для повторного использования не требуется перекомпиляция всего проекта.
Рис. 10.4. Архитектурная модель EJB
EJB компоненты хорошо сопрягаются с Web-сервисами и с CORBA.
Архитектурная модель EJB включает в себя следующие элементы (рис. 10.4):
- JEE контейнер;
- EJB контейнер;
- Web- контейнер;
- клиент;
- база данных (БД).
JEE контейнер представляет собой EJB- совместимый сервер приложений, внутри которого имеются EJB контейнер и Web- контейнер. EJB-компоненты функционируют внутри EJB контейнера, а сервлеты и JSP – внутри Web- контейнера. БД используется для хранения состояния EJB-компонентов. Для взаимодействия с контейнером EJB-компонент используют Home-интерфейс, а для взаимодействия с клиентом – Remote- интерфейс.
Кроме того, в процессе функционирования EJB-компоненты пользуются такими сервисами как JNDI, JTS, систем безопасности и т.п.
Рассмотрим основные компоненты архитектуры EJB.
JEE сервер. JEE совместимый сервер приложений обеспечивает следующие основные сервисы:
- HTTP-сервис;
- сервисы безопасности;
- Java Naming and Directory Interface (JND) – сервисы.
EJB-контейнер реализует следующие сервисы:
- управление жизненным циклом компонента;
- управление транзакциями;
- управление персистностью.
Рис. 10.5. Структура EJB-контейнера
EJB-контейнер поддерживает интерфейс для EJB-компонентов. Клиенты никогда не обращаются напрямую к EJB-компонентам. Все обращения идут к контейнеру, который выполняет функции посредника. На рис. 10.5 показана структура EJB-контейнера. Когда компоненты ходят обратиться к внешним компонентам, то используется информация, содержащаяся в контексте. EJB-контейнер реализует такие функции как создание и уничтожение EJB-компонентов.
EJB-компоненты образуют распределенную компонентную систему. Приложения и другие компоненты обычно могут обращаться к EJB-компоненту через удаленный интерфейс. Если вызывающий и вызываемый компоненты находятся в одном контейнере, то используется локальный интерфейс. Для того, чтобы поместить EJB-компонент в контейнер, необходимо отредактировать дескриптор размещения – (Deployment Descriptor, DD), который представляет собой XML –документ.
Компонентная модель EJB 2.Х. Каждый EJB-компонент имеет бизнес-интерфейс, через который клиент может обратиться к данному компоненту, при этом клиенту могут быть неизвестны подробности, касающиеся, в частности, места нахождения компонента. Этот интерфейс называют удаленным (remote interface). Конкретный экземпляр EJB-компонента управляется контейнером через домашний интерфейс (home interface). Каждый EJB-компонент должен поддерживать как удаленный, так и домашний интерфейс.
Рис. 10.6. Структура EJB-компонента
Конфигурирование EJB-компонента осуществляется посредством редактирования конфигурационного файла. Структура EJB-компонента и процесс взаимодействия клиента и EJB-компонента показан на рис. 10.6.
EJB класс реализует эти два интерфейса. Взаимодействие осуществляется следующим образом. Клиент обращается к компоненту по имени (Lookup), которое используется для получения объектной ссылки (Object Reference, OR) через JNDI сервис. При обращении к контейнеру (Create) он создает экземпляр EJB-компонента и передает ему параметры вызова. Очевидно, что для того, чтобы можно было получать ссылки, компоненты должны быть предварительно зарегистрированы с помощью JNDI. Затем вызывается требуемый метод (Invoke).
EJB-компонент представляет собой программный компонент, который может быть повторно использован без перекомпиляции в разных приложениях. Для использования EJB-компонента достаточно поместить его в соответствующий каталог и выполнить настройки конфигурационного файла, который называют Deployment Descriptor (DD). DD представляет собой XML файл.
Компонентная модель EJB определяет три основных типа компонентов:
- сеансовые компоненты (Session Beans);
- компоненты-сущности (Entity Beans);
- компоненты, ориентированные на сообщения (Message Driven Beans).
В свою очередь, сеансовые компоненты делятся на две группы:
- сеансовые компоненты без состояния (Stateless Session Beans);
- сеансовые компоненты с состоянием (Stateful Session Beans).
Сеансовые компоненты без состояния предназначены для выполнения бизнес-операций, для выполнения которых не требуется сохранять внутреннее состояние компонента. К таким операциям можно отнести операции, связанные с поиском слов в словаре, архивирования файлов, калькуляторы.
Компоненты данного типа можно реализовать в виде Web-сервисов.
Сеансовые компоненты с состоянием помнят свое состояние только в пределах сеанса.
Время жизни таких компонентов соответствует одному сеансу, продолжительность которого может составлять от нескольких секунд до нескольких часов и даже дней.
Типичным примером использования Сеансовых компонентов с состоянием Интернет-магазин. EJB-компонент может описывать, например, описывает содержимое корзины покупателя. Тогда сеансом будет считаться время с момента регистрации пользователя на сайте магазина до момента закрытия пользователем браузера или перехода к другому сайту.
Компоненты-сущности, напротив, способны поддерживать свое состояние. Их состояние сохраняется в реляционной базе данных. Каждому компоненту обычно ставится в соответствие строка базы данных. В рамках компонентной модели EJB 2.Х выделяется два варианта управления состоянием компонента: ручное сохранение (Bean Managed Persistence, BMP) и автоматическое сохранение (Container Managed Persistence, CMP).
В первом случае ответственность за сохранение состояние возлагается на компонент, т.е. на программиста. Во втором случае сохранение и восстановление состояние возлагается на контейнер. Информацию, необходимую для работы с БД контейнер берет из дескриптора размещения (Deployment Descriptor, DD), который представляет собой XML файл.
При работе с компонентами-сущностями можно использовать EJB QL, который позволяет находить компоненты по первичному ключу или значениям отдельных полей.
Компоненты, ориентированные на сообщения предоставляют асинхронный интерфейс. Такому компоненту можно отослать сообщение и продолжать работу сразу после окончания его передачи, не дожидаясь окончания его обработки, призваны взаимодействовать с системами очередей сообщений, в первую очередь с JMS. Обычно компоненты, ориентированные на сообщения, выполняют роль адаптеров, принимающих асинхронные сообщения, что полезно при построении систем, ориентированных на работу с событиями.
Жизненный цикл и роли при работе с EJB. Как для всякой компонентной системы для EJB выделение типовых ролей при разработке и сопровождении приложений, использующих EJB.
- применительно к EJBвыделяются следующие роли:
- провайдер сервера EJB;
- провайдер контейнера EJB;
- разработчик EJB;
- специалист по внедрению/установке EJB;
- разработчик приложения.
Провайдер сервера EJB – это производитель EJB-совместимого сервера приложений.
Производитель сервера EJB может также выступать в качестве производителя контейнера EJB.
Провайдер контейнера EJB — это производитель EJB-контейнера. Производитель сервера EJB обычно выступает в качестве производителя контейнера EJB. Как правило, это крупные фирмы или организации, такие как IBM или Oracle.
Разработчик EJB – это разработчик или группа разработчиков, которые имеют не только знания о спецификации EJB, но и бизнес-требования, т.к. он отвечает за кодирование бизнес-логики в серверных компонентах. Разработчик EJB может создавать EJB-компоненты как для нужд конкретной организации, так и на продажу. Спецификация EJB называет разработчика EJB провайдером EJB.
Специалист по внедрению/установке EJBответственен за определение EJB, всех поддерживающих классов и их правильную инсталляцию на сервере EJB.
Разработчик приложения пишет клиентские приложения, используя EJB-компонентов. Обычно разработчик приложения имеет возможность подключать готовые EJB-компоненты без необходимости их разработки или тестирования.
Спецификация EJB называет разработчика приложения ассемблером приложения.
Модель размещения EJB-компонента. После того как разработка кода клиента и сервера завершена, выполняется их компилирование в файлы классов. EJB-компонент упаковывается в .jar, который, в свою очередь, вместе с другими Web-компонентами (.war), DD XML файлы и коды клиентской части (.jar) упаковываются в .ear файлы.
DD – это файл размещения в XML формате. Этот файл создается обычно автоматически. Ниже приведен фрагмент DD файла:
accountBeanaccounthomeaccountAccount
Container
Integer
…
id
…
name
…
…
Особенности компонентной модели EJB 3.0. Одним из побудительных мотивов создания EJB технологии были сложности CORBA. Однако эволюция технологии EJB привело к тому, что эта технология стала казаться разработчикам чрезмерно сложной, в частности:
- чрезмерно тяжеловесная модель программирования, требующая работы с несколькими интерфейсами;
- необходимость непосредственного взаимодействовать с Java Naming Directory Interface (JNDI);
- необходимость работать с непомерно сложным XML DD.
Эти недостатки устранены в EJB3.0, где используется только один бизнес-интерфейс вместо home и remote интерфейсов, минимизируется использование DD за счет использования аннотаций. Кроме того, используется новый механизм для сохранения состояния для компонентов-сущностей (Entity Beans).
Одной из новых черт EJB 3 является использование JavaPersistenceAPI (JPA) для реализации сохранения состояния.
Сохранения состояния (Персистенс) – это способность автоматически сохранять состояние Java объектов в реляционных базах данных.
JPA – это самостоятельная технология, которая обеспечивает объектно-реляционное отображение JAVA объектов и предоставляющая API для сохранения, получения и управления такими объектами. Собственно JPA – это спецификация, которая представляет собой часть EJB3 спецификации. Наиболее известными реализациями JPA являются Hibernate, Oracle TopLink, Apache OpenJPA.
JPA состоит из трех элементов:
- API – интерфейсы в пакете javax.persistance, представляющий собой набор интерфейсов;
- JPQL – объектный язык запросов, похожий на SQL, но запросы выполняются к объектам;
- Metadata – аннотации над объектами, которые представляют собой набор аннотаций, которыми описывают объектно-реляционные отображения. Метаданные можно описывать либо с помощью XML файлов, либо с помощью аннотаций.
Аннотирование является одной из ключевых особенностей программирования в технологии EJB 3.0. Эта возможность позволяет разработчикам аннотировать программные элементы непосредственно в исходных текстах на языке Java с целью управлять поведением или развертыванием компонентов.
Механизм аннотаций введен в язык Java, начиная с версии 1.5. Аннотации не меняют смысл программы, однако, позволяют непосредственно в тексте программы помещать указания для различных инструментальных средств. Механизм аннотаций позволяет вводить новые типы аннотаций и использовать существующие для аннотирования программных конструкций.
Ниже приведен пример использования механизма аннотаций. Интерфейс описывается как обычный Java интерфейс (Plain Old Java Interface, POJI). Класс компонента представляет собой обычный Java объект (Plain Old Java Object, POJO). Строка @Stateless представляет собой аннотацию, которая указывает на то, данный объект должен быть реализован как EJB-компонент без сохранения состояния. Для того, исполнить этот компонент, его надо поместить в EJB-контейнер.
package ejb3component.example;
public interface Hello {
public void Hello(String name);
}
package ejb3component.example;
import javax.ejb.Stateless;
@Stateless
public class HelloBean implements Hello {
public void Hello(String name) {
System.out.println(«Hello » + name);
}
}
Lis
tНа данном примере достаточно хорошо просматривается идея POJO, которая состоит в том, пользователь пишет только код, который реализует требуемую функциональность, а способ реализации указывает в аннотациях [142].
10.4. Компонентная модель .NET
.NETFramework — программная платформа компании Microsoft, предназначенная как для создания обычных программ и веб-приложений. .NET является патентованной технологией.
В основу .NET Framework была положена амбициозная идея сделать независимую от платформы универсальную виртуальную машину, которая могла бы выполнять код, написанный на произвольном языке программирования в различных ОС без перекомпиляции кода. Однако со временем Microsoft ограничилась поддержкой только собственных ОС, предоставив независимым разработчикам заниматься поддержкой других платформ.
Основными составными частями .NET Framework являются инвариантная к языку программирования среда исполнения (common language runtime, CLR) и библиотека классов Framework (framework class library, FCL). CLR – это некоторая обертка для API ОС, которая служит средой для исполнения управляемых приложений (managed applications). FCL предоставляет объектно-ориентированный API, к которому обращаются управляемые приложения.
При работе с управляемыми приложениями программист теряет возможность работать с Windows API, MFC, ATL, COM и других знакомых инструментов и технологий и должен работать с FCL.
Если программист не хочет отказываться от «старых» технологий, то ему предоставляется возможность создавать приложения, основанные на использовании неуправляемого кода, который исполняется без использования CLR. Совмещение в рамках одного приложения управляемого и неуправляемого кода возможно, но не приветствуется разработчиками платформы.
Инвариантная к языку программирования достигается за счет того, что среда разработки создаёт байт-код, который интерпретируется виртуальной машиной. Встроенные (поставляются вместе с .NET Framework). В качестве основных языков, поддерживаемых платформой .NET, выступают: C#, VB.NET, JScript .NET, C++/CLI, IronPython, IronRuby и F# (функциональный язык общего назначения).
В качестве входного языка виртуальной машины в .NET используется Common Intermediate Language (CIL), (В более ранних версиях он назывался Microsoft Intermediate Language (MSIL)).
Применение байт-кода позволяет получить кроссплатформенность на уровне скомпилированного проекта, который называют сборкой. Функцию преобразования сборки в исполняемый код целевого процессора реализует JIT-компилятор (just in time), который выполняет компиляцию «на лету».
Кроме того, имеется утилита, которая компилирует сборку в родной (native) код для выбранной платформы.
Данный подход идентичен используемому в Java виртуальной машине.
Опыт использования виртуальных машин, как в рамках Java платформы, так и в рамках .NET показал, что их применение не приводит к резкому падению скорости работы приложений, а часто оказывается близкой.
Этот феномен можно объяснить тремя причинами. Во-первых, постоянно растет производительность аппаратных средств. Во-вторых, большая часть исполняемого кода – это библиотечный, т.е. уже скомпилированный код. В-третьих, постоянно повышается скорость работы компиляторов.
Microsoft начала разрабатывать .NET Framework в конце 1990-х годов, и первая версия .NET 1.0 была выпущена в начале 2002 года.
Рис. 10.7. Стек технологий .NET
На момент написания данной книги основной являлась версия 4.0, которая поддерживается средой разработки Microsoft Visual Studio 2010 [143].
Практически каждая новая версия включала в себя новые технологии. Стек технологий .NET показан на рис. 10.7.
Назначение Среды выполнения и Базовой библиотеки классов описано выше.
Система построения клиентских приложений (Windows Presentation Foundation, WPF) предназначена создания как автономных, так и запускаемых в браузере приложений.
WPF представляет собой векторную система визуализации и широко использует язык XAML (Extensible Application Markup Language), представляющий собой XML, в котором реализованы классы .NET Framework. Кроме того, используются такие элементы как элементы управления, привязку данных, макеты, двухмерную и трехмерную графику, анимацию, стили, шаблоны, документы, текст, мультимедиа и оформление.
Основой WPF является DirectX, что позволяет использовать аппаратные ускорители.
Система обмена данными между приложениями (Windows Communication Foundation, WCF) представляет собой программный фреймворк, используемый для обмена данными между приложениями и входящий в состав .NET Framework.
WCF позволяет комбинировать функциональность различных технологий .NET таких как ASP.NET, Web Services, .NET Remoting, .NET Enterprise Services и System.Messaging для создания распределённых приложений
Система управления рабочими процессами (Windows Workflow Foundation, WF) — это технология для определения, выполнения и управления рабочими процессами.
WF использует визуальное программирование и в ее основе лежит декларативная модель программирования.
Использование WF предлагает три способа описания:
— последовательный процесс (Sequential Workflow);
— описание процесса в терминах конечный автомат;
— описание процесса с помощью правил.
Технология единого входа (Windows CardSpace, WCS) — это система идентификации пользователей при работе с разными ресурсами без необходимости повторного ввода имен и паролей.
Данная технология является собственностью Microsoft, что затрудняет ее использование при работе с сторонними приложениями.
Windows CardSpace — патентованная технология единого входа от Microsoft. WCS — это способ простой и безопасной идентификации пользователей при перемещении между ресурсами Интернета без необходимости повторного ввода имен и паролей.
Модель доступа к данным (ADO.NET (ActiveX Data Objects .NET))- интерфейс программирования приложений для доступа к данным, основанный на технологии компонентов ActiveX., позволяющий представлять данные из разнообразных источников, таких как реляционных баз данных, текстовых файлов и т. д. в объектно-ориентированном виде.
Язык интегрированных запросов (LanguageIntegratedQuery,LINQ) — Позволяет поддерживать механизм запросов для коллекций объектов в памяти, реляционных баз данных и данных в формате XML, обладает расширяемой архитектурой, которая позволяет сторонним разработчикам реализовать доступ к их хранилищам данных через механизм LINQ.
Параллельные расширения (Microsoft Parallel Extensions for .Net) включает два компонента:
— библиотеку параллельных задач (Task Parallel Library, TPL);
— язык параллельных интегрированных запросов (Parallel Language-Integrated Query, PLINQ).
Параллельные расширения ориентированы на работу с управляемым кодом и позволяют распараллеливать задачи, при работе в мультипроцессорных системах с общей памятью и, в частности, при использовании многоядерных процессоров.
Библиотека параллельных задач. В качестве базового понятия используется понятие задача (Task). Задача – это фрагмент кода, который может выполняться независимо от других фрагментов (задач). Как PLINQ, так и TPL предлагают API для создания задач. При этом PLINQ разбивает запрос на отдельные запросы (задачи), а TPL разбивает задачу на подзадачи, разбивая циклы или последовательность блоков кода на задачи. Для синхронизации имеются соответствующие примитивы.
Параллельный интегрированный язык запросов (Parallel Language-Integrated Query, PLINQ) — является параллельной реализацией LINQ. В отличие от LINQ PLINQ поддерживает параллельное выполнение запросов, используя, все доступные ядра/процессоры.
Для поддержки параллельных расширений используется менеджер задач, на который возлагаются функции планирования. Планирование осуществляется на уровне потоков (нитей).
Компонентная модель .NET. Компонент .NET представляет собой прекомпилированный MSIL, который может быть помещен в любой другой MSIL компонент или клиентскую программу без выполнения компиляции.
Компонент .NET представляет собой прекомпилированный самоописываемый MSIL модуль, построенный на базе одного или более классов или модулей, расположенных в DLL файле сборки (DLL assembly file) [143].
Сборки представляют собой базовые строительные блоки, которые обеспечивают развертывание и выполнение приложений .NET.
Исполняемый файл, библиотека или файл ресурсов, созданный на платформе .NET, представляет собой сборку. Кроме того, сборки обеспечивают реализацию механизма работы с версиями, область действия типов и ресурсов, зависимости и управление правами доступа.
Принципиальным отличием сборок от EXE- и DLL-файлов является то, что метаданные, описывающие содержимое, при работе со сборками хранятся внутри сборок, а при работе с EXE- и DLL-файлами метаданные хранятся в отдельных файлах.
Структура сборки. Сборка представляет собой совокупность элементов, образующих сегмент приложения. Обычно в состав приложения входит несколько сборок. Сборка состоит из четырех элементов.
- манифест;
- метаданные;
- код приложения;
- ресурсы.
Манифест (manifest) содержит имя сборки, информация о версии, информация о файлах, входящих в состав сборки и безопасности.
Метаданные (metadata)- это информация о типах, объявленных в сборке, имена типов, их областях видимости, базовые классы и реализуемые интерфейсы.
Код приложения — это код, который компилируется в формат промежуточного языка Microsoft (Microsoft Intermediate Language, MSIL) и реализует типы, описываемые метаданными.
Ресурсы – это графические файлы, курсоры и статический текст
Наличие в сборке метаданных и декларации означает, что сборка является полностью самодокументированной.
Кроме того, сборка также может содержать неуправляемый код и неуправляемые данные. Существует множество способов группировки элементов в сборке. Обязательным элементом сборки является манифест.
Сборка может представлять собой либо один физический файл, либо может быть распределен среди нескольких файлов. Чаще всего сборка оформляется в виде одного файла. Такой файл называют переносимым исполняемым файлом (Portable Executable — РЕ). Сборки, состоящие из одного файла обычно включают декларацию, метаданные и код MSIL.
Если сборка содержит несколько файлов, ее элементы размещаются в отдельных модулях.
Модули могут состоять из откомпилированного кода MSIL, ресурсов. Модули, которые образуют многофайловую сборку, хранятся в файловой системе как отдельные файлы и связываются только логически через декларацию сборки, где содержится детальная информация о файлах, составляющих сборку.
Рис. 10.8. Типовая структура однофайловой сборки
Типовая структура однофайловой сборки показана на рис. 10.8, а многофайловой – на рис. 10.9.
Рис. 10.9. Типовая структура многофайловой сборки
Среда CLR работает с многофайловой сборкой как с единым объектом.
Лишь один из модулей сборки может содержать декларацию. При этом возможна ситуация, когда единственный модуль включает только декларацию. Но чаще всего декларация оказывается упакованной в один из связанных модулей.
В .NET имеется много разных типов компонентов. В частности, можно выделить «визуальные» и «невизуальные» компоненты. Визуальные компоненты имеют иконки и в процессе разработки их можно перетаскивать в проект.
Незизуальные компоненты или просто .NET component могут работать на стороне клиента, сервера или в составе промежуточного ПО. Независимо от того где он находится, .NET component всегда предоставляет своему клиенту некоторый сервис.
В качестве клиента может выступать как другой компонент, так и клиентское приложение.
.NET component может быть либо локальным (local component), либо распределенным (distributed component). Локальный компонент ((.dll) доступен локально (внутри домена приложения) на одном хосте. Удаленный (распределенный) компонент может быть доступен удаленно из других доменов приложений на том же или другом хосте. Домен приложений – это легковесный процесс, который может быть запущен и остановлен независимо от других легковесных процессов.
Следует заметить, что компонент не может напрямую обращаться к компоненту, находящемуся в другом домене приложений, поскольку каждому домену приложений соответствует собственное адресное пространство.
.NET DLL component может быть установлен как частный компонент (private component), который может работать только с определенным клиентом, либо как разделяемый (shared public component), которому неизвестен клиент. DLL компоненты можно включать в любые приложения .
10.5. OSGi
OSGi (Open Services Gateway Initiative) — спецификация динамической модульной шины для создания Java-приложений. Основным разработчиком является консорциум OSGi Alliance [144].
Инициатива OSGi была выдвинута в 1999г., группой 15 компаний. Идея состояла в том, чтобы множество устройств, начиная от бытовых систем и заканчивая промышленными роботами, могли взаимодействовать между собой через Интернету посредством использования универсального шлюза, построенного на основе технологии Java.
В результате должен был появиться отраслевой стандарт платформы для приложений Java, позволяющей нескольким приложениям безопасно работать с одной виртуальной машиной Java (Java Virtual Machine, JVM), кроме того, приложения могут совместно работать с такими ресурсами как данные, функции и нити (threads). Сервисная платформа OSGi должна была позволять создавать приложения из небольших, взаимодействующих друг с другом (collaborative) компонентов. Изначально OSGi разрабатывалась для использования в составе встроенных систем различного назначения, однако постепенно область применения расширилась и данная спецификация стала использоваться для построения как десктоп-приложений, так и корпоративных приложений.
Следует заметить, что данная модель компонентных приложений является прямым конкурентом платформе Microsoft .Net,
Версии стандарта OSGi. Первая версия спецификации OSGi появилась в мае 2000 года, вторая – в октябре 2001 года, третья – в октябре 2006 года. На момент написания книги последней была версия 4.3, которая появилась в апреле 2011 года. В марте 2010 появилась спецификация OSGi для корпоративных систем (Enterprise Specification).
Имеется достаточно много как бесплатных, так и распространяемых реализаций OSGi, относящимся к разным версиям спецификации. Среди наиболее популярных реализаций стандарта с открытым исходным кодом: Apache Felix, Knopflerfish, Concierge OSGi и Equinox.
Apache Felix —фреймворк, являющийся реализацией спецификации OSGi Release 4. Основой данного фреймворка является проект Oscar из состава ObjectWeb, позднее этот стал проектом верхнего уровня некоммерческой организации Apache Software Foundation.
Knopflerfish — некоммерческая организация, развивающая технологию OSGi. Проект представляет собой свободную сертифицированную реализацию спецификации OSGi R4 v4.2, а также связанные с ней инструменты и приложения.
Concierge — фреймворк, реализующий спецификацию OSGi (Open Service Gateway Initiative) R3, предназначен для устройств с ограниченными ресурсами, таких как мобильные и встраиваемые системы.
Equinox — проект Eclipse который представляет собой фреймворк, реализующий спецификацию OSGi версии 4. Equinox по свой сути является системой поддержки плагинов, которая позволяет разработчикам создавать приложения в виде набора бандлов, использующих общие сервисы и инфраструктуру. В версии Eclipse 3.0 Equinox заменил старую систему поддержки плагинов, использовавшуюся в более ранних версиях. Таким образом, технология OSGi предоставляет сервис-ориентированную платформу с поддержкой модульности для разработки приложений.
На основе Equinox построена среда разработки Eclipse 3.0+, претендующая на звание отраслевого стандарта компонентной сборки программ, что позволило использовать Eclipse не только как среду разработки (IDE), но и как платформу для создания приложений различного профиля и уровня сложности, в ядре которой OSGi используется для управления работы встраиваемых плагинов (plugin).
Платформа OSGi имеет две составляющие: OSGi фреймворк (OSGi framework) и стандартные сервисы OSGi (OSGi standart services). Фреймворк играет основную роль, он является средой, в которой исполняются приложения и которая обеспечивает предписываемую стандартом OSGi функциональность. Стандартные сервисы определяют интерфейс для общих задач, например запуск сервлетов, управление питанием, управление устройствами, ведение протокола работы и т.д.
Архитектура OSGi. Фреймворк является ядром сервисной платформы OSGi, которая обеспечивает безопасную управляемую среду исполнения, которая загружать и исполнять приложения, которые называют bundles (модули).OSGi-совместимые устройства могут загружать, устанавливать и удалять модули в процессе функционирования, при этом ядро автоматически отслеживает зависимость между модулями.
OSGi имеет многослойную архитектуру (рис. 10.10), при этом в рамках OSGi выделяются следующие слои (layers):
— уровень безопасности;
— уровень управления модулями системы;
— уровень управления жизненного цикла OSGi компонент;
— уровень управления сервисами.
Рис. 10.10
Уровень безопасности (Security Layer) реализует модель безопасности Java 2.
Уровень управления модулями системы (Module layer) – уровень управления модулями системы, связанный с компоновкой, разделением и совместным использованием кода. Основной задачей этого уровня является предоставление другим компонентам доступа к заданному внешнему интерфейсу компонента, скрывая при этом его внутреннюю реализацию, и определение модулей, которые необходимы для успешного функционирования данного компонента (то есть определение модулей, наличие которых необходимо). Чтобы различать традиционные модули java и OSGi модули, было введено понятие bundle, который в реально является обычным архивом jar с указанной в файле META-INF/MANIFEST дополнительной конфигурационной информацией;
Уровень управления жизненного цикла (Lifecycle layer) – это уровень, который предоставляет возможность управлять жизненным циклом OSGi компонента и в определенные моменты производить необходимые действия, такие как установление соединения с базой данных или запуск фоновый процесса при инициализации работы модуля, при этом OSGi-компонент в каждый конкретный момент времени находится в одном из следующих 6 состояний:
— модуль установлен (installed);
— разрешены все зависимости (resolved);
— запуск модуля (starting);
— модуль запустился (active);
— модуль остановлен (stopping);
— модуль удален (stopping).
Уровень управления сервисами (Service Layer) – это уровень управления сервисами, который отвечает за динамическую зарегистрацию интерфейсов в реестре сервисов OSGi (SOA Registry), что позволяет другим компонентам динамически находить и использовать зарегистрированные сервисы.
OSGi часто называют «малой СОА» или «SOA in small», поскольку изначально был ориентирован преимущественно на работу с периферийными устройствами [145].
Note java.beans: This package has been deprecated in Java 9 and later versions, in favor of using annotations and other modern ways of creating beans.
Enterprise Java Beans (EJB) is one of the several Java APIs for standard manufacture of enterprise software. EJB is a server-side software element that summarizes business logic of an application. Enterprise Java Beans web repository yields a runtime domain for web related software elements including computer reliability, Java Servlet Lifecycle (JSL) management, transaction procedure and other web services. The EJB enumeration is a subset of the Java EE enumeration.
The EJB enumeration was originally developed by IBM in 1997 and later adopted by Sun Microsystems in 1999 and enhanced under the Java Community Process.
The EJB enumeration aims to provide a standard way to implement the server-side business software typically found in enterprise applications. Such machine code addresses the same types of problems, and solutions to these problems are often repeatedly re-implemented by programmers. Enterprise Java Beans is assumed to manage such common concerns as endurance, transactional probity and security in a standard way that leaves programmers free to focus on the particular parts of the enterprise software at hand.
To run EJB application we need an application server (EJB Container) such as Jboss, Glassfish, Weblogic, Websphere etc. It performs:
1. Life cycle management
2. Security
3. Transaction management
4. Object pooling
Types of Enterprise Java Beans
There are three types of EJB:
1. Session Bean: Session bean contains business logic that can be invoked by local, remote or webservice client. There are two types of session beans: (i) Stateful session bean and (ii) Stateless session bean.
- (i) Stateful Session bean :
Stateful session bean performs business task with the help of a state. Stateful session bean can be used to access various method calls by storing the information in an instance variable. Some of the applications require information to be stored across separate method calls. In a shopping site, the items chosen by a customer must be stored as data is an example of stateful session bean.
- (ii) Stateless Session bean :
Stateless session bean implement business logic without having a persistent storage mechanism, such as a state or database and can used shared data. Stateless session bean can be used in situations where information is not required to used across call methods.
2. Message Driven Bean: Like Session Bean, it contains the business logic but it is invoked by passing message.
3. Entity Bean: It summarizes the state that can be remained in the database. It is deprecated. Now, it is replaced with JPA (Java Persistent API). There are two types of entity bean:
- (i) Bean Managed Persistence :
In a bean managed persistence type of entity bean, the programmer has to write the code for database calls. It persists across multiple sessions and multiple clients.
- (ii) Container Managed Persistence :
Container managed persistence are enterprise bean that persists across database. In container managed persistence the container take care of database calls.
When to use Enterprise Java Beans
1.Application needs Remote Access. In other words, it is distributed.
2.Application needs to be scalable. EJB applications supports load balancing, clustering and fail-over.
3.Application needs encapsulated business logic. EJB application is differentiated from demonstration and persistent layer.
Advantages of Enterprise Java Beans
1. EJB repository yields system-level services to enterprise beans, the bean developer can focus on solving business problems. Rather than the bean developer, the EJB repository is responsible for system-level services such as transaction management and security authorization.
2. The beans rather than the clients contain the application’s business logic, the client developer can focus on the presentation of the client. The client developer does not have to code the pattern that execute business rules or access databases. Due to this the clients are thinner which is a benefit that is particularly important for clients that run on small devices.
3. Enterprise Java Beans are portable elements, the application assembler can build new applications from the beans that already exists.
Disadvantages of Enterprise Java Beans
1. Requires application server
2. Requires only java client. For other language client, you need to go for webservice.
3. Complex to understand and develop EJB applications.
Так как я уже затрагивал тему EJB3 в уроках, то решил рассмотреть его более детальней.
Немного о EJB
EJB (Enterprise Java Beans) – это фреймворк для построение бизнес-логики приложения.
Сервер приложений J2EE состоит из двух основных элементов:
WEB-Container – (JSP, JSF и т.д.) все что дает конечный вид пользователю, а точней пользовательский интерфейс.
EJB-Container – используется для написания бизнес-логики.
С точки зрения EJB – это технология, предоставляющая множество готовых решений (управление транзакциями, безопасность, хранение информации и т.п.) для вашего приложения.
EJB делится на три типа компонентов
1. Session beans – используется для построения бизнес-логики, которая может быть вызвана программным клиентом через локальный, удаленный или веб-интерфейс обслуживания клиентов.
Для доступа к приложению, развернутого на сервере, клиент вызывает методы сессионного компонента. Сессионный компонент выполняет работу для своего клиента, защищая его от сложности, выполняя бизнес-задач внутри сервера.
Существует 2 типа session-beans: stateless и stateful.
Stateful – автоматически сохраняют свое состояние между разными клиентскими вызовами.
Stateless – используются для реализации бизнесс-процессов, которые могут быть завершены за одну операцию.
2. Message-Driven beans – компонент является корпоративным компонентом, который позволяет Java EE приложениям обрабатывать сообщения асинхронно.
Этот тип бинов обычно действует в качестве слушателя JMS-сообщения, который похож на слушателя событий, но получает JMS-сообщений вместо событий. Сообщения могут быть отправлены на любой компонент Java EE (клиентское приложение, другой компонент, или веб-компонент) или JMS приложение или систему, которая не использует Java EE технологий.
Message-Driven beans может обрабатывать не только JMS сообщения но и других видов сообщений.
На схеме выше можно наблюдать общение между приложением и сервером с помощью очереди куда поступают сообщения.
3. Entities – это сущности каких то объектов и в EJB оно является хранилищем данных на период жизненного цикла Entity.
Entities является свое-родным отображением таблиц в БД.
Одним из главным достоинством EJB3 стал новый механизм работы с persistence, он дает возможность автоматически сохранять объекты в реляционной БД используя технологию ORM.
Для работы с entity был создан JPA (Java Persistence API).
JPA определяет стандарт для:
1) конфигурации маппинга сущностей приложения и их отображения в таблицах БД;
2) EntityManager API – позволяет выполнять CRUD (create, read, update, delete) операции над сущностями;
3) Java Persistence Query Language (JPQL) – для поиска и получения данных приложения;
Основные аннотации EJB3
@EJB – помечается bean, который мы собираемся использовать.
@Stateless – говорит контейнеру, что класс будет stateless session bean. Для него контейнер обеспечит безопасность потоков и менеджмент транзакций.
@Local – относится к интерфейсу и говорит, что bean реализующий интерфейс доступен локально.
@Remote – относится к интерфейсу и говорит, что bean доступен через RMI (Remote Method Invocation).
@Stateful – говорит контейнеру, что класс будет stateful session bean.
@Remove – метод, помеченный как Remove говорит контейнеру, что после его исполнения нет больше смысла хранить bean, т.е. его состояние сбрасывается. Это бывает критично для производительности.
@Entity – говорит контейнеру, что класс будет сущностью БД.
@Table(name=”<name>”) – указывает таблицу для маппинга БД.
@Id – указывает уникальный идентификатор сущности который будет ключом в БД.
@Column – указывает параметры колонки в БД включая имя колонки в БД.
@WebService – говорит, что интерфейс или класс будет представлять web-сервис.
Правила создания session bean
В качестве session bean может выступать обычный класс Java, но он должен удовлетворять следующим условиям:
1. Он должен иметь как минимум один метод;
2. Он не должен быть абстрактным;
3. Он должен иметь конструктор по-умолчанию;
4. Методы не должны начинаться с “ejb” (например ejbBean, ejbGoAtHome)
5. Свойства класса должны быть объявлены примитивами или реализовывать интерфейс Serializable.
Жизненный цикл EJB3
У stateless и MDB бинов существует 2 события жизненного цикла, которые мы можем перехватить. Это создание и удаление бина.
Метод, который будет вызываться сразу после создании бина помечается аннотацией @PostConstruct, а перед его удалением – @PreDestroy.
Stateful бины обладают помимо рассмотреных выше еще 2 событиями:
1) При активации @PostActivate;
2) При деактивации @PrePassivate.
- None Found
EJB2 против EJB3
EJB (Enterprise JavaBeans) — это Java API (интерфейс прикладного программирования), входящий в спецификацию Java EE (Java Platform, Enterprise Edition). EJB описывает архитектурную модель для разработки корпоративных приложений. Это управляемая серверная модель, способная фиксировать бизнес-логику корпоративного приложения. IBM является первоначальным создателем EJB, который разработал его в 1997 году. Sun Microsystems приняла его в 1999 году.
До появления EJB было обнаружено, что решения проблем, обнаруженных во внутреннем бизнес-коде, часто повторно реализовывались программистами. В результате был представлен EJB для решения таких общих проблем, как постоянство, целостность транзакций и безопасность. EJB предоставляет стандартные способы решения этих внутренних проблем, определяя, как сервер приложений должен обрабатывать транзакции, интегрироваться со службами JPA (Java Persistence API), обрабатывать управление параллелизмом, обрабатывать события JMS (Java Message Service), решать проблемы именования с помощью JNDI ( Java Naming and Directory Interface), разработка безопасных программ с помощью JCE (Java Cryptography Extension) и JAAS (Java Authentication and Authorization Service), развертывание компонентов, удаленная связь с RMI-IIOP (Java Remote Method Invocation interface через Internet Inter-Orb Protocol) , разрабатывать веб-службы, вызывать асинхронные методы и использовать службу таймера.
EJB2
EJB2 (EJB 2.0) был выпущен 22 августа 2001 года. Он описывает спецификацию для разработки распределенных объектно-ориентированных приложений на Java путем объединения инструментов, разработанных различными поставщиками. Одной из основных целей EJB2 было позволить программистам более легко разрабатывать корпоративные приложения без необходимости разбираться в деталях низкого уровня, таких как многопоточность и объединение пулов. Другая цель состояла в том, чтобы позволить программистам один раз написать «компонент» и запустить его где угодно без перекомпиляции (придерживаясь слогана языка программирования Java «напиши один раз, запусти где угодно»). Более того, EJB2 предназначен для того, чтобы позволить компонентам, разработанным разными поставщиками, легко взаимодействовать, и позволить поставщикам писать расширения для своих продуктов, которые могут поддерживать EJB.
EJB3
EJB3 (EJB 3.0) был выпущен 11 мая 2006 года. EJB3 очень облегчил жизнь программистам, позволив им использовать аннотации вместо дескрипторов развертывания, которые использовались в предыдущих версиях. EJB3 содержит бизнес-интерфейс и конкретный объектный компонент, который может реализовать этот бизнес-интерфейс, устраняя необходимость в использовании домашнего / удаленного интерфейсов и файла ejb-jar.xml. Общая производительность EJB3 значительно улучшена по сравнению с EJB2, и в этом выпуске EJB значительно улучшены конфигурируемость, гибкость и переносимость.
В чем разница между EJB2 и EJB3?
EJB3 имеет заметное улучшение конфигурации и производительности по сравнению с EJB2. Одной из причин такого повышения производительности является использование POJO (простой старый объект Java) с метаданными и дескрипторами развертывания XML в EJB3 вместо поиска JNDI, используемого в EJB2 для ссылок на объекты. Конфигурация EJB3 намного проще, поскольку программисту не нужно реализовывать интерфейсы Home / Remote и другие (например, SessionBean), что устраняет необходимость использования методов обратного вызова контейнера (таких как ejbActivate и ejbStore).
Кроме того, EJB3 лучше, чем EJB2, в областях гибкости и переносимости. Например, легко преобразовать сущности EJB3 в DAO (объект доступа к данным) и наоборот, потому что сущности EJB3 легковесны (в отличие от тяжеловесных сущностей EJB2, которые реализуют вышеупомянутые интерфейсы). Запросы к базе данных, написанные на EJB3, очень гибкие, потому что он использует усовершенствованный EJB-QL вместо более старой версии EJB-QL, которая имела несколько ограничений. EJB3 устраняет все проблемы переносимости EJB2 (который использует объектные компоненты для доступа к базе данных), поддерживая более обобщенный JPA для всех транзакций с данными.
В отличие от EJB2, для выполнения которого требуется контейнер EJB, EJB3 может выполняться на независимой JVM (виртуальной машине Java) без необходимости использования контейнеров (это возможно, поскольку он не реализует стандартные интерфейсы). В отличие от EJB2, EJB3 легко подключается к поставщикам сохраняемости, предлагаемым третьими сторонами. Еще одно важное различие между EJB3 и EJB2 заключается в том, что EJB3 может использовать безопасность на основе аннотаций, тогда как EJB2 использует безопасность на основе дескрипторов развертывания. Это означает, что задачи конфигурирования и настройки в EJB3 намного проще, а накладные расходы на производительность значительно снижаются по сравнению с EJB2.
Enterprise JavaBeans (EJB) — это управляемый компонент, принадлежащий
стороне сервера для модульного конструирования промышленного приложения [7].
Итак, начнем наш тур по Enterprise JavaBeans путем исследования
значения этих слов.
«Компонент» — означает, что EJB распространяются
в бинарном формате и могут настраиваться, так что клиентский программист может
использовать их для создания собственного приложения. Эта та же самая концепция,
которую мы видели в графических компонентах JavaBean: вы покупаете компонент
JavaBean для создания части графической круговой диаграммы, вы встраиваете
его в ваше приложение (обычно при использовании RAD инструмента, такого как
JBuilder), вы настраиваете параметры компонента по своему желанию (например,
цвет фона), и вы используете его в вашем приложении, создающем отчеты. У вас
нет исходного кода для компоненты круговой диаграммы, тем не менее, вы можете
подстроить его в соответствии со своими нуждами. Способ, которым вы внедряете,
настраиваете и используете Enterprise JavaBeans, не похож на то, как вы работаете
с обычным JavaBeans, но концепция сущности компонента та же самая. Это важно
для создания терминологического различия между компонентами и экземплярами:
мы используем термин Enterprise JavaBeans для указания типа компонента — например
EJB, представляющий банковский счет; и мы используем термин «экземпляр
EJB» для указания на объект, который представляет специфический банковский
счет с уникальным номером счета.
«Сторона сервера» означает, что объект EJB размещается
в процессе на том же сервере, а не на клиентской машине. EBJ может предлагать
удаленный просмотр, локальный просмотр или оба. Термин «просмотр»
не относится к графическому просмотру; здесь мы говорим о способе, которым
EJB предоставляет свой интерфейс. Если EJB представляет удаленный просмотр,
все вызовы методов между клиентским кодом и удаленным экземпляром происходят
через протокол удаленного вызова процедур, такого как RMI-IIOP. Если EJB представляет
локальный просмотр, клиентский код должен быть в том же процессе, что и EJB
объект, а все вызовы являются прямыми вызовами методов.
Как вы видели в Главе 16, способность выполнять удаленный
вызов процедур подразумевает присутствие двух фундаментальных частей архитектуры:
именованные службы и RPC прокси. Именованные службы — это сетевые службы,
которые клиентский программист использует для нахождения гетерогенных ресурсов
сети. RPC прокси — это программно сгенерированный Java класс, созданный на
клиентской стороне, который представляет тот же самый интерфейс, что и специфичный
удаленный компонент. Так как он предоставляет тот же интерфейс, клиенты не
могут общаться один с другим, а прокси может претендовать на роль удаленного
экземпляра. Но поскольку это прокси, он делегирует все вызовы удаленному компоненту,
реализующему сетевой код и прячущий все сложность от клиента. В EJB мы имеем
аналогичную концепцию именованных служб и RPC прокси, но они слегка отличаются
от того, что мы видели с Java Remote Method Invocation (RMI).
И последнее, и наиболее важное, EJB могут управляться.
Это означает, что когда объект EJB активен в памяти, ведущий его процесс делает
с ним немого больше, чем то, что обычно делает JVM. Процесс, обслуживающий
EJB, вызывается EJB контейнером и является стандартизированной средой времени
выполнения, которая предоставляет управляющую функциональность. Так как спецификация
EJB стандартизирует службы, предоставляемые EJB контейнером, мы имеем поставщика,
реализующего эту функциональность в коммерческих продуктах, таких как WebSphere
и WebLogic, два наиболее известных коммерческих EJB контейнера от IBM и BEA
Systems, соответственно. В EJB контейнере службы, такие как удаленные объекты
и нейтралитет клиентского протокола, неявно используют JAVA RMI; другие службы
(перечисленные ниже) являются стандартными. Такие службы, как кластеризация
и поддержка при поломках, являются дополнительными и предлагаются определенными
поставщиками.
Вот службы, предоставляемые всеми контейнерами EJB:
- Постоянство Объекта
- Декларативный Контроль Безопасности
- Декларативный Контроль Транзакций
- Управление Конкурированием (Параллельностью)
- Управление Масштабированием
Постоянство объекта означает, что вы можете отразить состояние
EJB экземпляра на данные в некотором постоянном хранилище — обычно, но не
обязательно, в реляционной базе данных. Контейнер хранит состояние в постоянном
хранилище, синхронизированным с состоянием EJB экземпляра, даже когда этот
объект используется и модифицируется параллельно несколькими клиентами.
Декларативный Контроль Безопасности дает вам возможность
позволить Контейнеру проверять, что клиент, вызывающий определенный метод
для некоторого EJB, был авторизован и принадлежит к роли, которую вы ожидаете;
если это не так, будет сгенерировано исключение и метод не будет выполнен.
Выгода от декларативного контроля безопасности в том, что вам не нужен код
для любой логики безопасности в вашем EJB — вы просто определяете роли и «говорите»
контейнеру каким ролям позволяется вызывать какие методы. Так как нет жестко
закодированной логики безопасности в вашем EJB, легко произвести изменения
в соответствии с требованиями безопасности без перекомпиляции.
Декларативный Контроль Транзакций это аналогичный механизм:
вы говорите Контейнеру, чтобы он сделал что-то для вашей пользы, но вы предоставляете
информацию о том, что должно происходить в терминах разграничения транзакций,
когда вызывается определенный метод. Например, вы можете проинструктировать
Контейнер начать новую транзакцию, когда вызывается метод, или вы можете проинструктировать
его использовать существующую транзакцию и отклонить вызов метода, если один
из методов еще не активен (транзакция проходит по цепочке вызовов методов).
Контейнер будет автоматически подтверждать транзакцию, когда метод, вызвавший
запуск транзакции, завершиться корректно, или он откатит транзакцию, если
будет перехвачено исключение, выброшенное в то время, когда транзакция была
активна. Опять таки, польза от декларативного управления транзакциями в том,
что нет логики транзакций в исходном коде вашего EJB, так что это не только
упрощает жизнь разработчику, но это также облегчает изменение поведения транзакции
вашего EJB без перекомпиляции.
Если вы вспомните, что EJB являются компонентами, вы поймете,
почему эти две особенности так важны. Возможность осуществлять декларативный
контроль над логикой безопасности и транзакций является фундаментальным требованием
в компонентной модели, потому что это позволяет людям, не имеющим исходного
кода, или не желающим работать на таком уровне, адаптировать компоненты в
приложение, которое строится с помощью этих компонентов.
Управление конкурированием синхронизирует параллельные
вызов методов, приходящие от различных удаленных клиентов, и направляет их
к одному и тому же EJB объекту. На практике, это гарантирует, что компонент
может быть безопасно использован в наследуемой многопоточной среде сервера
приложений (довольно полезное свойство).
Управлению масштабируемостью адресуется проблема увеличения
выделяемых ресурсов, которая возникает при увеличении количества одновременно
работающих клиентов. Ресурсы выделяются для клиента, а не для EJB объектов,
есть такие поддерживаемые ресурсы, как соединения с базой данных, нити (threads),
сокеты, очередь сообщений и так далее. Например, если число одновременно работающих
клиентов увеличивается от 100 до 1000, вы можете получить 1000 EJB объектов
в памяти, которые могут открыть 1000 соединения с базой данных; это может
быть слишком много для количества имеющейся у вас памяти, и это определенно
слишком тяжелая нагрузка на ваш сервер базы данных. EJB Контейнер может решить
заняться этой проблемой, предоставив объединенные (pooling) экземпляры EJB
и объединенные (pooling) соединения с базой данных. Таким образом, Контейнер
будет хранить только ограниченное количество экземпляров или соединений, живущих
в памяти, и будет присваивать им различных клиентов только во время, когда
клиент действительно будет нуждаться в этом.
Красота Enterprise JavaBean
Мы знаем, что EJB суть компоненты. Однако, термин «компонент»
один из наиболее перегруженных в индустрии, и разные люди (и разные поставщики)
имеют разные идеи о том, что такое компонент. Для платформы .NET от Microsoft
компонент является чем-то, что компилируется с (D)COM(+) бинарной спецификацией,
а природа и тип компонента определяется стандартными интерфейсами, которые
он предоставляет. Однако, нет архитектурной модели, предписанной платформой
Microsoft, или это преднамеренно не оговорено. Другими словами, существует
очень мало предписанных архитектурных требований, которые говорят, как разрабатывать
и собирать компоненты для создания промышленного приложения.
Платформа J2EE, с другой стороны, предоставляет вам более
точную архитектуру рабочей среды, в которой вы создаете и используете компоненты.
Это особенно верно для EJB, для которых спецификация определяет три разных
EJB типа, с разными характеристиками отклика и разными областями применения.
Вот эти три EJB типа:
- Entity Beans
- Session Beans
- Message-Driven Beans
Entity beans представляет объекты в том смысле, что Контейнер
прозрачно хранит их состояния синхронно с данными в некотором другом постоянном
хранилище, обычно это реляционная база данных. По этой причине entity beans
используются для представления бизнес-сущностей, таких как клиент, корзина
покупок и так далее. Entity beans не реализуют бизнес-логику, за исключением
самосодержащейся логики напрямую связанной с внутренними данными. Хотя все
entity beans открыты для клиентского кода одинаковым образом, они могут быть
реализованы при использовании двух разных живучих стратегий. Разработчик имеет
два варианты: 1) позволить Контейнеру заботиться о перемещении состояний между
EJB объектом и базой данных, или 2) позаботиться об этом механизме и реализовать
код, который перемещает состояние EJB от и к постоянному хранилищу. В первом
случае мы говорим, что мы применяем Живучесть Управляемая Контейнером [Container
Managed Persistence] (CMP), так что entity beans является CMP bean; во втором
случае мы используем Живучесть Управляемая Компонентом [Bean Managed Persistence]
(BMP), и мы получаем BMP bean. Опять таки, хотя есть существенное практическое
отличие между CMP и BMP в стратегиях реализации, это не влияет на способ использования
клиентом entity bean.
Обсуждения всех хитросплетений при предпочтении CMP перед
BMP выходит за пределы этой главы. Однако важно объяснить, что большинство
полезных свойств CMP не в том, как вы можете подумать, что вам не нужен код
логики самосохранения. Реальная выгода от CMP состоит в том, что компонент
может портироваться под любую систему постоянного хранения. Если вы думали
об этом, CMP работает потому, что Контейнер генерирует весь код, необходимый
для переноса состояния между EJB объектом и постоянным хранилищем. Это означает,
что Контейнер знает, как взаимодействовать с таким специальным хранилищем.
Реализация EJB Контейнера поддерживает различные хранилища, обычно все основные
RDBMS, такие как Oracle, DB2, MySQL и т.п. Так как логика сохранения не закодирована
жестко в CMP entity bean, а она предоставляется Контейнером, вы можете использовать
тот же самый бинарный компонент в разных рабочих средах и все еще пользоваться
поддержкой хранения объекта, предоставляемой Контейнером. Если вы используете
BMP, логика хранения (например SQL выражения, если вы программируете для специфической
RDBMS) будет встроена в ваш компонент, что затруднит использования другого
хранилища.
Таким образом, вы используете CMP для того, чтобы повысить
уровень портируемости; и вы используете BMP, если ваш entity bean связан с
некоторой системой, не поддерживаемой платформой J2EE (например, это CICS
приложение в IBM майнфрейме) или по другим особым причинам, которые мы не
может предположить здесь.
Session beans по сути это другой род. Они не постоянны,
и вместо дискретных компонентов, которые реализуют бизнес-логику, реализуют,
например, шаги, требуемые для проверки и покупки некоторых продуктов в виртуальную
корзину. Session beans могут взаимодействовать с другими session beans, чтобы
получить доступ к дополнительной бизнес-логике, и они используют entity beans,
когда им нужно получить доступ к хранимой информации. Session beans получаются
в двух разных вариантах: session beans не имеющий состояний (Stateless session
beans — SLSB) и session beans поддерживающие состояния (Stateful session beans
— SFSB).
Различия между этими двумя типами в том, что session beans
с поддержкой состояний хранит диалоговую информация во время обмена с клиентом,
в то время, как session beans без поддержки состояний этого не делает. Диалоговая
информация о состоянии — это информация, которая передается от клиента к session
beans при последовательном вызове методов.
Например, вам нужен session beans, реализующий логику резервирования
и покупки билетов в кино по сети. Клиенты должны подключиться и использовать
один из экземпляров такого компонента; экземпляр должен предоставить два метода,
reserveSeats(& ) и purchase(& ). Первый метод принимает количество
мест, которые нужны покупателю для покупки, и резервирует их в системе; второй
метод принимает информацию о кредитной карте покупателя, проверяет сумму на
ней и выполняет процесс покупки. Если Компонент является session beans с поддержкой
состояний, то когда будет вызван метод reserveSeats(& ), экземпляр session
bean «запомнит» количество мест, и вам не нужно будет опять передавать
эту информацию в метода purchase(& ). Если session beans не поддерживает
состояния, Компонент не будет хранить в памяти информацию, переданную в предыдущем
вызове метода, так что клиенту нужно будет передавать ее при каждом вызове
метода. Существует несколько стратегий для реализации и оптимизации передачи
состояний, но состояния все равно должно передаваться при каждом вызове метода.
Причина существования этих двух типов session beans достаточно
проста: неотъемлемой частью некоторых бизнес-процессов является отсутствие
состояний (особенно это относится к тем процессам, которые вплотную привязаны
к HTTP), а для других процессов неотъемлемо наличие состояний; архитектура
призвана отразить это различие.
Есть технический подтекст в использовании одного типа session
bean или другого, но так же, как и в случае сравнения CMP и BMP, детальное
обсуждение выходит за рамки этой главы. Одна вещь, которую вы должны запомнить,
состоит в том, что session bean без состояний ведут себя лучше при работе
с экземпляром механизма пулинга (объединения) Контейнера, по сравнения с session
bean с поддержкой состояний. Так как экземпляр session bean без поддержки
состояний не предназначен для запоминания любой информации о состоянии, передаваемой
клиентом, при завершении работы метода, этот же самый экземпляр может легко
быть переназначен другому клиенту для вызовов других методов. Если экземпляр
session bean поддерживает состояния, Контейнер не может переназначить его
другому клиенту до тех пор, пока он не переместит информацию о состояниях
в какое-то временное хранилище для последующего использования (в EJB этот
процесс называется активация и пассивация). В этом заключено общее непонимание
того, что при объединении (pooling) экземпляров, session beans без состояний
улучшают масштабируемость, но это не при любых условиях. Ваш Контейнер должен
быть очень хорошо оптимизирован относительно механизма активизации и пассивации,
так чтобы перемещение состояния session bean с поддержкой состояний в некоторое
вторичное хранилище и извлечение из него оказывало очень малое воздействие
на производительность. Во-вторых, если вы используете session bean без поддержки
состояний, вы должны передать состояние клиента в session bean при каждом
вызове, и если клиент и session bean находятся на двух различных распределенных
уровнях, то процесс постоянной передачи состояния, а также сериализация и
десериализация параметров метода, как этого требует RMI, может стать критическим
местом.
Интересно замечание относительно объединения (pools) экземпляров.
Дело в том, что ваш Контейнер может их вообще не понимать. Если принять во
внимание недавнюю оптимизацию, введенную в компиляторы Java и JVM, современные
Контейнеры могут решить, что выделение блока памяти и сборка мусора более
эффективное занятие, чем управление объединением.
И наконец, третий тип Enterprise JavaBean: Message-Driven
Beans (MDB). MDB работает в кооперации с системой сообщений JAVA [Java Messaging
System](JMS), которая является абстрактным API для системы Message-Oriented
Middleware (MOM), более-менее похожую на то, как JDBC является абстрактным
API поверх SQL базы данных.
Еще раз, у нас нет места в этой главе для полного описания
системы MOM. Коротко, система MOM предоставляет модель сообщений с публичной
подпиской, основанной на асинхронной, распределенной очереди сообщений. MOM
сообщение суть пакет информации, которое кто-то публикует, а кто-то другой
интересуется им и принимает его. MOM сообщения публикуются в и извлекаются
из очереди или канала. Источник сообщения и подписчик могут находиться в двух
разных процессах, а сообщение посылается в MOM очередь, которая гарантирует,
что оно будет доставлено, даже в случае сбоя системы. MOM система чрезвычайно
полезна для реализации любой формы распределенного, асинхронного процесса
— она чем-то похожа на обработку событий в самостоятельном приложении.
MBD являются приемниками MOM сообщений, приходящих через
JMS API. MDB обычно реализуются для выполнения некоторых действий при получении
сообщений и выступают в роли объектно-ориентированных точек соединения между
подсистемами, взаимодействующих посредством JMS. Например, MDB может реализовать
посылку электронной почты администратору (используя JavaMail API), когда будет
получено сообщение об определенном событии.
Отличие MDB от session beans и entity beans состоит в том,
что они не предоставляют никаких удаленных или локальных представлений. Другими
словами, клиентский код не может получить доступ к MDB, но MDB может использовать
другие EJB и другие службы.
EJB Роли
Тот факт, что EJB является компонентом архитектуры, неявно
означает, что есть различные моменты во времени жизни EJB компонента: разработка,
установка, конфигурация и использование. EJB спецификация доходит вплоть до
определения организации работы и вовлекаются различные роли во время жизни
EJB компонента. Спецификация различает следующие роли:
-
Enterprise Bean Provider. Реализует EJB компонент и оформляет его для
распространения. Знает о прикладной области, но может не знать об операционной
среде, в которой компонент будет использоваться. -
Deployer. Для EJB, развертывание состоит в процессе установки одного или
нескольких EJB компонентов в специфическом EJB Контейнере. Deployer является
экспертом в специфической рабочей среде и отвечает за связывание EJB со
всеми ресурсами, которые ему нужны для работы (соединение с базой данных,
таблицы, другие EJB и тому подобное). -
Application Assembler. Использует различные развернутые компоненты в специфической
среде для создания полного приложения. -
System Administrator. Он отвечает за создание и поддержку пользователей,
баз данных и за общую инфраструктуру ресурсов, необходимых для специфической
рабочей среды.
Важно помнить, что это роли, а не персоны. Для небольшого
проекта одна и та же персона может выступать в любой или во всех ролях сразу.
Для больших проектов, когда компоненты могут разрабатываться другими отделениями
или приходить от третьих сторон, разные персоны могут выступать в разных ролях.
Другая интересная вещь состоит в том, что спецификация
не только определяет ответственность и уровень знания для каждой роли, но
даже определяет, какие исходные файлы предназначены для какой роли.
Аналогично, EJB спецификация принуждает, чтобы отдельный
кусок не стандартной конфигурационной информации был определен в отдельном
исходном файле. Это необходимо потому, что различные реализации EJB Контейнера
могут предоставлять различные возможности, которые обычно конфигурируются
человеком посредством XML файлов. Если определенная особенность специфична
для одного Контейнера, она будет определена в файлах, специфичных для Контейнера.
Основное API
EJB API — это не только платформа Java2 Enterprise Edition.
Это горадно больше: Java Transaction API (JTA), Java Messaging System API
(JMS), Сервлеты, JavaServer Pages (JSP) и Java Database Connectivity (JDBC)
вот несколько названий. Прежде чем мы приступим к рассмотрению реализации
и использованию EJB, нам необходимо коротко рассмотреть пару фундаментальных
API: Java Naming and Directory Interface (JNDI) и актуальный EJB API.
JNDI
JNDI — это абстрактный API над различными службами именования,
такими как RMI Naming Service или COS Naming Service в CORBA, или служба директорий
аналогичная Lightweight Directory Access Protocol (LDAP). Служба имен и служба
каталогов концептуально это не одно и то же, но, как я уже говорил ранее,
здесь не место для обсуждения различий. То, что мы сделаем — это просто взглянем
на то, что в них общего.
Все службы именования и директорий позволяют вам заполнять
и искать репозитории некоторого рода. Более подробно, они позволяют вам ассоциировать
(или связывает, если хотите) имя с объектом, а затем искать этот объект (или
рассматривать его), используя это имя. По аналогии, он может использоваться
как директорий белых страниц, когда физический телефон, на который вы хотите
перевести звонки (уникально идентифицируемый номером), ассоциируется с именем
клиента. В качестве более приближенного к Java примера можно привести RMI:
вы можете зарегистрировать объект с именем (строка) в RMI Naming Service,
так что другие приложения могут производить поиск этого имени в службе. Это
в точности совпадает с тем, что вы можете делать с COS Naming Service. Таким
образом, почему JNDI является достаточно удобной абстракцией: он предоставляет
вам однообразный интерфейс к различным службам именования и директорий, точно
так же, как вы используете JDBC для доступа к различным базам данных.
Как и JDBC, JNDI является абстрактным API, и вы можете
найти в JNDI пакете javax.naming только Java интерфейсы. Действительная реализация
этих интерфейсов должна быть предоставлена некоторым поставщиком, который
хочет предоставить поддержку JNDI для своей службы. Для действительного использования
этой службы вам необходим Поставщик Услуг (Service Provider) JNDI — точно
так же, как вам необходим соответствующий JDBC драйвер для доступа к определенной
базе данных.
JDK1.4 поставляется с четырьмя стандартными Поставщиками
Служб JNDI, которые предоставляют доступ к RMI, DNS, COS Naming Service и
LDAP. Существует также дополнительный Поставщик Службы JNDI, который вы можете
получить с вебсайта Sun, который предоставляет JNDI просмотр вашей локальной
файловой системы (так что вы можете искать файлы и директории, используя JNDI).
JNDI поддерживает концепцию пространства имен, которое
является логическим пространством, в котором могут определяться имена. Два
одинаковых имени, определенных в разных пространствах имен не будут являться
причиной неоднозначности или коллизии имен, а пространства имен могут быть
вложенные. Эту концепцию вы можете видеть в нескольких различных ситуациях
— ваша локальная файловая система использует вложенное пространство имен (директории),
DNS Интернета использует вложенное пространство имен (домены и субдомены).
В JNDI пространство имен представлено интерфейсом Context,
наиболее часто используемым элементом API. Существуют разные классы, реализующие
интерфейс Context, в зависимости от реальной службы, к которой вы обращаетесь
посредством JNDI. Интерфейс Context имеет методы для связывания имени и объекта,
для удаления связывания, для переименования, для создания и удаления подконтекста,
для поиска имен, для получения списка имен и так далее. Вы также должны заметить
что, так как контекст в Java является объектом, он может быть зарегистрирован
в другом контексте под своим собственным именем. Другими словами, мы можем
получить вложенный субконтекст, начав с родительского контекста, и создав
связывание между именем субконтекста и вложенным объектом Context.
Другая фундаментальная концепция в JNDI API состоит в том,
что независимо от реально используемой вами службы, для того, чтобы получить
возможность создать связывание, выполнить поиск и тому подобное, вам нужно
начать с некоторого «корневого» контекста. Класс InitialContext
— это то, что вы используете, чтобы получить экземпляр Контекста, которые
представляет родителя всех субконтекстов, к которым вы можете получить доступ.
Хотя определенные операции в JNDI применимы только к определенному
Поставщику Службы, концепция распространяется так далеко, что становится общей
и широко применимой. Рассмотрим пример. Приведенный ниже код показывает, как
получить список всех имен, зарегистрированных в корне используемой вами службы.
Обратите внимание, что конструктор InitialContext получает в качестве аргумента
тип Property. Я объясню это немного позже. Сейчас же просто взглянем на приведенный
ниже код.
Context context =
new
InitialContext
(
props
)
;
Enumeration names = context.list
(
""
)
;
while
(
names.hasMoreElements
())
System.out.println
(
names.nextElement
())
;
Вы видите, что это достаточно просто. Мы создаем объект Context, который представляет
корень вашей службы именования или директории, получаете перечисление всех
элементов этого контекста (пустая строка в вызове метода list( ) означает,
что вы не ищете определенное имя), затем перебираете и печатаете все элементы
из перечисления.
Абстракция и модель программирования достаточно проста.
Нас должен волновать вопрос: какую службу именования или директорий мы используем?
Ответ содержится в контейнере параметров, который мы передаем в конструктор
InitialContext( ). JNDI API полностью определяет несколько стандартных имен
параметров (декларированных, как константные Строки и интерфейсе Context),
а значения этих параметров определяют природу службы, которую вы будете использовать.
Из этих параметров два являются фундаментальными: INITIAL_CONTEXT_FACTORY
и PROVIDER_URL. Первая из них указывает класс, который будет производить экземпляр
JNDI Context. Если вам нужен DNS, например, вы будете указывать класс, который
производит Context, способный взаимодействовать с DNS сервером. Второй параметр
— это расположение службы, следовательно, это URL. Формат этого URL зависит
от определенной службы.
Ниже приведен законченный пример, который использует JNDI
для просмотра содержимого корня контекста в DNS сервере (возможно, вам понадобиться
использовать другие IP адреса для вашего DNS, в зависимости от конфигурации
вашей сети).
//: c18:jndi:SimpleJNDI.java
import
javax.naming.*;
import
java.util.*;
public class
SimpleJNDI
{
public static
void
main
(
String
[]
args
)
throws
Exception
{
Properties props =
new
Properties
()
;
props.put
(
Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.dns.DnsContextFactory"
)
;
props.put
(
Context.PROVIDER_URL,
"dns://207.155.183.72"
)
;
Context context =
new
InitialContext
(
props
)
;
Enumeration names = context.list
(
""
)
;
while
(
names.hasMoreElements
())
System.out.println
(
names.nextElement
())
;
}
}
// /:~
Если вы хотите использовать другой DNS или полностью отличный тип службы,
в большинстве случаев вы должны просто поместить отличную информацию в контейнер
параметров, а оставшийся код останется без изменения.
Существует другой способ предоставления значений параметров
JNDI. Вы можете использовать внешний файл параметров, который является текстовым
файлом, который ассоциирует названия параметров с их значениями. Этот файл
должен называться jndi.properties, и он должен быть расположен в CLASSPATH
вашего JNDI приложения. Отличие состоит в том, что вы не можете использовать
константы названия параметров, определенных в интерфейсе Context, а вместо
этого вы должны использовать их «строковые» значения (которые вы
можете найти в стандартной документации по JDK). Содержимое нашего файла jndi.properties
будет следующим:
java.naming.factory.initial=com.sun.jndi.dns.DnsContextFactory
java.naming.provider.url=dns:
//207.155.183.72
Если вы выберете этот подход, вам больше ненужно будет передавать контейнер
параметров в конструктор InitialContext. Другими словами, то, что вы поместите
в файл jndi.properties, то вы и установите для JNDI в качестве значений по
умолчанию.
Последнее, и наиболее важное, что я хотел бы рассказать
о JNDI, это как ищутся имена. Как я упоминал, существует метод lookup( ) в
интерфейсе Context. В следующем примере мы предполагаем, что существует внешний
файл jndi.properties, в котором определено, какую службу мы просматриваем.
//: c18:jndi:SimpleJNDI2.java
import
javax.naming.*;
public class
SimpleJNDI2
{
public static
void
main
(
String
[]
args
)
throws
Exception
{
System.out.println
(
new
InitialContext
()
.lookup
(
args
[
0
]))
;
}
}
// /:~
Мы создали новый InitialContext и вызвали метод lookup( ) для него, передав
Строку в качестве аргумента имени. Так как метод lookup( ) предназначен для
работы с различными службами, он возвращает общий класс Object. Однако, реальный
тип времени выполнения, возвращаемый из lookup( ) определяется специфичной
службой, которую вы используете. Ради этого примера мы игнорируем тип и просто
печатаем результат.
В программировании EJB мы используем JNDI для нахождения
всех видов ресурсов, включая EJB, пул соединений с базой данных, информацию
об окружении и многое другое. Другими словами, из окна EJB Контейнера вы можете
взглянуть на остальной мир посредством JNDI. Клиентское приложение тоже использует
JNDI для получения соединения с фабрикой EJB (подробнее об этом позже).
Таким образом, если мы используем JNDI с EJB, что такое
Поставщик Услуг JNDI? Ответ состоит в том, что EJB Контейнер работает и выставляет
свою собственную службу JNDI, специализированную для работы с ресурсами, управляемыми
Контейнером. Другими словами, эта служба EJB JNDI предназначена, чтобы позволить
клиентам и Enterprise JavaBean’ам находить ресурсы по JNDI именам. Помните,
когда вы запускаете ваш EJB Контейнер, вы также неявно запускаете EJB JNDI
службу, которая доступна вам через стандартный JNDI API.
EJB
Другой API, на который нам нужно взглянуть, это сам EJB
API. Он определен в пакете javax.ejb, который, что само по себе интересно,
состоит только из интерфейсов и нескольких классов исключений.
Приведенная ниже диаграмма показывает главные интерфейсы
пакета. Три из них представляют разные EJB типы: EntityBean, SessionBean и
MessageDrivenBean. В зависимости от того, EJB какого типа вы кодируете, ваш
класс должен реализовывать один из этих интерфейсов. Существуют также интерфейсы
EJBHome и EJBObject, который вы используете как базовый интерфейс, когда определяете
собственное представление компонента (если оно вам нужно) — по этой причине
EJBHome и EJBObject наследуются от интерфейса Remote RMI. Оставшиеся два интерфейса,
EJBLocalHome и EJBLocalObject, вы используете для предоставления локального
представления вашего компонента (опять таки, предполагается, что вам нужно
это локальное представление). В следующем разделе мы увидим, как реальный
код использует эти интерфейсы. До этого момента просто держите в уме этот
дизайн.
Другой набор элементов, который нужен нам для короткого
обзора, это классы исключений. Вы можете видеть на приведенной ниже диаграмме
наиболее часто встречающиеся исключения (их существует немного больше в пакете,
пожалуйста, обратитесь к документации по JDK за более детальной информацией).
Как вы можете видеть, есть две главных категории: исключения,
наследуемые от java.lang.Exception напрямую, и другие исключения, наследуемые
от java.lang.RuntimeException. Или, в терминах Java, проверяемые и не проверяемые
исключения, соответственно.
В EJB все проверяемые исключения относятся к исключениям
уровня приложения. Таким образом, они разбросаны по разным уровням распределенного
приложения, и когда они генерятся EJB, они пересекают сеть распределенных
уровней и передаются удаленному клиенту.
Фактически, использование проверяемых исключений EJB указано
в определениях EJB интерфейсов, используемых клиентом, что предопределяется
спецификацией. Например, CreateException должно быть указано в спецификации
метода, который клиент использует для создания экземпляра EJB. Аналогично,
FinderException должно быть указано в спецификации метода, который клиент
использует для нахождения существующего, постоянного объекта EJB. А RemoveException
должно указываться в спецификации метода, который удаляет EJB объект.
Не проверяемые исключения используются во внутренней реализации
EJB. Другими словами, если какая-то попытка вашего EJB провалилась, вы выбрасываете
EJBException или какое-либо наследуемое от него исключение. Причина, по которой
EJBException не проверяется состоит в том, что в большинстве случаев они представляют
некоторые ошибки, которые приходят из одной подсистемы в другую внутри EJB
Контейнера. Даже если вы попытаетесь перехватить эти исключения, вы не сможете
сделать это, так как EJB существует только внутри EJB Контейнера, который
управляет экземплярами и заботится обо всем, что с ними происходит. Вот пример:
у вас есть реализация EJB, который обращается к базе данных и в определенный
момент база данных генерирует SQLException. Бессмысленно возвращать это исключение
удаленному клиенту, поскольку клиент не может знать, что делать с ним. С другой
стороны, вы можете захотеть прервать текущую операцию и известить Контейнер,
что что-то пошло не так, таким образом должна существовать какое-либо корректное
действие, подобное откату текущей транзакции.
Вы не можете просто позволить SQLException’у остаться в
Контейнере, поскольку Контейнер имеет общий способ получения исключений уровня
системы — так что он может постоянно принимать исключения от различных, даже
будущих, подсистем. Что вы должны сделать — это обернуть проверяемое SQLException
в не проверяемое EJBException, используя конструктор, который принимает java.lang.Exception,
а затем вы выбросите EJBException.
Все исключения, которые поступают наружу из вашего EJB
объекта, перехватываются Контейнером. Действия, предпринимаемые в этом случае
Контейнером, могут сильно зависеть от условий, но в общем Контейнер автоматически
откатит текущую транзакцию (если она есть) и передаст исключение клиенту.
Если исключение, сгенерированое внутри вашего EJB, было типа EJBException,
клиент получит общее RMI RemoteException, что проинформирует его, что метод
окончился неудачей. Если исключение, сгенерированое в EJB, было исключением
уровня приложения, таким как FinderException, Контейнер передаст это исключение
клиенту.
EJB Контейнер изнутри
Вы знаете, что EJB — это управляемые компоненты, и теперь
пришло время более пристально взглянуть на то, как контейнер управляет вашими
EJB объектами. Это позволит нам лучше понимать службы, которые предоставляет
Контейнер, примеры кода и процесс разработки.
Основная идея достаточно проста. Когда бы клиентское приложение
ни запросило ссылку на EJB объект, Контейнер реально возвращает ссылку на
сгенерированный Контейнером прокси, который принимает все клиентские запросы,
выполняет некоторые вспомогательные действия и, в конечном итоге, делегирует
их объекту, реализованному BeanProvider’ом. Мы вызываем формирователь EJB
Объекта, а затем EJB Экземпляра. Пожалуйста, не путайте их: EJB Объект генерируется
Контейнером, в то время как EJB экземпляр реализуется Bean Provider’ом.
Вы также должны заметить, что наличие и роли EJB Объекта
являются стандартом EJB спецификации. Также обратите внимание на то, что стратегия
реализации и способ взаимодействия с экземпляром EJB специфичны для контейнера.
И наконец, сгенерированный контейнером прокси (EJB Объект)
не нужно путать с RMI прокси, который также представлен. Приведенная ниже
диаграмма разъясняет эту архитектуру.
Диаграмма показывает архитектурное позиционирование EJB
объекта относительно других главных составных частей. На диаграмме я показал
случай удаленного клиентского приложения, но вы должны держать в уме, что
всегда существует перехватывающий EJB объект, даже когда вызов метода приходит
из кода в этом же контейнере (например, другого EJB).
RMI прокси и заглушка (stub), с одной стороны, присутствуют
только когда клиент обращается к удаленному представлению EJB компонента.
Пожалуйста, обратите внимание, что RMI прокси и заглушка автоматически герерируются
Контейнером, хотя различные Контейнеры выполняют это действие, применяя разные
стратегии.
Пунктирная стрелка представляет зависимости, и она означает,
что если, например, реализация Экземпляра EJB изменится, EJB Объект также
должен быть изменен, поскольку он полагается на специфическую реализацию метода
для этого Экземпляра EJB.
Тот факт, что Экземпляр EJB никогда не доступен напрямую,
является основным механизмом, которым Контейнер управляет экземплярами вашего
компонента. На языке EJB мы говорим, что Контейнер вставляет код между клиентом
(если он присутствует) и EJB Экземпляром, а мы вызываем EJB Объект — артефакт
Контейнера. Вставленный Контейнером код представляет EJB экземпляр с промежуточными
службами, такими как объединение экземпляров, управление распараллеливанием,
управления транзакциями и постоянством объектов.
Таким образом, с ваших плеч снимается огромная ноша — представьте
себе сколько кода вам было бы необходимо написать для реализации некоторых
или всех этих служб самостоятельно. Но так как у вас есть EJB Контейнер, вы
можете просто сказать ему, что ему нужно делать для вашей пользы — например,
запустить новую транзакцию, когда вызывается определенный метод.
В EJB мы называем декларативное управление транзакциями
и логику безопасности метапрограммированием. Идея состоит в том, что вы, фактически,
программируете свой компонент или приложение, но часть поведения вы не кодируете
самостоятельно — вы просто сообщаете Контейнеру что нужно делать.
Теперь вы знаете весь архитектурный фон, который вам нужен
для начала рассмотрения того, как мы реализуем и используем Enterprise JavaBean.
Я дам вам более подробную информацию об EJB Объектах и внутренних способах
работы Контейнера тогда, когда мы будем рассматривать примеры кода.
Программное обеспечение
Прежде, чем мы начнем рассматривать код, позвольте коротко
упомянуть программное обеспечение, которое нужно нам для запуска примеров.
Весь код примеров прилагается к этой книге. Я рекомендую
вам использовать этот код и собирать прилагающиеся скрипты, так как процесс
сборки включает в себя несколько шагов и множество исходных файлов.
Все EJB примеры из этой главы были проверены на сервере
приложений JBoss 3.0.3 (JBoss — это лидирующий EJB Контейнер с открытыми исходниками,
и он может быть загружен с http://www.jboss.org).
Хотя я использовал JBoss, и более специфичную версию, которая поставляется
со встроенным Контенером Tomcat Сервера, количество информации, специфичной
для JBoss, в этой главе и в примерах сведено к минимуму, так что перенесение
этих примеров на другие Контейнеры должно потребовать очень небольшие изменения
кода или вообще не потребуют их. Однако, пожалуйста, обратите внимание, что
если вы используете отличную от JBoss версию, вам может понадобиться изменить
соответствующие скрипты построения Ant.
Другие программные продукты, которые вам понадобятся: Java
SDK1.4 или более позднюю версию; Ant и JUnit (которые вероятно уже установлены
у вас, если вы запускали другие примеры из этой книги); и XDoclet, другая
утилита с открытыми исходниками, которая поможет нам в разработке ваших EJB.
Инструкция по установке, которую вы найдете в директории
кода c18, предоставит вам все дополнительные детали.
Пример приложения
Все примеры этой главы следуют общей теме, иллюстрирующей
концепцию. Мы построим простое приложение, называющуюся JavaTheater, для продажи
и покупки билетов в кино. Приложение будет строится инкрементально, пример
за примером, и мы будет иметь дело с адресами кинотеатров, шоу, билетами,
покупателями, кредитными картами и так далее. У меня нет места, чтобы показать
вам, как создавать полновесное законченное приложение, так что я сфокусируюсь
на ядре функциональности.
Здесь будут классы, которые представляют постоянные сущности,
такие как фильмы и шоу, и другие классы, которые реализуют большую часть логики
приложения. Например, шаги, требующие реальной покупки одного или нескольких
билетов на определенное шоу.
Прежде чем посмотрим на реальный код, я хочу упомянуть
некоторые вещи относительно структуры исходных текстов. Все примеры находятся
в директории c18 исходного кода для этой книги. Каждый поддиректорий является
отдельным, самодостаточным примером, который собирается в корне поддиректория.
На верхнем уровне директории каждого примера есть Ant скрипт для сборки. На
этом же уровне есть директорий src, который содержит все файлы исходного кода
для этого примера. Директорий src содержит поддиректории ejb-tier и rmiclient,
в которых содержится код для реализации EJB и для клиентского приложения (включая
JUnit тест), соответственно. Также, обратите внимание, когда вы будете собирать
пример, что Ant скрипт будет создавать рабочий директорий для компиляции и
сборки (смотрите комментарии в скрипте Ant более подробно), но ничего не создает
и не изменяет в src директории. И, наконец, все наши классы определены в пакете
javatheater, содержащем вложенные пакеты, которые тоже стоит упомянуть: javatheater.client
содержит клиентское приложение; javatheater.test содержит классы JUnit тест;
javatheater.ejb содержит наши EJB интерфейсы и связанные классы, а javatheater.ejb.implementation
содержит классы реализации EJB.
Наш первый пример, example01, не использует никакую EJB
функциональность. Это обычное и простое Java приложение, которое мы использует
в качестве прототипа фундаментального класса. Наипростейший класс — это Movie,
и вы можете видеть его реализацию ниже:
//: c18:example01:src:javatheater:Movie.java
//
package
javatheater;
public class
Movie
{
int
id;
String title;
public
Movie
(
int
id, String title
) {
this
.id = id;
this
.title = title;
}
public
int
getId
() {
return
id;
}
public
void
setId
(
int
id
) {
this
.id = id;
}
public
String getTitle
() {
return
title;
}
public
void
setTitle
(
String title
) {
this
.title = title;
}
public
String toString
() {
return
"["
+ id +
"] "
+ title;
}
}
// /:~
Здесь определен класс Movie, который содержит два поля: id (типа int) и title
(типа String). Класс также определяет конструктор плюс сеттеры и геттеры (setters
и getters) для доступа к значениям полей. Конечно, более реалистичный объект
фильма должен содержать много больше информации, такой как актеры, директор,
рейтинг, краткий обзор; но реализация всего этого добавит ненужную сложность
в пример.
Другой класс — это Show, который также достаточно прост:
у него есть id (типа int), время начала показа time (строка) и количество
мест (типа int). Он также содержит ссылку на объект Movie, что означает, что
у нас есть однонаправленное отношение многие к одному между показами и фильмами:
фильм может быть связан с многими показами, но на одном показе может быть
только один фильм. Вот реализация класса Show:
//: c18:example01:src:javatheater:Show.java
//
package
javatheater;
public class
Show
{
int
id;
Movie movie;
String showtime;
int
availableSeats;
public
Show
(
int
id, Movie movie, String showtime,
int
availableSeats
) {
this
.id = id;
this
.movie = movie;
this
.showtime = showtime;
this
.availableSeats = availableSeats;
}
public
int
getId
() {
return
id;
}
public
void
setId
(
int
id
) {
this
.id = id;
}
public
Movie getMovie
() {
return
movie;
}
public
void
setMovie
(
Movie movie
) {
this
.movie = movie;
}
public
String getShowtime
() {
return
showtime;
}
public
void
setShowtime
(
String showtime
) {
this
.showtime = showtime;
}
public
int
getAvailableSeats
() {
return
availableSeats;
}
public
void
setAvailableSeats
(
int
availableSeats
) {
this
.availableSeats = availableSeats;
}
public
String toString
() {
return
"["
+ id +
"] "
+ movie +
", "
+ showtime +
", "
+ availableSeats;
}
}
// /:~
Так как example01 это простейшее Java приложение, оно не употребляет многие
службы, предоставляемые архитектурой EJB. Определенно, мы не имеет поддержки
постоянства. Я не использовал JDBC для хранения и получения объектов из базы
данных (что должно означать отображения объект/отношения, нечто более сложное
для нашего первого примера), также в примере есть класс, называемый Storage,
который эмулирует наличие постоянного хранилища данных.
//: c18:example01:src:javatheater:Storage.java
//
package
javatheater;
public class
Storage
{
private static
Storage ourInstance;
private
Movie
[]
movies;
private
Show
[]
shows;
public synchronized static
Storage getInstance
() {
if
(
ourInstance ==
null
) {
ourInstance =
new
Storage
()
;
}
return
ourInstance;
}
private
Storage
() {
movies =
new
Movie
[] {
new
Movie
(
1
,
"Return of the JNDI"
)
,
new
Movie
(
2
,
"A Bug's Life"
)
,
new
Movie
(
3
,
"Fatal Exception"
)
,
new
Movie
(
4
,
"Silence of the LANs"
)
,
new
Movie
(
5
,
"Object of my Affection"
) }
;
shows =
new
Show
[] {
new
Show
(
1
, movies
[
0
]
,
"5:30pm"
,
100
)
,
new
Show
(
2
, movies
[
0
]
,
"7:00pm"
,
300
)
,
new
Show
(
3
, movies
[
1
]
,
"6:00pm"
,
200
)
,
new
Show
(
4
, movies
[
4
]
,
"9:00pm"
,
200
) }
;
}
public synchronized
Movie findMovieById
(
int
id
) {
for
(
int
i =
0
; i < movies.length; i++
) {
Movie movie = movies
[
i
]
;
if
(
movie.id == id
)
return
movie;
}
return null
;
}
public synchronized
Movie findMovieByTitle
(
String title
) {
for
(
int
i =
0
; i < movies.length; i++
) {
Movie movie = movies
[
i
]
;
if
(
movie.title == title
)
return
movie;
}
return null
;
}
public synchronized
Movie
[]
findAllMovies
() {
return
movies;
}
public synchronized
Show findShowById
(
int
id
) {
for
(
int
i =
0
; i < shows.length; i++
) {
Show show = shows
[
i
]
;
if
(
show.id == id
)
return
show;
}
return null
;
}
public synchronized
Show findShowByMovie
(
Movie movie
) {
for
(
int
i =
0
; i < shows.length; i++
) {
Show show = shows
[
i
]
;
if
(
show.movie.id == movie.id
)
return
show;
}
return null
;
}
public synchronized
Show
[]
findAllShows
() {
return
shows;
}
}
// /:~
Этот класс реализует дизайнерский шаблон Синглетона (при котором существует
только одно хранилище данных в вашей системе). Его приватный конструктор заполняет
фиктивную базу данных с фильмами по Java тематике и показами. Он также предоставляет
публичный метод для получения фильмов и показов из фиктивной базы данных по
разным критериям. В нем нет методов для обновления нашей фальшивой базы данных,
но вы вольны добавить их в качестве упражнения, если чувствуете в этом необходимость.
Последний класс в example01 — это наш главный клас, ShowListing,
который просто использует хранилище для нахождения группы показов, и распечатывает
их.
//: c18:example01:src:javatheater:ShowListing.java
//
package
javatheater;
public class
ShowListing
{
static
Storage storage = Storage.getInstance
()
;
public static
void
main
(
String
[]
args
) {
Show
[]
shows = storage.findAllShows
()
;
for
(
int
i =
0
; i < shows.length; i++
) {
Show show = shows
[
i
]
;
System.out.println
(
show
)
;
}
}
}
// /:~
Повторюсь, этот пример умышленно упрощен, но он вводит несколько фундаментальных
концепций, которые мы применим при использовании EJB архитектуры: постоянство
объектов, разделение сущностных классов он логики бизнес классов и связи между
объектами. Плюс к этому, пример подал нам идею того, чем будет приложение,
чтобы охватить все вопросы.
← |
Произвольные тэги |
Ваш первый Enterprise JavaBean |
→ |