Главная » Java, JavaBeans » Поддержка EJB1.0

0

Генерация Дескриптора Поставки

Класс GenerateDescriptors генерирует Дескриптор Поставки EJB 1.0. Дескрипторы Поставки – это объекты языка Java, свойства которых описывают, как нужно поставить (deploy) конкретную программу, написанную на Java. Например, свойство может описывать, как нужно запустить программу на выполнение или как зарегистрировать ее имя в службе имен (naming service). В EJB 1.0 Дескриптор Поставки хранится в файле в сериализованном виде. Процесс построения приложения включает в себя помещение файла, содержащего сериализованный Дескриптор Поставки, в jar-файл.

Этот класс создает выходной файл, устанавливает свойства Дескриптора, а затем выполняет его запись в файл как стандартную процедуру сериализации Java. Давайте сначала ознакомимся с функцией main () этого класса (Пример Кода 11.1). Функция создает файл с именем cart.ser, для работы с которым создается объект типа "поток вывода". Для вывода класса Java в поток используется стандартный класс ObjectOutputStream. Затем происходит обращение к методу createDescriptor (), который создает Дескриптор Поставки и записывает его в файл cart.ser. См. Пример Кода 11.2.

Пример Кода В. 1 Функция main() класса GenerateDescriptors

public static void main(String[] args) throws Exception { ObjectOutputStream objectOutput =

new ObjectOutputStream(new FileOutputStream("cart.ser")); objectOutput.writeObject(createDescriptor());

}

При создании Дескриптора Поставки метод createDescriptor () инициализирует session-Дескриптор (так как CartBean является Session-

Компонентом; для Entity-Компонента была бы выполнена инициализация entity-Дескриптора) и устанавливает следующие его свойства:

•          CartBean как имя класса реализации Компонента.

•          CartHome как имя home-интерфейса.

•          Cart как имя remote-интерфейса.

•          Cart как JNDI-имя. JNDI не использует строки в качестве имен. Он использует так называемые "naming names" Java. Простейшим способом преобразования строки в naming name Java является создание объекта типа javax.naming.CompositeName, что и сделано в нашем примере.

•          STATEFUL_SESSION как тип состояния Компонента CartBean. Это выполняется с помощью вызова функции setStateManagementType (). (Для stateless Session-Компонента использовалось бы значение STATELESS_SESSION). Это также устанавливает режим транзакций для Компонента EJB.

•          Атрибуты транзакций. С CartBean сопоставлен атрибут TX_NOT_SUPPORTED. Метод purchase () получает атрибут TX_REQUIRES.

•          0 как величину тайм-аута сеанса связи. Эта величина является настраиваемым значением, которая влияет на цикл жизни Компонента. Существуют два фактора, которые управляют циклом жизни Session-Компонента:

•          Явные команды клиента. Как правило, клиент создает Компонент, использует его, а затем уничтожает.

•          Величина тайм-аута, если она задана. Если она задана, то Контейнер может самостоятельно уничтожить Компонент, если в течение определенного периода времени клиент к нему не обращался. В нашем примере величина тайм-аута в Дескрипторе Поставки установлена равной 0. Нулевое значение означает, что интервал тайм-аута не установлен и Контейнер не удалит объект, если клиент забыл это сделать. Если же установить величину тайм-аута равной 100, то если в течение 100 секунд клиент не будет обращаться к Компоненту, Контейнер его уничтожит.

Пример Кода В.2 Установка свойств Дескриптора

