Главная » Java, Web, XML » Компоненты EJB

0

, как следует из их названия, должны обладать той же особенностью, что и компоненты JavaBeans, а именно — легко и без всяких изменений встраиваться в создаваемые приложения. В случае компонентов EJB это условие означает — встраиваться в любой  и работать

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

интерфейс EnterpriseBean — на удивление прост. Он не содержит ни констант, ни заголовков методов, а только расширяет интерфейс Serializable. Это означает, что каждый компонент EJB должен быть сериализуемым. На самом деле интерфейс EnterpriseBean — это только суперинтерфейс для интерфейсов, описывающих конкретные типы компонентов EJB. На сегодняшний день существует три типа компонентов EJB, описанных тремя расширениями интерфейса EnterpriseBean — интерфейсами SessionBean, EntityBean и MessageDrivenBean. Каждый компонент EJB должен реализовать один из этих интерфейсов.

Компоненты типа SessionBean предназначены для работы с клиентом EJB- приложения, которым может быть сервлет, страница JSP, отдельное приложение, другой компонент EJB. Мы будем называть их session-компонентами. Клиенты session-компонента могут быть удаленными (remote) или локальными (local). Локальные клиенты работают на той же самой виртуальной машине Java, что и компонент. Удаленные клиенты работают на другой виртуальной машине Java.

Есть две разновидности session-компонентов: компоненты, не сохраняющие свое текущее состояние для последующих вызовов клиента (Stateless Session Beans), и компоненты, сохраняющие свое состояние в оперативной памяти, но не на постоянном носителе информации (Stateful Session Beans). Первые удобны для создания Web-служб, поскольку Web-службы не создают сеанс связи с клиентом. Последние удобны для создания сеанса связи с клиентом и в Web-службах не применяются.

Компоненты типа EntityBean предназначены для хранения данных, извлеченных из постоянных хранилищ, в виде объектов Java. Мы будем называть их entity-компонентами. Клиенты entity-компонента могут изменить его содержимое. Entity-компоненты поддерживают связь с источником данных и сохраняют свое содержимое в постоянном хранилище при всяком изменении своего состояния. Они не применяются для создания Web-служб, а используются ими когда Web-службам надо получить информацию из базы данных или сохранить информацию в базе данных.

Компоненты ТИПа MessageDrivenBean ВЫПОЛНЯЮТ Те Же фуНКЦИИ, ЧТО И session-компоненты без сохранения состояния, но действуют асинхронно.

Мы будем называть их MDB-компонентами. Они удобны для создания асинхронных Web-служб документного стиля.

Итак, для создания Web-служб процедурного стиля удобны session- компоненты без сохранения состояния, а для создания Web-служб документного стиля — MDB-компоненты. Рассмотрим подробнее устройство этих компонентов EJB.

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

Как ясно из сказанного выше, session-компонент — это класс или несколько классов, реализующих интерфейс SessionBean. Интерфейс SessionBean описывает всего четыре метода. Три метода предназначены для EJB- контейнера.

Метод

public void ejbActivate ()

throws EJBException, RemoteException

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

Метод

public void ejbPassivate ()

throws EJBException, RemoteException

автоматически выполняется EJB-контейнером, когда он решает, что пора сохранить состояние session-компонента.

Как ВИДНО ИЗ ЭТОГО Краткого ОПИСаНИЯ, МеТОДЫ ejbActivate () И ejbPassivate о полезны только для session-компонентов с сохранением состояния. Для Web-служб делается пустая реализация этих методов.

Третий метод

public void ejbRemovef)

throws EJBException, RemoteException

выполняется EJB-контейнером при завершении работы с контейнером. В него можно записать завершающие действия компонента.

Четвертый метод

public void setSessionContext(SessionContext ctx) throws EJBException, RemoteException

позволяет session-компоненту получить контекст, в котором он работает, в виде объекта типа SessionContext.

Интересно то, что никакой клиент не может обратиться к session- компоненту напрямую. Вместо этого клиент обращается к EJB-контейнеру, который активизирует session-компонент и передает ему запрос клиента. Результаты выполнения методов компонента опять-таки передаются клиенту через EJB-контейнер. Контейнер взаимодействует с клиентом через специальные remote- и home-интерфейсы.

Remote-интерфейс session-компонента

Для взаимодействия с удаленным клиентом EJB-контейнер предоставляет ему интерфейс типа EjBObject. Разработчик Web-службы должен расширить этот интерфейс, описав в расширении Web-услуги реализуемой компонентом Web-службы. Разработчик не должен реализовать интерфейс каким- либо классом, реализацию делает EJB-контейнер. Соответствующий интерфейс локального клиента называется

