Главная » Spring » Проксирование  сеансовых компонентов (EJB 2.x) Spring

0

Как вы уже, вероятно, догадались из вступления, более простой путь действительно существует. В главе 11 было показано, как на- строить прокси-объекты для организации доступа к различным уда- ленным службам, включая службы, основанные на RMI, Hessian, Burlap и Spring HTTP Invoker. Практически те же самые возмож- ности предлагаются фреймворком Spring и для доступа к компо- нентам EJB.

В Spring имеются два фабричных компонента, производящих прокси-объекты, пригодные для работы с сеансовыми компонента- ми EJB:

# LocalStatelessSessionProxyFactoryBean – используется для доступа

к локальным компонентам EJB (находящимся в том же кон- тейнере, что и клиент);

# SimpleRemoteStatelessSessionProxyFactoryBean – используется для

доступа к удаленным компонентам EJB (находящимся в дру- гом контейнере, отличном от того, где располагается клиент).

Как показано на рис. 16.1, эти фабричные компоненты создают прокси-объекты, автоматически отыскивающие домашние интер-

Рис. 16.1. Фабричный компонент, производящий прокси-объекты для доступа к EJB,

автоматически отыскивает домашний интерфейс компонента и производит прокси-объект, делегирующий вызовы методов фактическому компоненту EJB

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

Для простоты демонстрации предположим, что компонент EJB службы управления дорожным движением является локальным сеансовым компонентом EJB. Чтобы внедрить его в Spring, можно воспользоваться компонентом LocalStatelessSessionProxyFactoryBean, как показано ниже:

<bean   id="trafficService" class="org.springframework.ejb.access.

➥  LocalStatelessSessionProxyFactoryBean"

lazy-init="true">

<property name="jndiName" value="ejb/TrafficService" />

<property name="businessInterface" value="com.roadrantz.ejb.TrafficServiceEjb"   />

</bean>

Свойство jndiName компонента trafficService в этом примере ис- пользуется для идентификации имени домашнего интерфейса EJB

в репозитории JNDI. А свойство businessInterface идентифицирует прикладной интерфейс компонента EJB. Этот интерфейс будет под- держиваться прокси-объектом.

Обратите особое внимание на атрибут lazy-init в элементе <bean>. Контекст приложения Spring обычно заранее создает экземпляры одиночных компонентов в момент загрузки конфигурационного файла Spring. В большинстве случаев это правильное решение, но при использовании прокси-объектов для доступа к EJB это может вызывать проблемы, из-за того что контекст приложения Spring может загрузить и создать прокси-объект еще до того, как будет получен домашний интерфейс компонента EJB. Определив атрибут lazy-init со значением true, мы сообщаем фреймворку Spring, что он не должен пытаться получить домашний интерфейс до первого обращения к компоненту trafficService.

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

<bean   id="trafficService" class="org.springframework.ejb.access.

➥    SimpleRemoteStatelessSessionProxyFactoryBean"

lazy-init="true">

<property name="jndiName" value="trafficService" />

<property name="businessInterface" value="com.roadrantz.ejb.TrafficServiceEjb"   />

</bean>

Видите разницу? Единственное, что изменилось, – имя клас- са фабричного компонента. Все остальное осталось, как и прежде. Фреймворк Spring делает выбор между локальными и удаленными компонентами EJB практически прозрачным.

Возможно, кого-то волнует вопрос обработки исключения java. rmi.RemoteException. Как выбор между локальными и удаленными компонентами EJB может быть полностью прозрачным, если вызов метода удаленного компонента EJB может возбудить исключение RemoteException? Разве не нужно где-то перехватить это исключение?

В этом заключается еще одно преимущество использования под- держки EJB в Spring для доступа к компонентам EJB. Как и при работе со службами на основе механизма RMI, любые исключения

RemoteException, которые могут возбуждаться компонентами EJB, бу- дут перехвачены и преобразованы в исключение org.springframework. remoting.RemoteAccessException. А поскольку исключение RemoteAccess- Exception является неконтролируемым, его можно не перехватывать.

Объявление прокси-объектов для EJB с помощью XML-элементов из пространства имен jee Фабричные компоненты из фреймворка Spring, используемые для

организации доступа к компонентам EJB, значительно упрощают ра-

боту с EJB и позволяют внедрять их в компоненты Spring, как если бы они были обычными компонентами Spring. Но можно ли еще более упростить жизнь?

