@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, такие как обработка транзакций, пул, пассивация и кластеризация.
Это дает ответ на ваш вопрос в трех частях:
- Используйте @Inject поверх @EJB, концепция CDI (a) работает для всех управляемых bean-компонентов (включая EJB) и (b) является отслеживающей состояние и поэтому намного превосходит чистую @EJB DI
- Вы уверены, что вам нужны EJB для ваших компонентов?
- Стоит взглянуть на документацию CDI
@Inject
аннотация используется для Java-бобов (POJO), в то время как @EJB
аннотация используется для корпоративных Java-бинов. Когда контейнер вводит ejb, предоставленный @EJB
аннотация к другому bean-компоненту, он также управляет жизненным циклом ejb, выполняет пул для bean-компонентов без состояния и т. д. (когда bean-компонент, который будет внедрен, не развернут, ссылка будет нулевой). Если вы используете @Inject
Механизм аннотации CDI просто находит и создает экземпляр внедренного ресурса, например, с оператором new (если реализации интерфейса, который будет внедрен, не существует, ссылка будет нулевой). Вы можете использовать классификаторы с @Inject
аннотация для выбора другой реализации внедренного интерфейса.