У меня есть класс действий Struts2, который размещает запрос JMS Fetch для списка сделок в очереди JMS. Это сообщение JMS Fetch обрабатывается внешним процессом и может занять несколько секунд или даже несколько минут в зависимости от количества файлов Trade, которые должны быть обработаны внешним приложением для обработки задач.
Я хочу знать, как обрабатывать этот HTTP-запрос с соответствующим ответом. Клиент ждет, пока не будет возвращен список сделок? (клиент (пользовательский интерфейс) должен воздействовать на него, и в это время ему больше нечего делать).
Я подошел к этому так: HTTP-запрос --> Действие Struts2 -->
- Вызывает Runnable для запуска в отдельном потоке (отдельно от класса Action)
- Пользовательский интерфейс ждет
- Поток класса действий спит, пока runnable не выполнит свою работу
- Когда задача завершена, верните список сделок в пользовательский интерфейс.
Поток выглядит следующим образом:
- Поместите запрос на выборку JMS в Queue1
ExecutorService для Runnable
CClass cclass = new CClass(); final ExecutorService execSvc = Executors.newFixedThreadPool(1); execSvc.execute(cclass);
Где CClass реализует runnable, возвращающий список сделок:
List<Trade> tradesList = new ArrayList<Trade>();
@Override
public void run() {
while (true) {
try {
Message message = msgConsumer.receive(); // SYNCHRONOUS / NO MDB
if (message == null){
break;
}
if (message instanceof TextMessage) {
TextMessage txtMessage = (TextMessage) message;
Trade trade = TradeBuilder.buildTradeFromInputXML(txtMessage);
if (trade != null) {
tradesList.add(trade); // tradeList is a CClass class variable
}
}
} catch (JMSException e) {
logger.error("JMSException occurred ", e);
}
}
closeConnection();
}
И пока этот runnable выполняется, я делаю Thread.sleep в классе Action (чтобы Runnable выполнялся в отдельном потоке)
// In Action class
try {
Thread.sleep(5000); // some time till when the runnable will get executed
} catch (InterruptedException e) {
e.printStackTrace();
}
execSvc.shutdown();
Проблема в том, что если я использую Callable с FutureTask и выполняю get() , это будет блокироваться до тех пор, пока не будет возвращен какой-либо результат. Если я делаю Runnable, я должен перевести поток класса Action в спящий режим до тех пор, пока runnable не будет выполнен и не будет доступен tradeList.
Используя подход Runnable, я могу вернуть пару сотен записей обратно в пользовательский интерфейс, предоставляя 5-секундный Thread.sleep() в основном классе Action, но только частично сконструированный tradeList, когда тысячи записей должны быть извлечены и показаны в пользовательском интерфейсе.
Это явно не отказоустойчивый подход.
Есть ли лучший подход, чтобы предложить? Пожалуйста, объясните шаги для обработки в одном полном запросе - потоке ответов.