Обработка транзакций JPA между @Stateless и @Asynchronous EJB - PullRequest
0 голосов
/ 14 октября 2018

У меня есть EJB без сохранения состояния, который вставляет данные в базу данных, немедленно отправляет ответ и на последнем шаге вызывает асинхронный EJB.Асинхронный EJB может работать долго (я имею в виду 5-10 минут, что больше, чем время ожидания транзакции JPA).Асинхронный ejb должен читать (и работать с ним) то же дерево записей (только чтение), которое сохраняется в EJB без сохранения состояния.

Похоже, что асинхронный бин пытается прочитать дерево записей перед его фиксациейили вставлен (JPA) EJB-кодом statelsss, поэтому асинхронный компонент не может видеть дерево записей.

EJB без сохранения состояния:

@Stateless
public class ReceiverBean {

    public void receiverOfIncomingRequest(data) {
        long id = persistRequest(data);
        sendResponseToJmsBasedOnIncomingData(data);
        processorAsyncBean.calculate(id);
        }
    }
}

Асинхронный EJB:

@Stateless
public class ProcessorAsyncBean {

    @Asynchronous
    public void calculate(id) {
        Data data = dao.getById(id); <- DATA IS ALLWAYS NULL HERE!

        // the following method going to send
        // data to external system via internet (TCP/IP)
        Result result = doSomethingForLongWithData(data);

        updateData(id, result);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void updateData(id, result) {
        dao.update(id, result);
}

Может быть, я могу использовать очередь JMS для отправки сигнала с идентификатором на компонент процессора вместо вызова asyc ejb (и управляемый сообщениями компонент чтения данных из базы данных), но я хочу избежать этого, есливозможно.

Другим решением может быть передача всего дерева записей в виде отдельного объекта JPA в асинхронный EJB процессора вместо чтения данных из базы данных.

Можно ли заставить асинхронный EJB работать хорошо вэта структура как-то?

- ОБНОВЛЕНИЕ -

Я думал об использовании Weblogic JMS.Здесь есть еще одна проблема.В случае большой нагрузки, когда в очереди 100 000 или более данных (это будет нормально) и нет подключения к Интернету, все мои данные в очереди потерпят неудачу.В случае возникновения этого исключения (или любого другого) во время отправки данных через Интернет (методом doSomethingForLongWithData) данные будут откатываться в исходную очередь на основе настроек redelivery-limit и repetitaion в Weblogic.Это событие отката создаст 100 000 или более потоков в Weblogic на управляемом сервере для управления повторной доставкой.Эти новые тонны фоновых процессов могут убить или, по крайней мере, замедлить работу сервера.

Я также могу использовать IBM MQ, потому что у нас есть инфраструктура MQ.MQ не оказывает такого влияния на сервер Weblogic, но MQ не имеет функции ограничения доставки и задержки.Таким образом, в случае ошибки (отката) сообщение немедленно появится на MQ снова, без задержки, и я построил ручную мельницу.Thread.sleep() в состоянии catch не является решением в приложении EE, я думаю ...

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Вам просто нужно вызвать асинхронный метод рядом с методом с разметкой транзакции, поэтому, когда транзакция зафиксирована.

Например, вызывающая сторона метода receiveOfIncomingRequest () может добавить вызов

processorAsyncBean.calculate(id);

рядом с ним.

ОБНОВЛЕНИЕ : расширенный пример

CallerMDB

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void onMessage(Message message) {
    long id = receiverBean.receiverOfIncomingRequest(data);
    processorAsyncBean.calculate(id);
}

ReceiverBean

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public long receiverOfIncomingRequest(data) {
    long id = persistRequest(data);
    sendResponseToJmsBasedOnIncomingData(data);
    return id;        
}
0 голосов
/ 15 октября 2018

Похоже, что асинхронный компонент пытается прочитать дерево записей до того, как оно было зафиксировано или вставлено (JPA) EJB-компонентом statelsss, поэтому дерево записей не отображается асинхронным компонентом.

Это ожидаемое поведение с управляемыми компонентом транзакциями.Вы запускаете асинхронный EJB из EJB с его собственным контекстом транзакции.Асинхронный EJB никогда не использует контекст транзакции вызывающей стороны (см. Спецификацию EJB 4.5.3).Пока вы не используете уровень изоляции транзакции «read uncommited» со своим постоянством, вы не увидите все еще не переданные данные от вызывающей стороны.

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

Можно подумать об использовании транзакций, управляемых компонентом, перед фиксацией асинхронного EJB.Или вы можете делегировать обновление данных другому EJB с новым контекстом трансактина.Это будет зафиксировано перед вызовом асинхронного EJB.Обычно это нормально для некритических вещей, пропавших без вести или сбоев.

Использование постоянных и транзакционных сообщений JMS вместе с очередью недоставленных писем имеет преимущество в надежной обработке ваших запросов и обновлений даже при остановке / запуске сервера приложений.между или с временными ошибками во время обработки.

...