Статьи

Введение в EJB 3.0 Инъекция и поиск

Вступление

В спецификации Enterprise JavaBeans v. 3.0 представлен упрощенный API на основе аннотаций для внедрения и поиска EJB. EJB 3.0 теперь являются POJO и могут вводиться в другие компоненты (такие как EJB и сервлеты) с помощью простых аннотаций. EJB 3.0 — это одна из многих других спецификаций, основанных на POJO, которые сделали ее для Java EE 6, например, JSR-229 «Контексты и внедрение зависимостей для платформы Java EE» (ранее известная как «Web Beans»). Java EE еще никогда не была такой простой!

Тем не менее, хотя аннотации EJB 3.0 скрывают от программиста сложности сборки приложения Java EE и подключения всех его компонентов, есть некоторые тонкости, о которых вам следует знать. Некоторые из них, такие как «глобальные имена JNDI», были рассмотрены в спецификации Enterprise JavaBeans v. 3.1 . Между тем, пока серверы приложений Java EE 6 не будут широко развернуты, вы можете подвергаться риску написания кода, который зависит от поведения непереносимого сервера приложений.

Что еще хуже, некоторые из проблем, с которыми вы можете столкнуться, проявляются при использовании локального интерфейса EJB, который, предположительно, является интерфейсом прикладного объекта в области приложения. Поскольку локальные бизнес-интерфейсы фактически подразумевают локальный вызов метода (они используют семантику передачи по ссылке и ограничены одним и тем же экземпляром JVM), такие интерфейсы являются предпочтительным выбором при доступе к бизнес-интерфейсам компонентов в вашем приложении. Часто этот вариант использования будет составлять большинство вызовов EJB в вашем приложении Java EE.

Объявление EJB

Согласно EJB v. 3.0 Упрощенная Спецификация API, при объявлении сессионного компонента вы можете использовать две аннотации, в зависимости от типа сессионного компонента:

  • @Stateless
  • @Stateful

Обе аннотации имеют два общих элемента аннотации: name и mappedName .

название

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

mappedName

Спецификация EJB 3.0 определяет mappedName как «специфичное для продукта имя, которому должен быть сопоставлен сессионный компонент». Часто сервер приложений использует mappedName для сопоставления сессионного компонента с глобальным именем JNDI. Спецификация EJB 3.1 не поддерживает элемент mappedName и вводит понятие «переносимое глобальное имя JNDI».

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

EJB Отзывы

Чтобы установить ссылку на EJB, вы можете использовать аннотацию @EJB или стандартные дескрипторы развертывания (через <ejb-ref /> и <ejb-local-ref />). Аннотация @EJB определяется следующим образом:

1
2
3
4
5
6
7
8
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface EJB {
  String name() default "";
  Class beanInterface() default Object.class;
  String beanName() default "";
  String mappedName() default "";
  String description() default "";
}

название

Элемент name определяет введенное имя EJB «в среде приложения». Таким образом, имя EJB — это местоположение внедренного объекта в закрытом пространстве имен java: comp / env . Его значение по умолчанию — это полное имя аннотированного поля класса или свойства. Когда аннотация @EJB используется на уровне класса, элемент name является обязательным.

Элемент name является эквивалентом элемента <ejb-ref-name /> в дескрипторе развертывания:

1
2
3
4
<ejb-ref>
  <ejb-ref-name>bean name</ejb-ref-name>
  [...]
</ejb-ref>

beanInterface

BeanInterface — это тип бизнес-интерфейса внедренного компонента. По умолчанию это тип аннотированного поля или свойства. Когда аннотация @EJB используется на уровне класса, элемент beanInterface является обязательным.

Элемент beanInterface является эквивалентом элементов <remote /> или <local /> в дескрипторе развертывания:

1
2
3
4
5
<ejb-ref>
  <ejb-ref-name>bean name</ejb-ref-name>
  <remote>bean interface</remote>
  [...]
</ejb-ref>

beanName

Элемент beanName определяет «имя» bean-компонента, объявленное в аннотациях @Stateful и @Stateless через элемент name или в дескрипторе развертывания через элемент <ejb-name />. Элемент beanName наиболее полезен, когда более одного EJB-компонента реализуют один и тот же бизнес-интерфейс в приложении: beanName позволяет разработчику ссылаться на конкретный EJB-компонент в определенном модуле. Синтаксис для использования в этом случае:

1
<ejb module>#<ejb name>

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

Элемент beanName является эквивалентом элемента <ejb-link /> в дескрипторе развертывания:

1
2
3
4
5
6
<ejb-ref>
  <ejb-ref-name>bean name</ejb-ref-name>
  <remote>bean interface</remote>
  <ejb-link>linked ejb</ejb-link>
  [...]
</ejb-ref>

mappedName

Как и в случае элемента mappedName аннотаций @Stateless и @Stateful , mappedName является метаданными для конкретного продукта, использование которых не переносимо.