public class GenerateDescriptors {

static DeploymentDescriptor createDescriptor() throws Exception { SessionDescriptor d = new SessionDescriptor(); d.setEnterpriseBeanClassName("CartBean"); d.setHomelnterfaceClassName("CartHome"); d.setRemotelnterfaceClassName("Cart");

d.setBeanHomeName(new javax.naming.CompositeName("cart")); d. setSessionTimeout(0);

d.setStateManagementType(d.STATEFUL_SESSION); { // set the default control descriptor

ControlDescriptor defaultControl = new ControlDescriptor(null); DefaultControl.setTransactionAttribute

(ControlDescriptor.TX_NOT_SUPPORTED); // set the transaction mode on purchase to TX REQUIRES ControlDescriptor purchaseControl =

new ControlDescriptor(CartBean.class.getMethod("purchase", null));

purchaseControl.setTransactionAttribute

(ControlDescriptor.TX_REQUIRED); ControlDescriptor[] controls = { defaultControl,

purchaseControl }; d.setControlDescriptors(controls);

}

return d;

}

Спецификация EJB 1.1 требует, чтобы Дескриптор Поставки имел XML- формат. Дескриптор Поставки соответствует Document Type Definition (DTD), разработанному фирмой Sun Microsystems. Дескриптор Поставки содержит набор свойств, который описывает, как Контейнер будет выполнять процесс поставки Компонента или приложения.

Дескриптор Поставки включает набор тегов и атрибутов, чьи значения определяют состояние свойств Компонента. В качестве примера приведем несколько тегов для приложения cart:

•        <session> – говорит о том, что Компонент является session- Компонентом (тег <entity> используется для обозначения Entity- Компонентов) .

•        Внутри области тега <session> могут использоваться другие теги:

•        <ejb-class> – имя класса реализации.

•        <home> – имя home-интерфейса.

•        <remote> – имя remote-интерфейса.

•     <session-type> – показывает, является ли session-Компонент stateful- или stateless-Компонентом.

•     <transaction-type> – показывает, используется ли для Компонента СМР или BMP.

•        <trans-attribute> – задает значение атрибутов транзакции для каждого метода.

•   как обращаться к методам, объявленным для объекта Cart.

На рисунке 6.3 приведены наиболее интересные и важные фрагменты кода функции main () программы CartClient. Показаны только ключевые фрагменты кода. Цифры, приведенные слева от кода, обозначают номера шагов в описании, приведенном после рисунка. (Если вы хотите получить полный листинг программы, то вы можете найти его в каталоге примеров cart, который создается в процессе инсталляции).

В процессе существования Компонент может находиться в трех различных состояниях:

•                 Nonexistent. Экземпляр Entity-Компонента не существует.

•                 Pooled. Экземпляр Entity-Компонента существует, но не сопоставлен ни с какими конкретными данными (говорят, что он не имеет identity).

•     Ready. Экземпляр Entity-Компонента сопоставлен с конкретными данными.

На рисунке 7.1 изображен цикл жизни Entity-Компонента. Каждый Компонент должен наследовать интерфейс javax.ejb.EntityBean. Контейнер EJB использует методы этого интерфейса для уведомления экземпляра Компонента о происходящих событиях. См. раздел "Класс Entity-Компонента" на странице 7-7 для получения дополнительной информации. Методы, приведенные на диаграмме цикла жизни, объявлены в интерфейсе EntityBean.

•     Контейнер деактивизирует экземпляр Entity-Компонента с помощью вызова метода ejbPassivate (). Он использует этот метод, чтобы отделить этот экземпляр от данных без удаления Entity-объекта, то есть собственно этих данных. Обычно Контейнер выполняет деактивизацию при завершении транзакции. Тем не менее, он может выполнить деактивизацию даже тогда, когда экземпляр Компонента сопоставлен с транзакцией; в этом случае он сначала вызывает метод ejbStore(), чтобы экземпляр мог синхронизировать свое состояние с состоянием базы данных. Когда позднее происходит активизация экземпляра, Контейнер автоматически вызывает метод ejbLoad(), чтобы опять-таки выполнить синхронизацию между экземпляром и базой данных.

•          Контейнер удаляет Entity-объект путем вызова метода ejbRemove(). Вызов этого метода происходит в ответ на вызов клиентским приложением метода remove () home- или remote-интерфейса Компонента. Контейнер удаляет как экземпляр Компонента, так и сам Entity-объект (запись из базы данных).

Контейнер удаляет не сопоставленные с данными экземпляры из пула с помощью вызова метода unsetEntityContext () для этого экземпляра.

Класс Entity-Компонента наследует класс javax.ejb.EntityBean и реализует его методы. Контейнер использует методы этого интерфейса для уведомления экземпляров Компонента о происходящих событиях. Интерфейс EntityBean является аналогом интерфейса SessionBean.

Когда Entity-Компонент использует СМР, методы интерфейса EntityBean (за исключением двух, связанных с контекстом) и метод ejbPostCreate () служат са11Ьаск-методами. Это означает, что класс Компонента должен обеспечивать реализацию только их основных функций. Хотя это и не требуется, разработчик Компонента может добавить к этим методам код, специфический для приложения.

Entity-Компонент с BMP должен обеспечивать более полную реализацию тех же самых методов. Поскольку такой Компонент полностью берет на себя вопросы взаимодействия с базой данных, он должен корректно управлять чтением данных из БД, модификацией

•  ejbPassivate () – уведомляет Компонент о том, что готовится его деактивизация – другими словами, экземпляр будет отсоединен от конкретного Entity-объекта (от конкретных данных в базе данных) и

Для иллюстрации основ использования Entity-Компонентов с СМР в примере bank служит Компонент CheckingAccount. Во многом его реализация очень похожа на реализацию session-Компонента. Тем не менее, для реализации Entity-Компонента с СМР характерно наличие нескольких важных особенностей:

•          Entity-Компонент не содержит реализаций методов поиска. Для таких Компонентов (Компонентов с СМР) эти реализации обеспечивает Контейнер EJB. Вместо реализации этих методов в классе Компонента его разработчик помещает всю необходимую для их реализации информацию в Дескриптор Поставки.

В примере bank присутствует также Entity-Компонент SavingsAccount. Он является хорошей иллюстрацией использования BMP.

Компонент SavingsAccount используется для работы с другими таблицами, а не с теми же, с которыми взаимодействует CheckingAccount. Несмотря на то, что эти Компоненты используют различный способ сохранения своего состояния, они оба реализуют одни и те же home- и remote-интерфейсы. Несмотря на это, их реализации во многом отличаются друг от друга, и эти отличия носят принципиальный характер.

Для реализации Entity-Компонента с СМР характерно следующее:

•     Обычно поля Компонента объявляются как private, а не public. Взаимодействием с базой данных – чтением данных из БД в поля и сохранение результатов в БД – управляет сам Компонент, поэтому имеет смысл ограничить права доступа к этим полям. Это в корне отличается от использования СМР, когда вы обязаны сделать поля Компонента доступными для Контейнера, т.е. объявить их как public.

•          Метод ejbCreate () возвращает значение типа класса главного ключа – AccountPK в нашем примере. Контейнер использует это значение для создания удаленной ссылки на экземпляр Entity-Компонента.

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

•      Атомарность (Atomicity)

•      Связность (Consistency)

•      Изолированность (Isolation)

•   Сохраняемость (Durability)

Обычно для обозначения этих свойств используется аббревиатура ACID.

Транзакция часто содержит несколько операций. Атомарность подразумевает, что для завершения транзакции необходимо успешное выполнение всех ее операций. Если хотя бы одна из операций не выполнена, не должны быть выполнены все остальные.

Под связностью понимается связность информации в базе данных. Транзакции должны переводить базу данных из одного связного (устойчивого) состояния в другое. Транзакция должна обеспечивать семантическую и физическую связность данных в БД.

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

Понятие изолированности тесно связано с понятием совместного доступа. Существует понятие уровня изоляции, и чем он выше, тем более ограничены возможности внесения параллельных изменений. Наиболее высокий уровень изоляции транзакций подразумевает выполнение всех транзакций в порядке очереди (сериализация). Другими словами, содержимое базы данных меняется так, как если бы новая транзакция могла начаться только после завершения предыдущей. Тем не менее, многие приложения способны работать с более низким уровнем изоляции транзакций и, соответственно, с

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

•                 Создание объекта "транзакция".

•                 Явное начало транзакции.

•                 Передача и отслеживание контекста транзакции.

•         Подтверждение транзакции после внесения всех изменений.

Это требует от разработчика Приложения глубоких знаний о том, как управлять транзакциями с начала и до конца – код такого приложения достаточно сложен, труден для написания и может содержать ошибки. При декларативном стиле управления транзакциями Контейнер берет на себя выполнение большинства, если не всех, необходимых операций. Контейнер начинает и завершает транзакцию, а также поддерживает контекст транзакции в течение ее существования. Это существенным образом упрощает задачу разработчика, особенно для транзакций в распределенных средах.

Session-Компонент с ВМТ должен определить атрибуты транзакции и сопоставить их с каждым своим методом. Эти атрибуты предоставляют Контейнеру информацию о том, как он должен управлять транзакциями, в которых участвует данный Компонент. С каждым из методов Компонента может быть сопоставлен один из шести возможных атрибутов. Это сопоставление выполняется на этапе поставки Сборщиком Приложений или Поставщиком (Deployer).

Вот эти атрибуты:

• Reguired – этот атрибут гарантирует, что ассоциированный с ним метод выполняется в контексте глобальной транзакции. Если клиент, вызывающий этот метод, уже создал контекст транзакции, то используется именно он. Если нет, то Контейнер автоматически начинает новую транзакцию. Этот атрибут позволяет использовать любое количество Компонентов и координировать их работу в контексте одной и той же глобальной транзакции.

Вы помещаете информацию об источнике данных в Дескриптор Поставки. Необходимо указать три обязательных элемента:

•                 URL источника данных. При работе с интерфейсом DataSource, URL мог бы выглядеть так:

jdbc:oracle:thin:@avicenna:1521:avi73a

•                 Jndi-имя источника данных.

•   Имя класса jdbc-драйвера.

Полное описание этих элементов приведено в разделе "Источники данных" главы 9 на странице 9-9.

Пример Кода 8.3 содержит пример спецификации источника данных.

Пример Кода 8.3 Спецификация DataSource в Дескрипторе Поставки

<deployment-descriptor> <datasource>

<res-ref-name>jdbc/SavingsDataSource</res-ref-name> <url>jdbc:oracle:thin:@avicenna:1521:avi73a</url>

Если уровень изоляции транзакции не установлен явно, Контейнер использует уровни изоляции JDBC-драйвера и RDBMS по умолчанию. Например, Oracle поддерживает два уровня изоляции транзакций:

TRANSACTION_READ_COMMITTED и TRANSACTION_SERIALIZABLE. Первый из них используется по умолчанию, и Контейнер работает в этом режиме, если в Дескрипторе Поставки не указано другое значение.

Дескриптор Поставки может содержать пять значений уровней изоляции транзакций. Эти значения должны быть набраны заглавными буквами, а уровень их поддержки зависит от конкретной RDBMS. Вот эти значения:

•         TRANSACTI0N_N0NE

•         Т RAN SACT10N_READ_C0MMIT T E D

•         TRANSACTION_READ_UNCOMMITTED

•         TRANSACTION_REPEATABLE_READ

•     TRANSACTION_SERIALIZABLE

После того, как в Дескрипторе Поставки задан определенный уровень изоляции для источника данных, этот уровень используется для всех соединений с этим источником данных. По вопросам достижения максимальной производительности обращайтесь к документации по конкретной системе. Если вы не уверены, какой уровень изоляции выбрать, рекомендуется использовать уровень изоляции по умолчанию.

Более подробная информация приведена в главе 9 "Поставка Компонентов EJB".

Всю информацию в Дескрипторе Поставки можно разделить на две основные группы:

•          Информация о структуре Компонента. Она описывает его структуру и объявляет все внешние связи этого Компонента. Эта информация является необходимой. В общем случае она не может быть изменена, поскольку это могло бы привести к потере функциональности Компонента.

•     Информация для Сборщика Приложений. Она определяет, каким образом Компонент(ы), помещенные в файл ejb-jar, могут быть собраны вместе для формирования нового Компонента или приложения. Эта информация не является обязательной. Изменения этой информации не влияют на поведение Компонента, хотя могут повлиять на изменение поведения приложения в целом.

Для выполнения поставки Компонента вы должны установить содержащий его jar-файл в Контейнер EJB. Это можно сделать двумя способами:

•          с помощью Эксперта Поставки, входящего в состав Консоли Inprise Application Server.

•         с использованием утилиты командной строки.

В один EJB Контейнер можно установить несколько jar-файлов. В настоящее время Компонент EJB, созданный с помощью инструментов Inprise, может быть установлен только в Inprise EJB-Контейнер.

 

 

Источник: Руководство программиста Enterprise JavaBeans

По теме:

  • Комментарии