@Inject, @EJB, @Local, @Remote, @LocalBean и т. Д....: запутался?

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

  • 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" просто позволяет напрямую вызывать реализацию как "локальный" EJB, но вы должны использовать реализацию в своем коде так:

    @Stateless @ Локальный открытый класс ServiceBImpl реализует ServiceBItf {@EJB private ServiceAImpl serviceA;...}

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

    @Stateless @ Локальный открытый класс ServiceBImpl реализует ServiceBItf {@EJB private ServiceAItf 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", когда это для локального вызова. Это приводит меня к следующему вопросу: в каком случае рекомендуется (или просто используется) вызов EJB "@Local"?

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

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

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

2 ответа

Как видите, я объявил аннотацию "@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

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

Другие вопросы по тегам