Главная » Java, JavaBeans » Компонент EJB с точки зрения клиента

0

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

•                 Получить доступ к home-интерфейсу Компонента. Спецификация EJB говорит, что для получения ссылки на интерфейс клиенту следует использовать JNDI (Java Naming and Directory Interface) API.

•                 Получить ссылку на remote-интерфейс Компонента. Для этого используются методы home-интерфейса. Вы можете либо создать Session-Компонент, либо создать или найти Entity-Компонент.

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

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

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

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

Клиент получает ссылку на 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 j avax.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)

j avax.rmi.PortableRemoteObj ect.narrow(obj ref, SortHome.class); Sort sort = home.create(); … //do the sort and merge work

sort remove();

}

}

Функция main () клиентской программы может возбуждать самое общее исключение Exception. При таком способе кодирования программа SortClient не должна обрабатывать любое исключение, и возбуждение любой исключительной ситуации приведет к завершению программы.

Получение remote-интерфейса

Сейчас, после того, как мы получили home-интерфейс Компонента, мы можем получить ссылку на его remote-интерфейс. Для этого мы должны использовать create- или find-методы home-интерфейса. Какой именно метод нужно использовать, зависит от вида Компонента и того, какие методы для Компонента предусмотрел его разработчик.

Например, в Примере Кода 5.1 показано как SortClient получает ссылку на remote-интерфейс Sort. После того, как клиент получил ссылку на home-интерфейс и преобразовал ее к нужному типу (SortHome), он создает экземпляр Компонента и вызывает его методы. Создание выполняется с помощью обращения к методу home-интерфейса create (), который и возвращает ссылку на remote-интерфейс Sort, (так ка SortBean является stateless session-Компонентом, его home-интерфейс должен содержать только один метод create () без аргументов.) Теперь SortClient может вызывать методы remote-интерфейса – sort () и merge () – для выполнения необходимых действий. После завершения работы клиент вызывает метод remove () remote-интерфейса для уничтожения экземпляра Компонента.

Session-Компоненты

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

Все Session-Компоненты должны определять как минимум один метод create (). Компонент без состояния (stateless) должен иметь только один метод с таким именем, причем он не может иметь аргументов. Компонент с состоянием (stateful) может иметь один метод create (), и еще несколько таких методов дополнительно, с различными списками аргументов. Если метод create () получает аргументы, их значения используются для инициализации создаваемого экземпляра Компонента.

Базовый метод create () не имеет аргументов. Например, в примере sort используется stateless session-Компонент. По определению, он имеет один метод create () без аргументов:

Sort sort = home.create(); С другой стороне, в примере cart используется stateful Session- Компонент, и его home-интерфейс, CartHome, объявляет несколько

вариантов метода create (). Один из них получает три аргумента, которые вместе идентифицируют покупателя, и возвращает ссылку на remote-интерфейс Cart. Клиентская программа CartClient устанавливает значение этих трех параметров – cardHolderName, creditCardNumber и expirationDate – и вызывает метод create (). Все это показано в Примере Кода 5.2:

Пример Кода 5.2 Вызов метода create()

Cart cart; {

String cardHolderName = "Jack B. Quick"; String creditCardNumber = "1234-5678-9012-3456"; Date expirationDate = new GregorianCalendar(2001, Calendar.JULY, 1) .getTimeO ;

cart = home.create(cardHolderName, creditCardNumber, expirationDate);

}

Session-Компоненты не имеют finder-методов.

Entity-Компоненты

Клиент получает ссылку на remote-интерфейс такого Компонента с помощью операций создания или поиска. Напоминаем, что Entity- Компонент является объектным представлением неких хранящихся в БД данных. Поскольку данные хранятся в общем случае в течение долгого времени, то и Компоненты являются "долгоживущими" – как правило, они существуют и после того, как завершилось создавшее их клиентское приложение. Таким образом, в большинстве случаев клиент ищет готовый экземпляр Компонента, а не создает новый, что связано с помещением новых данных в БД.

Для поиска клиент вызывает предназначенные для этого методы, подобно тому, как это происходит с поиском нужной записи в реляционной БД. Это подразумевает, что find-методы выполняют поиск экземпляров Компонентов, чьи данные уже помещены в хранилище данных. Эти данные могут быть добавлены как с помощью Entity- Компонентов, так и с помощью других инструментов, не имеющих отношения к EJB – например, непосредственно средств управления данной базой данных (Database management system, DBMS), или, в случае унаследованных (legasy) систем, данные уже существуют перед инсталляцией Контейнера EJB.

Для создания экземпляра Компонента с помещением его состояния в сопоставленную с ним БД клиент вызывает метод create (). Для инициализации внутренних переменных Компонента используются аргументы метода create (). Этот метод всегда возвращает ссылку на remote-интерфейс, хотя соответствующий ему метод ejbCreate() возвращает ключ (primary key) экземпляра Компонента.

Каждый экземпляр Entity-Компонента должен иметь primary key, который является его уникальным идентификатором. Экземпляр

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

Методы поиска и класс ключа компонента

Основным методом поиска Компонента является метод findByPrimaryKey (), который выполняет поиск по значению первичного ключа. Вот его сигнатура:

