Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

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

.pdf
Скачиваний:
38
Добавлен:
24.05.2014
Размер:
1.45 Mб
Скачать

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò à E J B

Обратите внимание, что типы результата у соответствующих методов класса Компонента и его home-интерфейса отличаются друг от д руга.

Home-интерфейс для Entity-компонента содержит также методы поиска (find-методы). Об этом будет подробно рассказано в разд еле "Home-интерфейс Entity-Компонента" на стр. 4-9.

Базовый класс EJBHome

Каждый home-интерфейс наследует интерфейс javax.ejb.EJBHome. Пример Кода 4.3 показывает определение этого интерфейса:

Пример кода 4.3 Определение интерфейса EJBHome

package javax.ejb;

public interface EJBHome extends java.rmi.Remote {

void remove(Handle handle) throws java.rmi.RemoteException, RemoveException;

void remove(Object primaryKey) throws java.rmi.RemoteException, RemoveException;

EJBMetaData getEJBMetaData() throws RemoteException; HomeHandle getHomeHandle() throws RemoteException;

}

Предусмотрены два варианта метода удаления экземпляра К омпонента remove(). Первый из них удаляет экземпляр Компонента по его идентификатору (handle), второй - по значению primary key Компонента.

Handle Компонента представляет собой его уникальный идентификатор; для него может быть выполнена операция сериализации Java. Времена существования handle и сопоставленно го с ним объекта совпадают. При работе с Entity-Компонентами, клиент может сохранять (с помощью Java-сериализации) значение этого идентификатора с последующим восстановлением в нужный м омент. Этот идентификатор может корректно ссылаться даже на раз личные экземпляры Компонента; он остается корректным даже после сбоя на сервере с последующим перезапуском, а также в случае "пере мещения" объектов на другие Сервера или компьютеры. Он очень похож на преобразованную к строковому виду объектную ссылку CORBA.

Второй вариант remove() для определения подлежащего удалению экземпляра Компонента использует значение его primary key. Его типом может быть любой тип Java, который наследует класс Object и реализует интерфейс Serializable. Primary key - главное средство для идентификации Entity-Компонентов. Как правило, он совпадает с первичным ключом в таблице базы данных, используемом для уникальной идентификации записи, объектным представлен ием которой является данный Компонент.

Метод getEJBMetaData() возвращает metadata-интерфейс для Компонента EJB. Этот интерфейс предоставляет клиенту возмо жность

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò î â E J B

4 - 7

Каждый метод create() должен соответствовать методу ejbCreate в классе Компонента. Эти методы должны иметь одно и то же чис ло

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò à E J B

получить информацию о структуре Компонента (его метаданн ые). Обычно его используют инструментальные программные сре дства, создающие приложения из поставленных Компонентов EJB. Инте рфейс javax.ejv.EJBMetaData объявляет методы для получения ссылки на интерфейс javax.ejb.EJBHome, типов (классов) home- и remoteинтерфейсов, а также типа primary key. Он также содержит метод isSession() для определения того, является ли Компонент Sessionили

Entity-Компонентом. Метод isStatelessSession() позволяет определить, имеет ли Session-Компонент состояние (т.е. является ли он statelessКомпонентом или нет). Пример Кода 4.4 показывает, что собой представляет интерфейс javax.ejv.EJBMetaData.

Пример Кода 4.4 Интерфейс javax.ejb.EJBMetaData package javax.ejb;

public interface EJBMetaData { EJBHome getEJBHome();

Class getHomeInterfaceClass(); Class getRemoteInterfaceClass(); Class getPrimaryKeyClass(); boolean isSession();

boolean isStatelessSession();

}

Home-интерфейс Session-Компонента EJB

Как уже говорилось в разделе "Session-Компоненты" на стр. 2-3, каждый экземпляр такого Компонента обслуживает запросы только одного клиента. Это означает, что после создания экземпля ра Компонента по запросу клиента, этот экземпляр виден тольк о для создавшего его клиента (подразумевается, что мы говорим о statefulКомпоненте, который поддерживает состояние, характеризу ющее его "отношения" с клиентом. Компонент без состояния, поскольку он не отслеживает историю вызовов, может быть использован для обслуживания запросов различных клиентов).

Home-интерфейс Компонента выступает в роли фабрики Компонен тов, поскольку он содержит один или несколько методов create(). Спецификация EJB определяет следующие соглашения для кажд ого метода. create():

. Он возвращает remote-интерфейс для своего Компонента.

. Имя метода - всегда "create".

.аргументов одинаковых типов.

Он должен объявлять возможность возбуждения исключения java.rmi.remoteException.

4 - 8

