@Inject, @EJB, @Local, @Remote, @LocalBean и т. Д. ...: запутался? - PullRequest
36 голосов
/ 09 сентября 2011

У меня есть следующая конфигурация:

  • 1 EAR на одном GF, содержащем 2 EJB-JAR с компонентами EJB.
  • 1 WAR на другом сервере Glassfish ( => другая JVM ), содержащем веб-компоненты, обращающиеся к компонентам EJB.

У меня есть 2 бизнес-службы EJB в каждом EJB-JAR моего EAR, и все они разрабатываются следующим образом:

@Remote
public interface ServiceAItf {
    ...
}

@Stateless
@Local
public class ServiceAImpl implements ServiceAItf {
    ...
}

В моей WAR я обращаюсь к компонентам EJB через явный "InitialContext.lookup" на удаленном интерфейсе.

В моем EAR я не совсем понимаю, как лучше внедрять инъекцию с точки зрения производительности, архитектуры и т. Д. *

У меня есть следующие вопросы:

  • Как вы можете видеть, я объявил аннотацию "@ Local" для реализации службы без определения локального интерфейса. Это правильно? По крайней мере, у меня нет ошибки при развертывании. Но, возможно, мне лучше использовать аннотацию "@ LocalBean" ? Я предполагаю, что аннотация "@ LocalBean" просто позволяет напрямую вызывать реализацию как "Local" EJB, но вы должны использовать реализацию в своем коде так:

    @ Stateless @Местный открытый класс ServiceBImpl реализует ServiceBItf { @EJB частный сервис AImpl serviceA; ... }

  • Как лучше всего внедрить один EJB в другой? Это работает так:

    @ Stateless @Местный открытый класс ServiceBImpl реализует ServiceBItf { @EJB частный сервис AItf serviceA; ... }

Но из того, что я заметил, «serviceA» - это удаленный прокси-сервер, находящийся в той же JVM в том же файле EAR. Поэтому я предполагаю, что это повлияет на производительность. Вот почему я попытался внедрить услугу так:

@Stateless
@Local
public class ServiceBImpl implements ServiceBItf {
    @Inject
    private ServiceAItf serviceA;
    ...
}

Но в GF это не работает, у меня есть следующее исключение:

WELD-001408 Unsatisfied dependencies for type [...] ...

Затем я попытался создать локальный интерфейс, и внедрение через аннотацию "@Inject" работает, когда обе службы

Даже если я создаю подобный локальный интерфейс, сервис не внедряется через аннотацию "@ Inject" , но имеет значение null:

@Local
public interface ServiceALocalItf {
    ...
}

Я прочитал много статей, в которых настоятельно рекомендуется использовать "@ Inject" вместо "@ EJB" , когда это для локального вызова. Это приводит меня к следующему вопросу: в каком случае рекомендуется (или просто используется) вызов "@ Local" EJB?

После всего этого анализа я прихожу к следующему выводу:

  • Для каждой службы я создаю "@ Local" и "@ Remote" интерфейс.
  • От WAR до EJB-JAR EAR выполните поиск JNDI для удаленного интерфейса.
  • Из EJB-JAR в EJB-JAR выполнить инъекцию через "@ EJB" в локальный интерфейс.
  • Для двух служб в одном и том же EJB-JAR сделайте инъекцию через "@Inject" в локальный интерфейс.

Что вы думаете об этом? Это правильно?

Ответы [ 2 ]

22 голосов
/ 10 сентября 2011

Как видите, я объявил аннотацию "@Local" для реализации службы без определения локального интерфейса.Это правильно?

В EJB 3.1 требование к локальным интерфейсам было отброшено.Не нужно писать их, если они вам явно не нужны.

Каков наилучший способ внедрения одного EJB-компонента в другой?

Несколько вещей, чтобы написать здесь:

В Java EE 6 Java Enterprise изменилась.Новый JSR определяет так называемый управляемый компонент (не путайте с управляемыми компонентами JSF) как своего рода минимальный компонент, который все еще может извлечь выгоду из контейнера с точки зрения внедрения зависимостей и управления жизненным циклом.Это означает: если у вас есть компонент и вы просто хотите использовать DI и позволить контейнеру управлять его жизненным циклом, вам не нужно , чтобы использовать для него EJB.В конечном итоге вы будете использовать EJB, если - и только если - вам явно понадобятся функции EJB, такие как обработка транзакций, пул, пассивация и кластеризация.

Таким образом, ответ на ваш вопрос состоит из трех частей:

  1. Использование @Inject поверх @EJB, концепция CDI (a) работает для всех управляемых bean-компонентов (включая EJB-компоненты).) и (b) с состоянием и поэтому намного превосходят чистые @EJB DI
  2. Вы уверены, что вам нужны EJB для ваших компонентов?
  3. Определенно стоит взглянуть на документацию CDI
0 голосов
/ 09 сентября 2011

@Inject аннотация используется для Java-бинов (POJO), в то время как @EJB аннотация используется для корпоративных Java-бинов.Когда контейнер внедряет ejb, предоставленный аннотацией @EJB, в другой bean-компонент, он также контролирует жизненный цикл этого ejb, выполняет пул для bean-компонентов без сохранения состояния и т. Д. (Когда bean-компонент, который будет внедрен, не развернут, ссылка будет нулевой).Если вы используете механизм @Inject аннотации CDI, просто найдите и создайте экземпляр внедренного ресурса, например, с оператором new (если реализация интерфейса, которая будет внедрена, не существует, ссылка будет нулевой).Вы можете использовать квалификаторы с аннотацией @Inject для выбора другой реализации внедренного интерфейса.

...