Транзакционный тип Java EE для различных типов компонентов - PullRequest
0 голосов
/ 09 мая 2018

Рассмотрим следующий сценарий:

Аннотированный класс без сохранения ClassOne

@Stateless
public class ClassOne {
    // some injected fields
    // ....
    @Inject
    private ClassTwo classTwo;
    // ....

    public void methodInClassOne() {
        try {
            classTwo.methodInClassTwo();
        } catch(Exception e) {
            // handle exception
        }
    }
}

Классифицированный аннотированный класс ClassTwo

@Stateless
public class ClassTwo {
    // some injected fields
    // ....
    @Inject
    private ClassThree classThree;
    // ....

    public void methodInClassTwo {
        try{
            classThree.methodInClassThree();
        } catch (Exception e) {
            // handle exception
        }
    }
}

Неаннотированный класс ClassThree

public class ClassThree {
    // some injected fields
    // ....

    public void methodInClassThree {
        // some business logic
        // ....
        if (conditionCheck) {
            throw new RuntimeException("error message");
        }
    }
}

Скажем, для этого случая вышеприведенный conditionCheck всегда оценивается как true . Это рабочий код на сегодня. RuntimeException помещается в EjbException и перехватывается, обрабатывается и перебрасывается, как ожидается, до тех пор, пока не достигнет блока catch ClassOne. Но в тот момент, когда я делаю ClassThree Stateless (с @Stateless), исключение RuntimeException становится EjbTransactionRolledBackException, в результате чего транзакция отбрасывается, и любая обработка в ClassOne, которая пытается вызвать постоянную службу, прерывается из-за этого. Я попытался поэкспериментировать с @TransactionAttributes:

  1. ТРЕБУЕТСЯ ПОДДЕРЖКА -> дает то же поведение RollBack, убивающее транзакцию

  2. NOT_SUPPORTED -> дает, даже до проверки состояния, при вызове JpaRepository исключение TransactionRequiredException (с которым я предположил, что должен быть также TransactionType с исходным неаннотированным классом. И, вероятно, не той же транзакцией как в ClassTwo - из-за пункта 1.)

  3. REQUIRES_NEW -> который, казалось, вел себя так же, как исходный код.

У меня сложилось впечатление, что если бы ничего не было указано явно, то вызываемый метод / класс использовал бы тип по умолчанию REQUIRED (что, очевидно, не имело место, поскольку, как упоминалось в пункте 1.). Так как же TransactionType работает между компонентами Annotated (EJB) -NonAnnotated (CDI)? Отличается ли он от того, как он работает между двумя компонентами Annotated (EJB)? Я не уверен, что мой вопрос ясен. Короче говоря, все поведение транзакции сбивает с толку, особенно из-за того, как оно ведет себя по-разному для ClassThree до и после того, как делает его не имеющим состояния.

Любые материалы или ссылки на дополнительную информацию по этому вопросу будут действительно полезны. Заранее спасибо

1 Ответ

0 голосов
/ 15 мая 2018

Когда вы добавляете @Stateless к ClassThree, оно становится неявно транзакционным и (как вы говорите) ведет себя с типом транзакции REQUIRED).

Каждый вызов EJB проходит через условную «границу», где проверяются учетные данные безопасности вызова и, при необходимости, устанавливается (новая) транзакция (среди прочего). По завершении вызова результат вызова возвращается через ту же границу.

По умолчанию *, если результатом вызова является java.lang.RuntimeException, то контейнер должен

  1. пометить текущую транзакцию для отката
  2. обернуть исключение RuntimeException в EJBException
  3. перебрасывать новое исключение EJBException

Все это происходит на обратном пути через эту границу.

Следовательно, methodInClassTwo ловит EJBTransactionRolledbackException, подкласс EJBException. Обратите внимание, что именно шаг 1 убивает вашу транзакцию, а не любую последующую обработку исключений.

Если methodInClassThree был размечен с типом транзакции REQUIRES_NEW, то новая транзакция всегда создается при входе в границу метода. Любая ранее существующая транзакция приостановлена. Бросок RuntimeException ведет себя так же, как указано выше, за исключением того, что это новая транзакция, которая откатывается. Транзакция, которая была активна до входа в границу, остается неизменной и возобновляется.

Наконец, если methodInClassThree был размечен с типом транзакции NOT_SUPPORTED, текущая транзакция приостанавливается на границе и возобновляется при завершении вызова. Откат не выполняется из-за возникновения RuntimeException, так как нет активной транзакции. Но вам все равно не нужен этот сценарий.

* +1033 * & AST; Вы можете изменить это поведение, используя @javax.ejb.ApplicationException.
...