Интерфейс EJBObject расширяет интерфейс Remote, а значит, описывает распределенный объект. Будем называть интерфейс EJBObject и всякое его расширение remote-интерфейсом session-компонента. Web-услуги, описанные в remote-интерфейсе, должны следовать правилам распределенных методов — выбрасывать исключение класса RemoteException и не иметь аргументов и возвращаемых значений, которые сами являются распределенными объектами.

Интерфейс EJBObject описывает пять методов, которые реализуются самим EJB-контейнером. Разработчику Web-службы можно не беспокоиться о реализации этих методов, но он может воспользоваться ими для получения сведений о компоненте.

Метод

public EJBHome getE JBHome () throws RemoteException

возвращает объект типа EJBHome — home-интерфейс, о котором речь пойдет чуть ниже.

Метод

public Handle getHandle () throws RemoteException

возвращает идентификатор компонента типа Handle. Идентификатор хранит ссылку на объект типа EJBObject, которую можно получить методом getEJBObject (). Необходимость в этом методе возникает тогда, когда компоненту надо сослаться на себя, поскольку использовать ссылку this в компонентах EJB нельзя.

Метод

public boolean isldentical (EJBObject obj)

throws RemoteException

заменяет обычный метод сравнения объектов equals о, тоже не используемый в распределенных объектах, из-за того, что они выполняются на разных виртуальных машинах Java.

Метод

public void remove 0 throws RemoteException, RemoveException

удаляет компонент. Последний, пятый, метод интерфейса public java.lang.Object getPrimaryKey() throws RemoteException

используется только в entity-компонентах для получения первичного ключа.

В remote-интерфейсе локального клиента EJBLocalobject четыре метода: отсутствует метод getHandle (), а метод

public EJBLocalHome getEJBLocalHome () throws EJBException возвращает ссылку на home-интерфейс локального клиента.

Home-интерфейс session-компонента

Еще один интерфейс — интерфейс типа EJBHome, тоже расширяющий интерфейс Remote — предназначен для создания экземпляров session- компонента по требованию клиента. Мы будем называть всякое расширение интерфейса EJBHome         Интерфейс EJBHome описывает че

тыре метода, реализуемые EJ В-контейнером. Разработчик Web-службы не должен беспокоиться об этих методах — они реализуются EJB-контейнером — но может воспользоваться ими для получения сведений о компоненте. Метод

public EJBMetaData getEJBMetaData()

throws RemoteException

возвращает объект типа EJBMetaData, из которого клиент может извлечь некоторые сведения о компоненте.

Метод

public HoneHandle getHomeHandle ()

throws RemoteException

возвращает объект типа HomeHandle, содержащий всего один метод getEJBHome о . Этот метод используется вместо ссылки this.

Два метода

public void remove (Handle handle) throws RemoteException, RemoveException

public void remove (Object pk) throws RemoteException, RemoveException

удаляют компонент, заданный идентификатором или первичным ключом. В home-интерфейсе локального клиента EJBLocalHome всего один метод public void remove(java.lang.Object primaryKey) throws

Разработчик Web-службы должен расширить интерфейс EJBHome, и/или интерфейс EJBLocalHome, если у компонента будут локальные клиенты, записав в расширении метод с именем create о без аргументов.

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

Интерфейс адресата Web-службы

У session-компонента без сохранения состояния могут быть не только удаленные и локальные клиенты, но и клиенты Web-службы. Для них session- компонент предоставляет не remote- и home-интерфейсы, а интерфейс адресата Web-службы (Web Service Endpoint Interface). Будем называть его WSEI-интерфейсом session-компонента.

В отличие от remote- и home-интерфейсов, WSEI-интерфейс расширяет непосредственно интерфейс Remote, то есть является распределенным объектом. Он включается в систему JAX-RPC, описанную в главе 6, и должен следовать правилам   этой системы. Это означает, что ти

пы аргументов и возвращаемых значений его методов должны быть типами JAX-RPC, а сами методы должны выбрасывать исключение класса RemoteException. В частности, нельзя использовать объекты типов EJBObject и EJBLocalObject. Разработчику компонента не надо реализовать WSEI-интерфейс, это сделает EJB-контейнер.

Для каждого метода WSEI-интерфейса в классе session-компонента должен присутствовать соответствующий метод с тем же заголовком. При установке компонента в EJB-контейнер, WSEI-интерфейс описывается в конфигурационном файле ear-jar.xml элементом <service-endpoint>, вложенном в элемент <session>, а также в WSDL-файле.

Приведем самый простой пример session-компонента, который только можно придумать. Клиент посылает session-компоненту свое имя name, используя для этого метод sayHelloO session-компонента. Компонент отвечает: "Привет,         добавляя имя клиента. Назовем этот компонент

Пусть у него будут только удаленные клиенты и клиенты Web- службы, но не будет локальных клиентов.

Сначала напишем remote-интерфейс, описывающий метод sayHello(). Он приведен в листинге 7.1.

; Листинг 7.1. Remote-интерфейс session-компонента

package hello;

