JEE7: Поддерживают ли EJB и CDI beans транзакции, управляемые контейнером?
Java EE7 состоит из набора определений < bean:
- Управляемый Beans 1.0 (JSR-316/JSR-250)
- Injection Dependency для Java 1.0 (JSR-330)
- CDI 1.1 (JSR-346)
- Управляемый JSF Beans 2.2 (JSR-344)
- EJB 3.2 (JSR-345)
Чтобы избавиться от хаоса в моем сознании, я изучаю несколько статей "когда использовать тип bean". Один из плюсов для EJB кажется, что они одни поддерживают декларативные транзакции, управляемые контейнером (известные аннотации транзакций). Я не уверен, хотя, если это правильно. Кто-нибудь может это одобрить?
Между тем, я придумал простое демонстрационное приложение, чтобы проверить, действительно ли это так. Я просто определил CDI bean ( не EJB - он не имеет аннотаций уровня класса), как показано ниже, на основе этого фрагмента:
public class CdiBean {
@Resource
TransactionSynchronizationRegistry tsr;
@Transactional(Transactional.TxType.REQUIRED)
public boolean isTransactional() {
return tsr.getTransactionStatus() == Status.STATUS_ACTIVE;
}
}
Теперь результат GlassFish 4.0 заключается в том, что этот метод действительно возвращает true, что, согласно моим запросам, не работает как ожидалось. Я ожидал, что контейнер проигнорирует аннотацию @Transactional по методу CDI bean или даже выбросит исключение. Я использую недавно установленный сервер GlassFish 4, поэтому никаких помех нет.
Итак, мой вопрос действительно:
- Какие типы bean действительно поддерживают транзакции, управляемые контейнером?
- Просто ради любопытства, как я могу проверить его с помощью простого демонстрационного приложения, если неправильный код?
(BTW: Кто-то описал подобную проблему здесь, но ее решение не относится к моему делу.
Ответы
Ответ 1
Пока Java EE 7 только EJB не был транзакционным, а аннотация @Transactional
не существовала.
Так как Java EE 7 и JTA 1.2 вы можете использовать транзакционный перехватчик в CDI с аннотацией @Transactional
.
Чтобы ответить на ваш вопрос о наилучшем типе bean для использования, ответом является CDI по умолчанию.
CDI beans легче EJB и поддерживают множество функций (включая EJB) и активируются по умолчанию (при добавлении файла beans.xml
к вашему приложению).
Поскольку Java EE 6 @Inject
заменяет @EJB
. Даже если вы используете удаленные EJB (функция, не существующая в CDI), лучшая практика предполагает, что вы @EJB
один раз, чтобы ввести удаленный EJB и производителя CDI, чтобы выставить его как CDI bean
public class Resources {
@EJB
@Produces
MyRemoteEJB ejb;
}
То же самое предлагается для ресурсов Java EE
public class Resources2 {
@PersistenceContext
@Produces
EntityManager em;
}
Эти производители будут использоваться позже
public class MyBean {
@Inject
MyRemoteEJB bean;
@Inject
EntityManager em;
}
EJB продолжает иметь смысл для определенных сервисов, которые они включают в себя как JMS или асинхронное лечение, но вы будете использовать их как CDI bean.
Ответ 2
javadoc Transactional говорит:
Аннотации javax.transaction.Transactional предоставляют приложению возможность декларативно контролировать границы транзакций на управляемом CDI beans, а также классы, определенные как управляемые beans по спецификации Java EE, как на уровне класса, так и на уровне метода где аннотации уровня метода переопределяют те, которые находятся на уровне класса.
Итак, ваши предположения ошибочны. EJB до Java EE 6 были единственными компонентами поддержки декларативных транзакций. Транзакционная аннотация точно была введена в Java EE 7, чтобы сделать транзакцию не EJB, управляемого CDI beans.