Транзакция, управляемая контейнером - не помечена для отката - PullRequest
0 голосов
/ 18 июня 2020

Банк. java

@Stateless
@Local
public class Bank implements IBank {

    @EJB
    IConfigBean iConfigBean;

    @EJB
    IDbs iDBS;

    @EJB
    IPosb iPosb;

    @Override
    public void doTransaction() {
        System.out.println("--Bank Transaction Started--");
        try {
            Config config1 = getConfig(1);
            iConfigBean.create(config1);

            iDBS.doDBSTransaction();

            Config config3 = getConfig(3);
            iConfigBean.create(config3);

            iPosb.doPOSBTransaction();

            Config config5 = getConfig(5);
            iConfigBean.create(config5);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("---Bank Exception--");
        }
        System.out.println("--Bank Transaction End--");
    }

    @Override
    public Config getConfig(int inserttionOrderNo) {
        Config config = new Config();
        config.setType("EJBTransactionTESTING - " + inserttionOrderNo);
        return config;
    }
}

DBS. java

@Stateless
@Local
public class DBS implements IDbs {

    @EJB
    IConfigBean iConfigBean;

    @Override
    public void doDBSTransaction() {
        System.out.println("--DBS Transaction Started--");
        try {
            Config config2 = getConfig(2);
            iConfigBean.create(config2);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("--DBS Exception--");
        }
        System.out.println("--DBS Transaction End--");
    }

    @Override
    public Config getConfig(int inserttionOrderNo) {
        Config config = new Config();
        config.setType("EJBTransactionTESTING - " + inserttionOrderNo);
        return config;
    }

}

POSB. java

@Stateless
@Local
public class POSB implements IPosb {

    @EJB
    IConfigBean iConfigBean;

    @Override
    public void doPOSBTransaction() {
        System.out.println("--POSB Transaction Started--");
        try {
            Config config4 = getConfig(4);
            iConfigBean.create(config4);
            if (true) {
                //For Test 1 
                //throw new NullPointerException(); 
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("--POSB Exception--");
        }
        if (true) {
            //For Test 2 
            // throw new NullPointerException();
        }
        System.out.println("--POSB Transaction End--");
    }

    @Override
    public Config getConfig(int inserttionOrderNo) {
        Config config = new Config();
        config.setType("EJBTransactionTESTING - " + inserttionOrderNo);
        return config;
    }
}

Я новичок в Stack Overflow, и это мой новый вопрос, так что поправьте меня, если я ошибаюсь.

Окружающая среда ...

  • Windows 10
  • Java 1,8
  • Eclipse
  • Tomcat 8,5
  • EJB3

У меня три без состояния bean, пожалуйста, посмотрите на диаграмму последовательности потока транзакции.

Я намеренно делаю исключение NullPointer в двух местах во время транзакции, чтобы узнать разницу, и я последовательно выделил жирным жирным символом диаграмма.

Я не использую атрибут @TransactionAttribute для каких-либо методов.

Тест 1 - нулевой указатель внутри блока try (светящийся полужирный символ с зеленым) Когда я начать тестирование, получено исключение указателя Null, и все транзакции не помечены для отката, и данные также были вставлены в db.

Я могу видеть только исключение нулевого указателя в журнале консоли.

Тест 2 - Нулевой указатель вне метода try-catch (выделение жирным шрифтом красного цвета) Когда Я начинаю тестирование, Получено исключение указателя Null плюс исключение EJBTransactionRolledbackException и все транзакции, отмеченные для отката, и данные не вставлены в db.

Я вижу исключения NullPointer и EJBTransactionRolledback в журнале консоли.

Вопрос здесь:

  1. Почему транзакция EJB не помечена для отката Если я сделал нулевой указатель внутри блока try
  2. Почему транзакция EJB откатывается, происходит Если я сделал нулевой указатель за пределами try block

Заранее спасибо.

1 Ответ

0 голосов
/ 21 июня 2020

Не забывайте о вызовах EJB, все "magi c", выполняемые контейнером, происходят именно там, включая разметку транзакции. Это возможно из-за того, что вызовы EJB не прямые, а всегда go через прокси.

У вас есть такие вызовы в вашем коде:

iPosb.doPOSBTransaction(); 

Итак, если не отмечено исключение ( NPE например) выбрасывается в этом методе и не перехватывается - в конечном итоге он перехватывается контейнером из-за прокси-сервера EJB, который обертывает вызов выше. В этом случае транзакцию можно было откатить.

Добавление вызова метода того же bean-компонента в ваш метод (без использования ссылки @EJB) не меняет этого:

@Override
public void doPOSBTransaction() {
    try {
        Config config4 = getConfig(4);
        iConfigBean.create(config4);
        if (true) {
            newMethod(); 
        }
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("--POSB Exception--");
    }
    if (true) {
        newMethod(); 
    }        
}

private void newMethod(){
    throw new RuntimeException();
}

Вы можете легко проверить, что поведение фиксации / отката в этом случае одинаково, независимо от того, что метод добавлен в стек вызовов.

Поэтому важно помнить, что все трюки с контейнерами работают только при вызовах @EJB. Так, например, бессмысленно размещать аннотацию транзакции в частном методе - она ​​никогда не будет использоваться.

Еще один важный момент касается проверенных исключений. По умолчанию они действительно не вызывают отката транзакции. Но по-прежнему можно аннотировать проверенное исключение, как показано ниже, чтобы выполнить откат текущей транзакции:

@ApplicationException(rollback = true) 
...