Дескрипторы развертывания компонентов EJB
Помимо декларации интерфейсов и классов компонентов, для построения EJB-компонента необходимо написать дескриптор развертывания — XML-файл в специальном формате, определяющий набор компонентов приложения и их основные свойства.
Чаще всего дескрипторы развертывания не пишут вручную, их готовят с помощью специализированных инструментов для развертывания J2EE-приложений или сред разработки (например, такими возможностями обладает среда NetBeans 4.0 [3]). Здесь мы опишем только часть содержимого дескрипторов развертывания. Полное описание используемых в них тегов и их назначения см. в [2].
Дескриптор развертывания упаковывается вместе с байт-кодом классов компонентов приложения в JAR-архив. При развертывании такой архив помещают в выделенную директорию, в которой сервером J2EE ищет развертываемые приложения. После этого сервер сам осуществляет запуск приложения и поиск кода компонентов, необходимых для обработки поступающих запросов, на основании информации, предоставленной дескриптором.
Заголовок дескриптора развертывания для набора EJB-компонентов версии 2.1 выглядит следующим образом.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" http://java.sun.com/j2ee/dtds/ejb-jar_2_1.dtd">
Дескриптор развертывания содержит следующие теги.
- <ejb-jar>
Обязательный элемент.
Это корневой тег дескриптора развертывания набора EJB-компонентов, содержащий все остальные теги.
- <enterprise-beans>
Обязательный элемент, должен появиться внутри <ejb-jar> ровно один раз.
Содержит набор описаний отдельных EJB-компонентов в виде элементов <entity>, <session>, <message-driven>.
- <entity> и <session>
Эти теги вложены в тег <enterprise-beans> и служат для описания, соответственно, компонентов данных и сеансовых компонентов. Они могут содержать следующие вложенные теги.
- <ejb-name>
Требуется ровно один.
Задает имя компонента.
- <home>
Необязателен, начиная с EJB 2.0. В EJB 1.1 требуется ровно один.
Указывает полное имя удаленного исходного интерфейса. - <remote>
Необязателен, начиная с EJB 2.0. В EJB 1.1 требуется ровно один.
Указывает полное имя удаленного интерфейса. - <local-home>
Необязателен.
Указывает полное имя локального исходного интерфейса. - <local>
Необязателен.
Указывает полное имя локального интерфейса. - <ejb-class>
Требуется ровно один.
Указывает полное имя класса компонента. - <primkey-field>
Необязателен, используется в описании компонентов данных.
Указывает имя поля, являющегося первичным ключом (если он состоит только из одного поля и синхронизацией компонента с базой данных управляет контейнер). - <prim-key-class>
Требуется ровно один, используется в описании компонентов данных.
Указывает имя класса первичного ключа. Можно отложить точное определение класса первичного ключа до развертывания, тогда в этом поле указывается java.lang.Object. - <persistence-type>
Требуется ровно один, используется в описании компонентов данных.
Имеет значения Bean или Container, в зависимости от того, управляется ли синхронизация компонента с базой данных самим компонентом или контейнером. - <cmp-version>
Необязателен.
Указывает версию спецификаций EJB, в соответствии с которой разработан компонент, что определяет способ управления этим компонентом. Может иметь значения 2.x и 1.x. - <abstract-schema-name>
Необязателен.
Задает уникальный идентификатор компонента для использования в запросах на языке EJB QL, который используется для описания запросов к схеме данных при реализации компонента данных, самостоятельно управляющего связью с СУБД. - <cmp-field>
Один или более, используется в описании компонентов данных.
Каждый такой элемент описывает одно поле данных, синхронизация которого с СУБД управляется EJB-контейнером. Он может содержать тег <description> с описанием поля и должен содержать тег <field-name> с именем поля.
В EJB 2.0 это имя совпадает с именем абстрактного свойства (для которого в классе компонента декларированы методы getName() и setName()), а в EJB 1.1 — с именем одного из полей класса компонента. - <security-role-ref>
Один или более, необязателен.
Указывает роли, используемые данным компонентом. Они при работе приложения служат для авторизации доступа — сопоставляются с ролями, которым разрешен доступ к тому или иному методу.
Может содержать тег <description> (необязателен) и теги <role-name> (обязателен), <role-link> (необязателен, служит для сопоставления указанного имени роли с логической ролью, описанной в <security-role> раздела <assembly-descriptor>). - <security-identity>
Необязателен.
Определяет, какую логическую роль будет играть данный компонент при обращениях к другим компонентам. Для этого может быть использован вложенный тег <run-as><role-name>…</role-name></run-as> для указания имени конкретной логической роли, или <use-caller-identity/> для указания того, что нужно использовать роль вызывающего клиента. - <session-type>
Требуется ровно один, используется в описании сеансовых компонентов.
Имеет значения Stateful или Stateless, в зависимости от того, использует ли данный компонент состояние сеанса. - <transaction-type>
Требуется ровно один, используется в описании сеансовых компонентов.
Имеет значения Container или Bean, в зависимости от того, управляет ли транзакциями данного компонента контейнер или он сам. В первом случае соответствующие транзакции должны быть описаны в разделе <assembly-descriptor> (см. далее). - <query>
Один или более, необязателен.
Используется для описания запросов, с чьей помощью реализуются некоторые методы компонентов данных, которые сами управляют связью с базой данных. Запросы описываются на языке EJB QL [X] и привязываются к методам компонента с помощью тегов <query-method>. Сам код запроса описывается внутри элемента CDATA во вложенном теге <ejb-ql>.
Например
<query> <query-method> <method-name>findByName</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql> <!CDATA[ SELECT OBJECT(c) FROM Client c WHERE c.name = ?1 ]] </ejb-ql> </query> - <relationships>
Необязателен. Вложен в <ejb-jar>.
Описывает набор отношений между компонентами, которые соответствуют связям в схеме базы данных и автоматически поддерживаются контейнером. Каждое отношение описывается с помощью вложенного тега <ejb-relation>. - <ejb-relation>
Описывает одно отношение и может иметь следующие элементы.- <ejb-relation-name>
Необязателен, только один. Задает имя отношения. - <ejb-relationship-role>
Обязательно два. Описывает одну роль в рамах отношения. В описании роли должны присутствовать следующие данные. - Имя роли — во вложенном теге <ejb-relationship-role-name>.
- Множественность — сколько экземпляров компонента могут играть такую роль в рамках данного отношения с одним экземпляром в другой роли. Описывается в теге <multiplicity> и может иметь значения One или Many.
- Имя компонента, экземпляры которого играют данную роль в этом отношении. Определяется в теге <relationship-role-source> внутри тега <ejb-name> в виде имени, которое присвоено компоненту в рамках данного дескриптора.
- Имя поля, которое хранит ссылку или коллекцию ссылок, поддерживающие это отношение в рамках экземпляра компонента. Определяется в теге <cmr-field>, во вложенном теге <cmr-field-name>, и для него в классе компонента должно быть определено абстрактное свойство с тем же именем.
- <ejb-relation-name>
- <ejb-name>
- <assembly-descriptor>
Этот обязательный тег внутри <ejb-jar> содержит дополнительные указания для сборки компонентов, в частности следующие.- <container-transaction>
Один или более, необязателен.
Содержит необязательный элемент <description>, а также приведенные ниже.
Для компонента данных должно быть по одному такому элементу на каждый метод удаленного интерфейсов.
Сеансовые компоненты, транзакциями которых управляет EJB-контейнер, также должны подчиняться этому правилу.- <method>
Один или более.
Содержит тег <ejb-name>, указывающий имя компонента, и <method-name>, указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам.
Может также включать элементы <description>, <method-params> и <method-intf>, который может иметь значения Remote, Home, Local, Local-Home, в зависимости от того, в каком интерфейсе этот метод декларирован — для поддержки возможности декларировать методы с одним именем и набором параметром в разных интерфейсах. - <trans-attribute>
Ровно один.
Определяет атрибут транзакции, управляющий политикой включения в транзакции или создания новых транзакций.
Для компонентов данных атрибуты транзакции должны быть определены для всех методов удаленного интерфейса и методов, декларированных в исходном интерфейсе, для сеансовых компонентов — для всех методов удаленного интерфейса.
Может иметь значения NotSupported, Supports, Required, RequiresNew, Mandatory, Never. Об их смысле рассказывалось в предыдущей лекции.
- <method>
- <security-role>
Один или более, необязателен.
Определяет роли, служащие для контроля доступа к методам компонентов. В таком элементе должен содержаться тег <role-name>, задающий имя роли. - <method-permission>
Один или более, необязателен.
Указывает правила доступа ролей, определенных в тегах <security-role>, к методам компонентов.
Содержит необязательный тег <description>, один или несколько тегов <role-name> и один или несколько тегов <method> (см. выше), кроме того, в нем может присутствовать тег <unchecked/>, который обозначает отсутствие проверки прав доступа во время работы, даже если они описаны.
Каждый тег <method> содержит тег <ejb-name>, указывающий имя компонента, и <method-name>, указывающий имя метода или знак *, который обозначает применение указанного атрибута ко всем методам. - <exclude-list>
Необязателен.
Содержит один или несколько тегов <method> (см. выше), определяющих методы, которые не должны вызываться при работе приложения. Каждый вызов такого метода создает исключительную ситуацию.
- <container-transaction>