Где использовать EJB 3.1 и CDI?

Я делаю продукт на основе Java EE, в котором я использую GlassFish 3 и EJB 3.1.

В моем приложении есть сеанс beans, планировщик и использует веб-службы. Недавно я узнал об Apache TomEE, который поддерживает CDI. Контейнер GlassFish также поддерживает CDI.

Можно ли заменить сеанс beans, где мне не нужна функция, которую CDI также не предоставляет? И если тогда, какие преимущества я могу получить?

Ответы

Ответ 1

Да, вы можете свободно смешивать CDI и EJB и добиваться отличных результатов. Похоже, вы используете @WebService и @Schedule, что является веским основанием для добавления EJB в микс.

Там много путаницы, так что вот некоторые общие сведения о EJB и CDI, поскольку они связаны друг с другом.

EJB >= CDI

Обратите внимание, что EJB являются CDI beans и поэтому имеют все преимущества CDI. Обратное неверно (пока). Так что определенно не привыкните думать "EJB против CDI", поскольку эта логика действительно переводит на "EJB + CDI против CDI", что является нечетным уравнением.

В будущих версиях Java EE мы продолжим их выравнивание. Какие средства выравнивания позволяют людям делать то, что они уже могут делать, просто без аннотации @Stateful, @Stateless или @Singleton вверху.

EJB и CDI в условиях реализации

В конечном счете, EJB и CDI имеют одну и ту же основную схему прокси-компонентов. Когда вы получаете ссылку на EJB или CDI bean, это не реальный bean. Скорее объект, которому вы даны, является подделкой (прокси). Когда вы вызываете метод на этом поддельном объекте, вызов переходит в контейнер, который отправит вызов через перехватчики, декораторы и т.д., А также позаботится о любых транзакциях или проверках безопасности. Как только все это будет сделано, вызов, наконец, перейдет к реальному объекту, и результат будет передан обратно через прокси для вызывающего.

Разница заключается только в том, как разрешается вызов объекта. "Разрешено" мы просто имеем в виду, где и как контейнер ищет экземпляр реального экземпляра.

В CDI контейнер выглядит "областью", которая будет в основном представлять собой хэш-карту, которая живет в течение определенного периода времени (по запросу @RequestScoped, за HTTP-сеанс @SessionScoped, за приложение @ApplicationScoped, разговора JSF @ConversationScoped, или для вашей собственной реализации области видимости).

В EJB контейнер также смотрит на хэш-карту, если bean имеет тип @Stateful. @Stateful bean также может использовать любую из вышеупомянутых аннотаций области, заставляя его жить и умирать со всеми остальными beans в области. В EJB @Stateful есть, по существу, "любая область действия" bean. @Stateless - это в основном пул экземпляров - вы получаете экземпляр из пула в течение одного вызова. @Singleton по существу @ApplicationScoped

Итак, на фундаментальном уровне все, что вы можете сделать с помощью "EJB" bean, вы должны иметь возможность сделать с "CDI" bean. Под обложками ужасно сложно рассказать им обособленно. Все сантехника одинакова, за исключением того, как разрешены экземпляры.

В настоящее время они не совпадают с услугами, которые контейнер предложит при выполнении этого проксирования, но, как я уже сказал, мы работаем над этим на уровне спецификации Java EE.

Замечание по производительности

Не обращайте внимания на любые "легкие" или "тяжелые" ментальные образы, которые у вас могут быть. Это весь маркетинг. У них такой же внутренний дизайн по большей части. Реализация экземпляра CDI, возможно, немного сложнее, потому что она немного более динамична и контекстуальна. Разрешение экземпляра EJB довольно простое, немое и простое сравнение.

Я могу рассказать вам с точки зрения реализации в TomEE, там около нулевой разницы в производительности между вызовом EJB и вызовом CDI bean.

По умолчанию POJO, затем CDI, затем EJB

Конечно, не используйте CDI или EJB, когда нет никакой пользы. Бросьте CDI, когда вы начинаете хотеть инъекции, события, перехватчики, декораторы, отслеживание жизненного цикла и тому подобное. Это самое время.