import j ava.rmi.*;

import j avax.ejb.*;

public interface Hello extends EJBObject{

String                name) throws RemoteException;

}

Потом записываем home-интерфейс, описывающий метод create о, это сделано в листинге 7.2.

‘ Листинг 7.2. Home-интерфейс session-компонента

package hello;

import j ava. rmi. * ; import javax. ejb.*;

public interface HelloHome extends EJBHome{

Hello create () throws CreateException, RemoteException;

Напишем и WSEI-интерфейс session-компонента. Он приведен в листинге 7.3.

Листинг 7.3. WSEI-интерфейс session-компонента

package hello;

import j

public interface HelloPort extends Remote!

String sayHello(String name) throws RemoteException;

}

После этого пишем сам класс session-компонента. Это сделано в листинге 7.4.

| Листинг„7,4, Класс.                                                                                                      . . . – :

package hello;

import j ava. rmi . * ; import javax.ejb.*;

public class HelloBean implements SessionBean{ private SessionContext ctx:; public HelloBean о {}

public String sayHello(String name) throws RemoteException!

return "Привет, " + name + "!";

}

public void setSessionContext (SessionContext. ctx:) t this, ctx = ctx:;

}

public void ejbCreate (){}

public void ejbActivate(){}

public void

public void ejbRemove(){}

}

В листинге 7.4 сделана пустая реализация трех методов интерфейса SessionBean и реализован метод setSessionContext (). Обратите внимание на то, что в классе компонента EJB обязательно должен быть открытый (public) конструктор по умолчанию, хотя бы пустой. Еще один обязательный метод ejbCreate о соответствует методу create о home-интерфейса, не являясь его реализацией. В отличие от метода create о он не возвращает никакого значения и не выбрасывает исключений. В нем записываются начальные действия компонента, которые будут выполнены, когда клиент обращается К методу create () .

Обратите внимание на соглашение об именах, принятое для компонентов EJB. Создавая компонент HelloEJB, мы называем remote-интерфейс компонента именем Hello, home-интерфейс называем HelloHome, а класс компонента — Hello Bean.

Компонент создан, теперь его надо установить (deploy) в EJB-контейнер. При установке или до нее создается конфигурационный XML-файл с именем ear-jar.xml. Установка выполняется какой-либо утилитой, входящей в состав EJB-контейнера. В набор J2EE входит графическая утилита deploytool, запускаемая из командной строки. Работа с этой утилитой подробно описана в книге [10]. В процессе установки компонент регистрируется в системе именования JNDI [10], обычно в контексте java:comp/env/ejb/. Для клиентов Web-служб рекомендуется создавать контекст

Пусть наш session-компонент HelioEJB зарегистрирован под JNDl-именем hello. Тогда удаленный клиент может обратиться к нему так, как показано в листинге 7.5.

Листинг 7.5. Удаленный клиент session-компонента

package hello ;

import j avax. naming. * ; import j avax.rmi.*;

public class HelloClient{

public static void main (String [] args) {

try{

InitialContext ctx = new InitialContext () ;

HelioHome home = (HelloHome)PortableRemoteObject.narrow( ctx.lookup("java:comp/env/ejb/hello"), HeiioHome .class);

Hello h = home.create ();

System.out.println(h.sayHello("Иван"));

}catch(Exception e){ System.err.println(e);

1

}

}

Клиент Web-службы обращается к компоненту по обычным правилам системы JAX-RPC, изложенным в предыдущей главе 6.

Создавая session-компонент, EJB-контейнер сначала создает экземпляр класса компонента методом         о с помощью конструктора

по умолчанию, который обязательно должен присутствовать в классе компонента. Затем EJB-контейнер создает объект типа sessionContext и устанавливает его в компонент методом setsessionContextо . После этого EJB- контейнер        метод ejbCreate () .

Посмотрим, что может получить класс компонента от объекта SessionContext.

Контекст session-компонента

Интерфейс SessionContext предоставляет ссылки на remote-интерфейсы типа EJBObject и         методами

public EJBObject getEJBObject();

public EJBLocalObj ect getEJBLocalOb j ect () ;

Версия EJB 2.1 добавила еще один метод, доступный только для адресатов Web-служб:

public

Этот метод предоставляет объект типа MessageContext, содержащий свойства сообщения. Он описан в главе 6.

Кроме ТОГО, интерфейс SessionContext расширяет интерфейс EJBContext И,

следовательно, обладает его методами

public

public

public UserTrasaction public boolean public Principal

предоставляющими ссылки на home-интерфейсы, сведения о транзакции, в которой участвует компонент, и сведения о клиенте компонента.

Все эти сведения можно использовать в классе компонента.

Литература:

Хабибуллин И. Ш. Разработка Web-служб средствами Java. — СПб.: БХВ-Петербург, 2003. — 400 с: ил.

По теме:

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