Почему EJB-компоненты с транзакциями, управляемыми компонентами, действуют как "барьер транзакций"?
Цитата из спецификации EJB 3.1:
13.6.1. Разграничение управляемых компонентом транзакций
Контейнер должен управлять вызовами клиента для экземпляра корпоративного компонента с разграничением транзакций, управляемых компонентом, следующим образом. Когда клиент вызывает бизнес-метод через одно из представлений клиента корпоративного компонента, контейнер приостанавливает любую транзакцию, которая может быть связана с запросом клиента.
С другой стороны, транзакция из автономного клиента или другого EJB-компонента распространяется в bean-компонент с использованием управляемых контейнером транзакций. Глядя на это с точки зрения CMT, кажется, что бины, использующие CMT, имеют еще одну важную особенность (распространение транзакций).
Какова причина того, что это ограничение ("транзакционный барьер") накладывается на компоненты, использующие BMT?
Смежные вопросы:
4 ответа
Мое "предположение" будет таким
Контейнер "видит", что вы пометили бин как BMT
так что в какой-то момент вы, вероятно, будете использовать объект UserTransaction и его методы begin/commit/rollback и т. д.
А так как действительно вложенные транзакции не поддерживаются weblogic / oracle и т. Д. Контейнеру ничего не остается, кроме как приостановить текущую транзакцию, чтобы иметь возможность поддерживать новую.
В случае CMT - поскольку вы используете Required или RequiredNew - контейнер "знает" ваше намерение и решает продолжить ту же транзакцию, либо соответственно приостановить и начать новую.
Я согласен с ответом Kalpesh Soni
просто я хотел бы добавить немного больше.
Контейнер использует один и тот же поток для выполнения одного вызова EJB. Поток может быть связан только с одной глобальной транзакцией, управляемой TM. Вот почему @Asynchronous
вызов bean не передает транзакцию (спецификация EJB 3.2, транзакции 4.5.3). Транзакция не может быть разделена на несколько потоков, и она связана с вызывающей стороной.
Если bean-компонент помечен как CMT, контейнер управляет созданием транзакции на основе аннотации или информации, взятой из ejb-jar.xml
дескриптор. Затем контейнер может решить, будет ли вызов метода bean-компонента частью текущей запущенной транзакции или необходимо создать новую. Как уже упоминалось, вложенные транзакции не поддерживаются в большинстве контейнеров Java EE. Насколько я понимаю, основная причина в том, что XAResource не поддерживает вложенные транзакции (см. Спецификацию JTA).
BMT использует бин UserTransaction
управлять управлением транзакциями самостоятельно. Каким образом должно работать распространение существующей транзакции на BMT или лучше, чем вы могли бы с ней потом? Если вы хотите начать новую транзакцию с UserTransaction.begin()
тогда текущий запущенный будет приостановлен. Вот как сейчас работает распространение. Я имею в виду, что транзакция не распространяется, а приостанавливается при вызове bean-компонента BMT Другая вещь, которую вы могли бы сделать, это управлять транзакцией. Это значит использовать UserTransaction.commit()
или же UserTransaction.rollback()
на входящую транзакцию. Если вы сделаете это, то вызывающий по возвращении будет работать без активной транзакции в его контексте. Это означает, что вызов другого компонента может работать с вашей транзакцией без вас, как об этом знает вызывающий абонент, и получает уведомление об этом. Я думаю, что вы не хотите, чтобы это было возможно. Это мое понимание причин.
В BMT есть еще одна забавная вещь. Если вы используете SLSB (Session Bean-компонент без сохранения состояния), вам не разрешается выходить из вызванного метода без завершения транзакции (см. EJB 3.2: 8.3.3 Enterprise Bean-компоненты, использующие разграничение транзакций, управляемых компонентом). С другой стороны, SFSB (Stateful Session Bean) может выйти из метода без завершения транзакции, что может быть завершено при другом вызове. Если такой вызов происходит, например, в другом сеансе HTTP, транзакция приостанавливается и берется из текущего потока, а затем активируется и закрепляется в новом потоке.
javax / транзакция /xa/XAResource.html "API XAResource Java EE 7"
Я сделал небольшой поиск по этому вопросу, суть в том, что - как то, что @kalpesh Soni сказал выше - Container knows exactly what It's doing to propagate the transaction, but leaving it to you, It's expected that you might create a scenario that causes problems due to the details of the underlying server that you use direclty
... В этой ссылке автор описывает определенный сценарий, который создает проблему именно с weblogic + странным поведением приложения.... Он также объясняет, как эта функция доступна, но не в UserTransaction
интерфейс напрямую, но в одной из его реализаций
Когда вы используете BMT, вы управляете транзакцией. Вы используете UserTransaction для создания и подтверждения транзакции.
Дело в том, что UserTransaction создает транзакцию в текущем потоке, и когда вы вызываете другой EJB, этот вызов будет выполнен в другом потоке (со своим жизненным циклом EJB).
В CMT контейнер вставляется в вызов метода для обработки транзакции.
3.1 Интерфейс UserTransaction (из спецификации JTA)
Метод UserTransaction.begin запускает глобальную транзакцию и связывает транзакцию с вызывающим потоком. Менеджер транзакций прозрачно управляет связью транзакции с потоком.
Поддержка вложенных транзакций не требуется. Метод UserTransaction.begin создает исключение NotSupportedException, когда вызывающий поток уже связан с транзакцией, а реализация менеджера транзакций не поддерживает вложенные транзакции.
3.2.2 Завершение транзакции
Метод TransactionManager.commit завершает транзакцию, в настоящее время связанную с вызывающим потоком. После возврата метода commit вызывающий поток не связан с транзакцией. Если метод commit вызывается, когда поток не связан с каким-либо контекстом транзакции, TM генерирует исключение.
13.2.5 Демаркация, управляемая контейнером (из спецификации EJB)
Всякий раз, когда клиент вызывает метод в бизнес-интерфейсе корпоративного компонента (или в представлении без интерфейса, или в домашнем или компонентном интерфейсе корпоративного компонента), контейнер вставляется в вызов метода. Интерпозиция позволяет контейнеру декларативно управлять демаркацией транзакции через атрибут транзакции, установленный разработчиком.