Управление транзакциями в iJaNet Framework

Автор: Антон Сержантов
Компания: Janet systems

Транзакции и архитектура iJaNet Framework

Главная задача данной статьи - рассказать как происходит обработка транзакции в системе iJaNet Framework. Архитектура iJaNet Framework построена таким образом, что все межмодульные вызовы методов сервисов iJaNet модулей происходят через Enterprise Java Session Bean with Container-Managed Transactions (подробнее о Session EJB см. здесь, о Container-Managed Transactions см. здесь). Таким образом, границы транзакции обрамляются границами вызываемого метода сервиса. В результате, получается, что, если метод сервиса отрабатывает свою логику без ошибок, то совершается commit транзакции. Если же в методе возникает ошибка (Exception) и она не гасится (передается выше по стеку вызова), транзакция прерывается, а все проделанные изменения в ресурсах, затронутых в данной транзакции, откатываются в то состояние, которое было перед вызовом метода сервиса.
Необходимо также отметить, что внутри метода сервиса, могут вызываться методы других сервисов. Факт порождения новой транзакции в вызываемых методах других сервисов, зависит от:
  1. Находятся ли вызывающий и вызываемый сервисы в одном модуле
  2. (Если вызывающий и вызываемый сервисы находятся в разных модулях) Находятся ли данные модули в пределах одного сервера приложений (контейнера) и через какой тип транспорта (поддерживающий/не поддерживающий транзакционность) происходит вызов .
Рассмотрим все ситуации подробнее:
  1. Если вызывающий и вызываемый сервисы находятся в одном и том же модуле, то вызываемый метод вызывается напрямую и работает в пределах транзакции вызывающего, и новая транзакция не порождается
  2. Если сервисы находятся в разных модулях, но модули находятся в пределах одного сервера приложений, то:
    • для EJB-траснпорта (EJB-Local) - новая транзакция в вызываемом методе сервиса не порождается
    • для HTTP-траснпорта - новая транзакция в вызываемом методе сервиса порождается
  3. Если сервисы находятся в разных модулях И модули находятся на разных серверах приложений, то:
    • для EJB-траснпорта (EJB) - новая транзакция в вызываемом методе сервиса порождается, но есть возможность настройки сервера приложений таким образом, чтобы для транспорта, поддерживающего транзакционность, новая транзакция не порождалась
    • для HTTP-траснпорта - новая транзакция в вызываемом методе сервиса порождается

Примеры обработки транзакций в различных конфигурациях системы.

Пример №1.

Пусть в системе есть два iJaNet модуля на разных серверах приложений. Модуль №1 - клиент, модуль №2 - серверная часть, работающая с базой данных. Модуль №1 соединен с модулем №2 по HTTP-транспорту.

Пусть в модуле №2 есть сервис Service2, который имеет метод save(), вызываемый клиентом для занесения изменений в базу данных:

 1 public void save(String data) throws MyException {
 2    ...
 3    try {
 4       update();
 5       ...
 6       update();
 7       ...
 8       update();
 9    } catch (Throwable th) {
10       throw new MyException("Invalid data update", th);
11    }
12 }

Метод save() сохраняет данные в базу посредством вызова метода update(). Если, например, при втором вызове update() произойдет ошибка (которая "запакуется" в MyException и передастся дальше), то транзакция прервется и изменения, сделанные в первом вызове метода update() откатятся назад. Если весь метод save() отработает без ошибок, то все изменения во всех ресурсах, задействованных в этой транзакции, становятся окончательными.

Пример №2.

Во многом повторяет пример №1, только метод update() делегирует работу с базой данных другому сервису, например, DataService, который находится в другом модуле на другом сервере приложений.

Пусть модуль №2 и модуль №3 соединены по HTTP транспорту. В таком случае, т.к. каждый метод update() вызывает метод другого сервиса, то каждый такой вызов будет порождать новую транзакцию, поэтому в случае, если во втором вызове метода update() произойдет ошибка, то изменения, сделанные в первом вызове метода update(), откатываться не будут.

Пример №3.

Cитуация такая же как и в пример №1, только метод save() является методом удаленного объекта (RemoteObject) и соответственно вызывается с клиента посредством remoting

Вызов метода удаленного объекта, также как и вызов метода сервиса оформляется как одна транзакция. Таким образом, обработка транзакции происходит абсолютно также, как и в примере №1.
В случае же, если метод update(), вызываемый внутри метода save() удаленного объекта, работает аналогично методу update() в примере №2, то обработка транзакции будет происходит по такому же алгоритму, как и в примере №2.

exmpl3.gif (25.3 KB) Виталий Шакуров, 04/30/2010 01:06 am

exmpl2.gif (33.4 KB) Виталий Шакуров, 04/30/2010 01:06 am

exmpl1.gif (20.5 KB) Виталий Шакуров, 04/30/2010 01:06 am

Also available in: HTML TXT