Ð ó ê î â î ä ñ ò â î Ï ð î ã ð à ì ì è ñ ò à E n t e r p r i s e J a v a B e a n s

.

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò à E J B

Он должен объявлять возможность возбуждения исключения

.

javax.ejb.CreateException.

Аргументы метода create() используются для инициализации нового

 

экземпляра Компонента.

Пример Кода 4.5 демонстрирует различные варианты метода create home-интерфейса Компонента. Обязательные фрагменты текста выделены жирным шрифтом.

Пример Кода 4.5 Пример методов create()

public interface AtmHome extends javax.ejb.EJBHome {

Atm create()

throws java.rmi.RemoteException, javax.ejb.CreateException;

Atm create( Profile preferredProfile )

throws java.rmi.RemoteException, javax.ejb.CreateException;

}

Обратите внимание, что home-интерфейс Session-Компонента не содержит методов для поиска объектов, поскольку такой объ ект может быть использован только создавшим его клиентом. Другие кл иенты не могут получить к нему доступ и, следовательно, не нуждаютс я в средствах поиска.

Home-интерфейс Entity-Компонента EJB

Home-интерфейс Entity-Компонента содержит точно такие же методы create(), как и Session-Компонент. В дополнение к ним, интерфейс определяет find-методы для поиска нужных экземпляров Компон ента с целью их последующего использования. Такие операции необ ходимы, так как экземпляры Entity-Компонентов являются "долгоживущим и" объектами и могут использоваться многими клиентами. Для большинства приложений, используемые в них Entity-Компоненты уже существуют и клиент просто должен найти нужный экземпляр для выполнения вызова.

Home-интерфейс Entity-Компонента EJB должен обеспечивать базовый метод поиска, findByPrimaryKey (primaryKey), который служит для поиска экземпляра Компонента по значению его primary key. Метод имеет единственный аргумент, а в качестве результата возв ращает remote-интерфейс Компонента. В качестве primary key может использоваться любой тип Java, производный от Object. Вы помещаете тип primary key в Дескриптор Поставки. Обратите внимание, что мето д findByPrimaryKey () по определению возвращает только один объект, в то время как другие find-методы могут возвращать наборы объе ктов.

Пример Кода 4.5 метод findByPrimaryKey()

<entity bean's remote interface> findByPrimaryKey( <primary key type> key )

throws java.rmi.RemoteException, FinderException;

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò î â E J B

4 - 9

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò à E J B

Home-интерфейс может объявлять и другие методы поиска. Кажды й такой метод должен быть реализован в классе Компонента. Каждый finder-метод home-интерфейса Компонента должен следовать следующим. соглашениям:

Типом результата является либо remote-интерфейс Компонента, л ибо, в случае соответствия сразу нескольких экземпляров Комп онента указанному критерию поиска, набор (collection) таких интерфейсов . Корректными типами-наборами Java являются java.util.Enumeration

. (äëÿ JDK 1.1) è java.util.Collection (äëÿ Java 2).

Имя метода поиска всегда начинается с префикса "find". Соответствующий ему finder-метод в классе Компонента должен

. начинаться с "ejbFind".

Он должен объявлять возможность возбуждения исключения

. java.rmi.remoteException.

Он должен объявлять возможность возбуждения исключения

. javax.ejb.FinderException.

Списки возможных исключений методов find() home-интерфейса и ejbFind() класса Компонента должны быть одинаковыми.

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

Методы create home-интерфейса должны соответствовать следующим правилам:.

Они должны объявлять возможность возбуждения исключени я

. java.rmi.remoteException.

Они должны объявлять возможность возбуждения исключени я

. javax.rmi.CreateException.

. Они возвращают remote-интерфейс Компонента.

. Имя метода - всегда "create".

Каждому методу create() интерфейса должен соответствовать метод

.ejbCreate() в классе Компонента с тем же списком своих аргументов. Список возможных исключений метода create() интерфейса должен включать в себя все исключения методов ejbCreate() è ejbPostCreate() класса Компонента, т.е. список исключений метода create() должен являться надмножестом объединения списков

исключений методов ejbCreate() è ejbPostCreate(). Типом результата

.метода ejbCreate() всегда является класс Primary Key.

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

Пример Кода 4.7 демонстрирует различные виды find- и create-методов. Требуемые фрагменты текста выделены жирным шрифтом.

4-10

Ð ó ê î â î ä ñ ò â î Ï ð î ã ð à ì ì è ñ ò à E n t e r p r i s e J a v a B e a n s

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò à E J B

Пример кода 4.7 Методы Create и find