Да, конечно! В версии Spring 2, в новом пространстве имен jee, появились конфигурационные элементы, еще более упрощающие на- стройку компонентов EJB. Пространство имен jee включает два кон- фигурационных элемента, специализирующихся на настройке EJB:

# <jee:local-slsb> – настраивает прокси-объект для локального

сеансового компонента EJB в контексте приложения Spring;

#  <jee:remote-slsb>  – настраивает прокси-объект для удаленного сеансового компонента EJB в контексте приложения Spring.

Чтобы воспользоваться этими двумя элементами, необходимо добавить объявление пространства имен jee в конфигурационный файл Spring, включив следующий элемент <beans>:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">

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

<jee:local-slsb>, как показано ниже:

<jee:local-slsb    id="trafficService" jndi-name="trafficService"

business-interface="com.roadrantz.ejb.TrafficServiceEjb"/>

За кулисами элемент <jee:local-slsb> автоматически настроит компонент LocalStatelessSessionProxyFactoryBean в контексте Spring. Конечный результат будет тем же, а объем разметки XML – меньше.

Аналогично, с помощью элемента <jee:remoteslsb>, можно внед- рить удаленный сеансовый компонент EJB:

<jee:remote-slsb  id="trafficService" jndi-name="trafficService"

business-interface="com.roadrantz.ejb.TrafficServiceEjb"/>

Как элемент <jee:local-slsb> является более краткой формой настройки компонента LocalStatelessSessionProxyFactoryBean, так и

<jee:remote-slsb> является более краткой формой настройки компо- нента   SimpleRemoteStatelessSessionProxyFactoryBean.

Объявление сеансовых компонентов EJB 3 в Spring Как упоминалось выше, спецификация EJB 3 упрощает процесс получения ссылки на компоненты, избавляя от необходимости при- обретать их домашние интерфейсы. Вместо получения ссылки на сеансовый компонент посредством его домашнего интерфейса, из- влекаемого из JNDI, ссылки на сеансовые компоненты EJB 3 из-

влекаются из JNDI непосредственно.

Но, как вы уже видели, реализация поиска компонентов в JNDI выглядит достаточно сложно и по большей части является шаблон- ной. Кроме того, организация извлечения EJB из репозитория идет вразрез с принципом внедрения зависимостей, которому следует фреймворк Spring. В Spring сеансовые компоненты должны внед- ряться, а не извлекаться.

К счастью, фреймворк Spring предоставляет возможность внедре- ния объектов, хранящихся в JNDI, как любых других компонентов, имеющихся в контексте приложения. Вся хитрость заключается в ис- пользовании компонента JndiObjectFactoryBean из фреймворка Spring. Следующий фрагмент конфигурационного XML-файла демонстри- рует объявление сеансового компонента EJB 3 службы управления движением:

<bean   id="trafficService" class="org.springframework.jndi.JndiObjectFactoryBean">

<property name="jndiName" value="ejb/TrafficService" />

<property  name="resourceRef"  value="true"  />

</bean>

Будучи фабричным компонентом, JndiObjectFactoryBean производит прокси-объект, обеспечивающий доступ к фактическому сеансовому компоненту (как показано на рис. 16.2), поиск которого выполня- ется в репозитории JNDI по имени, указанному в свойстве jndiName. Свойство resourceRef указывает, что компонент EJB должен извле- каться как Java-ресурс, вследствие чего перед выполнением поиска к значению свойства jndiName будет добавлен префикс java:comp/env/.

Рис. 16.2. Сеансовые компоненты EJB 3 можно также настраивать с использованием прокси-объектов для доступа к JNDI

При использовании пространства имен jee компонент EJB можно также объявить с помощью элемента <jee:jndi-lookup>:

<jee:jndi-lookup  id="trafficService" jndi-name="ejb/TrafficService" resource-ref="true"  />

Этот фрагмент эквивалентен объявлению <bean> выше. За кулисами элемент <jee:jndi-lookup> создает компонент JndiObjectFactoryBean. По- дробнее об элементе <jee:jndi-lookup> будет рассказываться в главе 17. А пока достаточно знать, что JndiObjectFactoryBean создает прокси-объ- ект для доступа к сеансовым компонентам, хранящимся в JNDI.

Теперь, после объявления прокси-объекта для доступа к сеансо- вому компоненту, можно включить его в работу. Посмотрим, как внедрить EJB в POJO, сконфигурированный в Spring.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

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