Элемент mappedName является эквивалентом элемента <mapped-name /> в дескрипторе развертывания:

1
2
3
4
5
6
7
<ejb-ref>
  <ejb-ref-name>bean name</ejb-ref-name>
  <remote>bean interface</remote>
  <ejb-link>linked ejb</ejb-link>
  <mapped-name>mapped name</mapped-name>
  [...]
</ejb-ref>

А как насчет бобов в других приложениях?

Если вы рассмотрите механизмы, описанные до сих пор, вы должны заметить, что не существует (переносимого) способа объявить зависимость (ссылку на EJB) бобу за пределами приложения. Спецификация EJB v. 3.1 решает эту проблему и определяет переносимые глобальные имена JNDI . Никаких изменений не потребуется, чтобы совместимому EJB v. 3.0 было присвоено переносимое глобальное имя JNDI в совместимом контейнере EJB v. 3.1.

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

Не полагайтесь на непереносимые глобальные имена JNDI для поиска EJB

Как описано в предыдущих разделах, до EJB v. 3.1 не было никакого портативного способа поиска EJB с глобальным именем JNDI, и развертыватель должен полагаться на специальные инструменты и метаданные сервера приложений для установления связи между ссылкой EJB и EJB. глобальное имя JNDI. Более того, такая ссылка необходима при создании ссылки на bean-компонент вне вашего приложения.

Даже если будет уместно избегать использования элементов аннотации @EJB (или их соответствующих элементов дескриптора развертывания) и использовать вместо этого глобальные имена JNDI, вы всегда должны полагаться на ссылки EJB и поиск в своем частном пространстве имен java: comp / env . Ваше личное пространство имен и механизм отображения предоставляют вам уровень косвенности, который изолирует ваш код от изменений конфигурации.

Это также означает, что, если вы ограничены EJB v. 3.0, вы всегда должны использовать механизм beanName (<ejb-link />) и выполнять поиск в своем личном пространстве имен java: comp / env . Много раз я слышал историю о том, как какой-то разработчик проверял глобальное дерево JNDI сервера приложений, чтобы определить глобальную схему именования JNDI сервера приложений для EJB, а затем испытывал некоторую исключительную ситуацию NamingException здесь и там. По этой причине избегайте использования элемента @EJB mappedName и используйте вместо него name и beanName.

Например, некоторые серверы приложений публикуют как удаленные, так и локальные бизнес-интерфейсы EJB с глобальными именами JNDI. Другие просто нет. Oracle WebLogic является одним из последних. Спецификация EJB v. 3.0, действительно, не требует наличия локального бизнес-интерфейса в глобальном дереве JNDI.

Поиск удаленных и локальных бизнес-интерфейсов

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

Ссылки на локальные интерфейсы EJB всегда могут быть разрешены с помощью механизма beanName . Это не всегда так для ссылок на удаленные интерфейсы, так как такой EJB может находиться за пределами вашего приложения. Вот еще одна причина не полагаться на глобальные имена JNDI в вашем коде: не только такой код будет непереносимым, но и потребует от вас использовать разные стратегии для поиска удаленных и локальных бизнес-интерфейсов (в зависимости от сервера приложений. ) Тип бизнес-интерфейса не будет прозрачным, и изменение типа бизнес-интерфейса может нарушить ваш код.

Простой шаблон для создания ссылок EJB

Хотя они могут быть необходимы в некоторых сценариях, избегайте поиска в EJB и полагайтесь на ссылки @EJB «автоматическое подключение». Соблюдение некоторых простых шаблонов гарантирует, что ваши ссылки на EJB будут объявлены и удовлетворены полностью автоматически:

  • Попробуйте уменьшить количество EJB-компонентов, совместно использующих бизнес-интерфейсы : если только один EJB-компонент реализует определенный бизнес-интерфейс в приложении, ссылка на EJB может быть автоматически объявлена ​​и связана с аннотацией @EJB по умолчанию.
  • Если совместное использование бизнес-интерфейсов улучшает дизайн вашего приложения, определите четкую политику именования для bean-компонентов вашего приложения и избегайте дублирования : если есть только один bean-компонент с определенным именем, ссылка на EJB может быть автоматически объявлена ​​и подключена с помощью @EJB (beanName = » [имя] ») аннотация. Если существует более одного компонента с одним и тем же именем, вы будете вынуждены использовать синтаксис @EJB (beanName = ”[ejb-module-path] # [ejb-name]») при объявлении ссылок.
  • Если вам нужно программно искать ссылки на EJB, объявите расположение ваших EJB в локальном пространстве имен, используя элемент имени @EJB (или элемент <ejb-ref-name />), и свяжите его с целевым EJB с помощью @EJB beanName. элемент (или элемент <ejb-link />.)

Ссылка: Введение в EJB 3.0 Injection and Lookup от нашего партнера JCG Грея из The Grey Blog .

Статьи по Теме :