public interface AccountHome extends javax.ejb.EJBHome {

Account create( String accountId )

throws java.rmi.RemoteException, javax.ejb.CreateException;

Account create( String accountId, float initialBalance ) throws java.rmi.RemoteException, javax.ejb.CreateException;

Account findByPrimaryKey( String key )

throws java.rmi.RemoteException, javax.ejb.FinderException;

Enumeration findBySocialSecurityNumber( String socialSecurityNumber ) throws java.rmi.RemoteException, javax.ejb.FinderException;

}

Реализация Компонента EJB

Именно на стадии реализации Компонента происходит напис ание кода его бизнес-методов. Реализация Компонента - прерогатива Bean Provider'а. Для Session-Компонента также необходимо реализовать методы интерфейса javax.ejb.SessionBean, для Entity-Компонента - интерфейса javax.ejb.EntityBean. Оба этих интерфейса наследуют базовый интерфейс Компонентов EJB - javax.ejb.EnterpriseBean.

Реализации Session- и Entity-Компонентов отличаются друг от друга. Обратитесь к Главе 6, "Написание Session-Компонента", для получени я подробной информации о реализации Session-Компонентов. Обрати тесь к Главе 7, "Написание Entity-Компонента", для получения подробной информации о реализации Entity-Компонентов.

Интерфейс EnterpriseBean

Интерфейс EnterpriseBean Компонентов EJB является общим базовым интерфейсом и, в свою очередь, он наследует интерфейс java.io.Serializable. Этот интерфейс не содержит объявлений методов. Его код показан в Примере Кода 4.8.

Пример Кода 4.8 Интерфейс EnterpriseBean

package javax.ejb;

public interface EnterpriseBean extends java.io.Serializable {}

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò î â E J B

4-11

Î ã ð à í è ÷ å í è ÿ ï ð è ï ð î ã ð à ì ì è ð î â à í è è

Идентификаторы (Handles)

Идентификатор (handle) представляет собой доступную для удале нных объектов догическую ссылку на экземпляр Компонента или е го homeинтерфейс. Интерфейс javax.ejb.Handle, который должен быть реализован для всех классов Идентификаторов Компонента , предоставляет хранимую (persistence) ссылку на экземпляр Компоне нта. Ниже приведен его код:

Пример Кода 4.9 Интерфейс Handle

public interface javax ejb Handle extends java.io.Serializable { public EJBObject getEJBObject() throws java.rmi.RemoteException;

}

Идентификатор может быть использован для долговременно го хранения ссылки на экземпляр Компонента путем Java-сериализ ации экземпляра класса, реализующего handle-интерфейс. Это очень по хоже на преобразование к строковому виду объектной ссылки CORBA. Интерфейс javax.ejb.Handle наследует интерфейс java.io.Serializable.

Существует также интерфейс javax.ejb.HomeHandle, который позволяет использовать хранимую ссылку на home-интерфейс Компонента. Э тот интерфейс должен быть реализован в классах, являющихся представлением такой ссылки. Пример Кода 4.10 показывает код интерфейса:

Пример Кода 4.10 Интерфейс HomeHandle

public interface HomeHandle extends java.io.Serializable { public EJBHome getEJBHome() throws RemoteException;

}

Обычно реализацию handle-интерфейсов обеспечивает Контейнер .

Ограничения при программировании

Ниже приведен список программных ограничений, определен ных в спецификации. EJB 1.1.

Компонентам EJB не разрешается управлять потоками (threads) или группами потоков. Им не следует создавать новые потоки ил и активизировать приостановленные, а так же завершать или приостанавливать выполняемые. Кроме того, Компоненты EJB не

. должны менять приоритеты потоков или их имена.

Компонентам EJB не разрешено использовать static-поля, за исключением полей "только для чтения". Следовательно, все st atic-

.поля должны быть объявлены как final.

Компонентам EJB не разрешено использовать средства синхро низации потоков для синхронизации выполнения кода нескольких экземпляров Компонента.

4 - 1 2

Ð ó ê î â î ä ñ ò â î Ï ð î ã ð à ì ì è ñ ò à E n t e r p r i s e J a v a B e a n s

.Компоненты не должны использовать средства Java AWT для вывода информации на экран или воспринимать информацию, вводиму ю сï ð èÎ ã ð à í è ÷ å í è ÿ ï ð î ã ð à ì ì è ð î â à í è è

. клавиатуры.Компонентам не следует использовать пакет java.io для работы с

. файлами или каталогами файловой системы.

Компонентам EJB следует избегать использования сокетов; ос обенно им не следует получать информацию из сокетов и отслеживат ь соединения. Кроме того, им не следует взаимодействовать с фабриками сокетов, используемыми ServerSocker è Socket, èëè

. фабриками, используемыми URL.

Компоненты EJB не должны обращаться к классам или пакетам, а также пытаться получить информацию о классах, с использов анием способов, не поддерживаемых языком Java, а также пытаться

