При остановке приложения с КМА, приложение должно вызвать метод КМА stop(). При этом КМА должен дать сигнал агентам для их аккуратного завершения и отправить конечный результат работы в МА. Завершение КМА состоит из 3х фаз.
Статус
Комментарий
Дополнительный комментарий
На 1й фазе для всех активных НЗ устанавливаем AgentContext#isCanceled в true. Для всех SCHED ставим флаг "прерван". Отменяем задачу ожидания запуска сигналов для запуска SCHED-агентов, чтобы новые агенты не запускать. Итераторы SCHED агентов должны перестать опрашивать очередные jms-сообщения. AsapAgentListener при получении сообщения не должен вызывать агент, а должен вызвать rollback() и закрыть свой JMSContext. ASAP и SCHED агенты теперь не получат новых сообщений, но могут обрабатывать последнее.
На 2й фазе ждем 15 сек. Агенты могут завершить обработку последнего сообщения без InterruptedException и закоммитить его. Для завершенных SCHED шлем в МА статус прерывания на основании флага "прерван". Для завершенных ASAP шлем в МА статус успешного завершения. JMS-транзакции коммитим. Если все агенты завершились ранее 15 сек, то прерываем фазу 2 и пропускаем фазу 3.
На 3й фазе принудительлно закрываем "зависших" агентов. Сначала для всех не завершенных SCHED вызываем Future.cancel(true). Затем для каждогоне завершенного ASAP ставим флаг "прерван", вызываем thread.interrupt() иJMSContext.close() (т.к. JMSContext.close() блокируется в ожидании завершения ASAP-Listener). Но агенты могут всё ещё продолжить работать. JMSContext для SCHED закрывается при выходе из агента. Если получили любой эксепшен и установлен флаг "прерван", то шлем в МА статус "прерван". (Помимо InterruptedException могут быть ещё связанные с не возможностью закоммитить jms-транзакцию) ASAP на этой фазе тоже могут завершится без эксепшена - шлем статус успешного завершения.