<remote interface> findByPrimaryKey! <key type> primaryKey ) Метод findByPrimaryKey () должен быть реализован для каждого Entity- Компонента. Тип единственного аргумента – primaryKey – представляет собой класс, объявленный в Дескрипторе Поставки. Этот тип должен соответствовать ограничениям RMI-IIOP, и может являться как стандартным классом Java, так и классом, созданным разработчиком.

Например, вы можете иметь Компонент Account, для которого определен класс его первичного ключа AccountPK. Типом AccountPK является стандартный тип String. Мы можем получить ссылку на нужный экземпляр Компонента Account, установив требуемое значение идентификатора счета и вызвав метод findByPrimaryKey (), как показано в Примере Кода 5.3.

Пример Кода 5.3 Поиск экземпляря Компонента по первичному ключу

AccountPK accountPK = new AccountPK("1234-56-789"); Account source = accountHome.findByPrimaryKey( accountPK ); Разработчик Компонента (bean provider) может определить дополнительные методы поиска.

Методы создания и удаления экземпляра

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

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

Вызов методов

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

Пример кода 5.4 иллюстрирует использование клиентом методов Компонентов EJB, в нашем случае, Session-Компонента cart, мы приводим фрагмент текста с момента создания нового экземпляра Компонента и получения ссылки на remote-интерфейс. После этого клиент может обращаться к нужным методам.

Во-первых, клиент создает новый объект "книга" и устанавливает его параметры "заглавие" и "цена". Затем он добавляет этот объект к списку покупок с помощью вызова бизнес-метода addltem(). Это метод определен в классе CartBean Session-Компонента и сделан доступным для клиента его объявлением в remote-интерфейсе.

После выбора всех нужных книг (не показано в примере) клиент вызывает свой собственный метод summarize () для получения списка покупок в чеке. После этого вызывается метод remove () для уничтожения экземпляра объекта. Обратите внимание, что обращение к методам Компонента выглядит точно так же, как и обращение к локальным методам клиента, таким, как summarize ().

Пример Кода 5.4 Вызов методов Компонента

Cart cart; {

// obtain a reference to the bean’s remote interface cart = home.create(cardHoiderName, creditCardNumber, expirationDate);

}

// create a new book object

Book knuthBook = new Book("The Art of Computer Programming", 49 95f); // add the new book item to the cart cart addltem(knuthBook);

// list the items currently in the cart

summarize(cart);

cart removeltem(knuthBook);

Удаление экземпляров Компонента

Метод remove () выполняется по-разному для Session- и Entity- Компонентов. Так как Session-Компонент является временным и взаимодействует только с одним клиентом, то клиенту при завершении работы с Компонентом следует вызвать метод remove (). Клиент может использовать один из двух доступных методов:

javax.ejb.EJBObject.remove() и javax.ejb.EJBHome.remove(Handle handle) (об использовании handle см. раздел "Использование идентификаторов компонентов" на стр. 4-7).

Хотя выполнение удаления объекта не является жестким требованием, это рассматривается как "хороший" стиль программирования. Если клиент не удалил stateful session-компонент явно, это будет сделано Контейнером по истечении определенного времени (интервала тайм- аута). Значение этого интервала хранится как свойство в Дескрипторе Поставки. Тем не менее, клиент может сохранить идентификатор этого экземпляра для дальнейшего использования.

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

Использование идентификаторов Компонентов

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

Тем не менее, таким способом вы можете восстановить связь с компонентом, но не сам Компонент; если другой процесс уничтожил экземпляр компонента, произошел сбой в системе, перезапуск Сервера или что-то другое, что привело к уничтожению экземпляра Компонента, то при попытке восстановить с ним связь будет возбуждено исключение.

Если вы не уверены в том, что экземпляр Компонента все еще существует, то лучше вместо идентификатора remote-интерфейса восстановить идентификатор home-интерфейса, после чего создать экземпрляр с помощью create- или find-методов.

Для получения идентификатора объекта после его создания, вы можете использовать метод getHandle (), после чего он может быть записан в файл с использованием механизма сериализации Java. Когда это станет необходимо, программа может извлечь данные из этого файла и преобразовать их к типу Handle. Затем она обращается к его методу getEJBObject() для получения ссылки на Компонент (с выполнением преобразования типа результата getEJBObject () к нужному типу).

В качестве иллюстрации рассмотрим пример, как программа CartClient могла бы сохранить идентификатор компонента CartBean:

Пример Кода 5.5 Использование идентификатора для доступа к Компоненту

import java.io; import javax.ejb.Handle;

Cart cart;

cart = home.create(cardHolderName, creditCardNumber, expirationDate); // call getHandle on the cart object to get its handle cartHandle = cart.getHandle(); // write the handle to serialized file

FileOutputStream f = new FileOutputStream ("carthandle.ser"); ObjectOutputStream о = new ObjectOutputStream(f); o.writeObject(cartHandle); o.flush ();

0.       close    ();

// read handle from file at later time

FilelnputStream fi = new FilelnputStream ("carthandle.ser"); ObjectlnputStream oi = new ObjectlnputStream(fi); //read the object from the file and cast it to a Handle cartHandle = (Handle)oi.readObject();

1.       close     ();

// Use the handle to reference the bean instance try {

Object ref = context.lookup("cart");

Cart cartl = (Cart) javax.rmi.PortableRemoteObject.narrow(ref, Cart.class);

} catch (RemoteException e) { }

После завершения работы с идентификатором, можно удалить его, обратившись к методу javax.ejb.EJBHome. remove (Handle handle).

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

По теме:

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