.получить доступ к классам, недоступным для Компонента.

Компонент EJB не должен обращаться к функциям и сервисам сре ды исполнения, взаимодействием с которыми занимается Конте йнер EJB - создавать загрузчики классов или получать доступ к их ко нтексту,

устанавливать или создавать менеджеров безопасности, ос танавливать

.JVM, изменять стандартные потоки ввода-вывода. Компонент не должен получать информацию о профилях

. безопасности для конкретных источников кода.

. Компоненты EJB не должны загружать native-библиотеки. Компоненты не должны добавлять классы в пакеты, так как эт о (в

.целях обеспечения безопасности) должны делать Контейнер ы. Компоненты EJB не должны использовать subclass и возможности

.object substitution Java Serialization Protocol.

Следует проявлять осторожность при передаче this в качестве

аргументов или при возврате результата. Безопаснее в этом случае использовать результаты вызовов методов

.SessionContext.getEJBObject() èëè EntityContext.getEJBObject(). Компонентам EJB не разрешается получать доступ или изменят ь объекты конфигурации безопасности. Например, им не разреш ено изменять свой java.security.Identity. Любые попытки такого рода должны приводить к возникновению исключения java.security.SecurityException.

Ð à ç ð à á î ò ê à Ê î ì ï î í å í ò î â E J B

4-13

Ð ó ê î â î ä ñ ò â î

Ï ð î ã ð à ì ì è ñ ò à

E n t e r p r i s e

J a v a B e a n s

Получить доступ к home-интерфейсу Компонента. Спецификация E JB говорит, что для получения ссылки на интерфейс клиенту сл едует
Отображение EJB на CORBA

Ã5ë à â à

Написание клиентского приложения

Â. главе рассматриваются следующие основные темы:

. Компонент EJB с точки зрения клиента

. Управление транзакциями

. Получение информации о Компоненте EJB

. Поддержка JNDI

Компонент EJB с точки зрения клиента

Клиентом Компонента является приложение - независимое (stan d- alone) приложение, сервлет или апплет - или другой Компонент. В любом случае для использования Компонента EJB клиент долже н выполнить. следующие действия:

.использовать JNDI (Java Naming and Directory Interface) API. Получить ссылку на remote-интерфейс Компонента. Для этого

используются методы home-интерфейса. Вы можете либо создать

.Session-Компонент, либо создать или найти Entity-Компонент.

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

Í à ï è ñ à í è å ê ë è å í ò ñ ê î ã î ï ð è ë î æ å í è ÿ

5-1

Ê î ì ï î í å í ò E J B ñ ò î ÷ ê è ç ð å í è ÿ ê ë è å í ò à

Инициализация клиента

Приложение SortClient импортирует все необходимые классы JNDI и home- и remote-интерфейсы Компонента SortBean (см. Пример Кода 5.1 на стр. 4-2.) Для поиска home-интерфейса используется JNDI API.

Поиск home-интерфейса

Клиент получает ссылку на home-интерфейс с помощью JNDI, как это показано в Примере Кода 5.1. Вначале клиент должен получить базовый контекст службы имен (initial naming context). В программе создается новый объект типа javax.naming.Context, который в нашем примере называется context. После этого клиент вызывает его мет од lookup() для получения ссылки на home-интерфейс. Обратите внимание, что способ инициализации фабрики initial naming context зависит от реализации Контейнера/Сервера.

Метод lookup() контекста возвращает объект типа java.lang.Object. Ваша программа должна выполнить преобразование к нужном у типу. Пример Кода 5.1 содержит фрагмент кода из примера sort. Функция main() начинается с использования службы имен JNDI и метода lookup() ее контекста для получения ссылки на home-интерфейс.

Вы передаете имя remote-интерфейса (sort в нашем случае) методу context.lookup(). Заметьте, что программа пробует преобразовать результат вызова метода к типу SortHome, т.е. типу home-интерфейса.

Пример Кода 5.1 Использование JNDI для поиска home-интерфейса Компонента

// SortClient java

import javax.naming.InitialContext;

import SortHome; // import the bean's home interface import Sort; // import the bean's remote interface

public class SortClient {

...

public static void main(String[] args) throws Exception { javax.naming.Context context;

{// get a JNDI context using the Naming service context = new javax.naming.InitialContext();

}

Object objref = context.lookup("sort"); SortHome home = (SortHome)

javax.rmi.PortableRemoteObject.narrow(objref,

SortHome.class); Sort sort = home.create();

... //do the sort and merge work

5 - 2

Ð ó ê î â î ä ñ ò â î Ï ð î ã ð à ì ì è ñ ò à E n t e r p r i s e J a v a B e a n s