Помимо этих основ, существует множество полезных контейнерных сервисов, которые вы можете использовать только в том случае, если вы сделаете свой CDI bean также EJB, добавив в него @Stateful, @Stateless или @Singleton.

Вот краткий список, когда я вырываю EJB.

Использование JAX-WS

Воздействие JAX-WS @WebService. Мне лень. Когда @WebService также является EJB, вам не нужно перечислить его и сопоставить его как сервлет в файле web.xml. Это работает для меня. Плюс я получаю возможность использовать любую из других функций, упомянутых ниже. Поэтому для меня это не проблема.

Доступно только для @Stateless и @Singleton.

Использование JAX-RS

Предоставление ресурса JAX-RS через @Path. Я все еще ленив. Когда служба RESTful также является EJB, вы снова получаете автоматическое обнаружение и не должны добавлять ее в подкласс JAX-RS Application или что-то в этом роде. Плюс я могу показать тот же самый bean как @WebService, если я хочу или использовать любую из замечательных функций, упомянутых ниже.

Доступно только для @Stateless и @Singleton.

Логика запуска

Загрузка при запуске через @Startup. В настоящее время в CDI нет эквивалента. Как-то мы пропустили добавление чего-то типа события AfterStartup в жизненный цикл контейнера. Если бы мы это сделали, у вас просто мог бы быть @ApplicationScoped bean, который слушал его, и это было бы фактически так же, как @Singleton с @Startup. Это в списке для CDI 1.1.

Доступно только для @Singleton.

Работа в параллельном режиме

@Asynchronous вызов метода. Начальные потоки - это не-no в любой серверной среде. Слишком много потоков - серьезный убийца. Эта аннотация позволяет вам распараллелить все, что вы делаете, используя пул потоков контейнера. Это круто.

Доступно для @Stateful, @Stateless и @Singleton.

Планирование работы

@Schedule или ScheduleExpression - это в основном функциональность cron или Quartz. Также очень классно. В большинстве контейнеров для этого используется кварц. Однако большинство людей не знает, что планирование работы в Java EE является транзакционным! Если вы обновляете базу данных, тогда планируете какую-то работу, и один из них не работает, оба будут автоматически очищены. Если вызов EntityManager persist завершается с ошибкой или возникает проблема очистки, нет необходимости расфанировать работу. Yay, транзакции.

Доступно только для @Stateless и @Singleton.

Использование EntityManager в транзакции JTA

В приведенной выше заметке о транзакциях, конечно же, необходимо использовать JTA EntityManager. Вы можете использовать их с простым "CDI", но без транзакций, управляемых контейнером, он может получить действительно монотонное дублирование логики фиксации/отката UserTransaction.

Доступно для всех компонентов Java EE, включая CDI, JSF @ManagedBean, @WebServlet, @WebListener, @WebFilter и т.д. Тем не менее аннотация @TransactionAttribute доступна для @Stateful, @Stateless и @Singleton.

Сохранение JTA EntityManager

Управляемый EXTENDED EntityManager позволяет вам поддерживать EntityManager между транзакциями JTA и не потерять кешированные данные. Хорошая функция для правильного времени и места. Используйте ответственно:)

Доступно только для @Stateful.

Простая синхронизация

Когда вам нужна синхронизация, аннотации @Lock(READ) и @Lock(WRITE) довольно хороши. Это позволяет вам получить бесплатное управление доступом. Пропустите всю водопроводную систему ReentrantReadWriteLock. В том же ведре @AccessTimeout, который позволяет вам сказать, сколько времени должен ждать поток, чтобы получить доступ к экземпляру bean перед тем, как сдаться.

Доступно только для @Singleton beans.

Ответ 2

если вы действительно не используете какие-либо функции ejb 3.1, ответ прост. но угадайте, что ваше задание указывает, что вы подозреваете, что есть концепции ejb 3.1, от которых вы извлекаете выгоду, не зная о них. одним из примеров может быть то, что контейнер может поддерживать пул slsb, готовый к использованию, так что jms и соединения с базой данных не должны вводиться как часть запроса