Долгосрочная задача в Java EE WebApp + icefaces - PullRequest
2 голосов
/ 14 декабря 2011

Я не очень разбираюсь в Java EE, но в настоящее время изучаю его.

Я разработал проект, который включает в себя долго выполняющуюся задачу (до нескольких минут), вызываемую пользователем.Задача состоит из нескольких этапов.Конечно, я хотел бы показать прогресс пользователю.

В проекте используется Java EE с JPA, JSF и Icefaces.Он работает на Glassfish.

Опытный коллега посоветовал мне следующий шаблон:

  1. Создайте асинхронный EJB без сохранения состояния, который создает объект ответа и обрабатывает запрос
  2. Сохранять объект ответа после каждого шага
  3. В компоненте поддержки запросите и отобразите объект ответа

Это работает хорошо.Моя единственная проблема - обновить статус сайта, чтобы отразить прогресс.В настоящее время я делаю это с простой страницей JavaScript, перезагружаемой каждые x секунд.

Знаете ли вы способ / шаблон для отражения текущего шага от ejb без состояния к компоненту поддержки jsf?Или, и я бы предпочел, чтобы вы знали, как запрашивать значение базового компонента каждые x секунд?

Редактировать:

Мне известно оМеханизм выдвижения Icefaces, но я хочу, чтобы сайт обновления статуса был отделен от EJB вычисления по следующим причинам:

  • Возможно, компонент поддержки уже уничтожен, поскольку пользователь покинул сайт и позже вернулся для получениярезультат
  • Несколько сессий и, следовательно, несколько бинов могут существовать для одного пользователя
  • Имея чистый дизайн

Ответы [ 3 ]

1 голос
/ 14 декабря 2011

Существует несколько вариантов возврата этой информации.Если EJB живет в той же JVM, вы также можете использовать какую-то одноэлементную Карту и сохранять прогресс под определенным ключом (ID сеанса)

Если это не так, вам потребуется некоторое общее состояние или коммуницирование.Есть несколько вариантов

  • сохранить его в базе данных, доступной с обоих уровней (sql, JNDI, LDAP - лучшим решением будет хранилище значений ключей, например, redis - если вы его получили)
  • использовать некоторые сообщения для передачи состояния обработки на стороне веб-уровня
  • сохранять состояние в хэше на стороне уровня EJB и предоставлять другой метод SLSB для получения этого состояния

На ваш выборЭто не легко - все эти решения сосут по-разному.

1 голос
/ 30 января 2013

Я выполнил это с помощью многопоточной модели опроса в сочетании с компонентом ProgressBar.

public void init()
{
    // This method is called by the constructor.
    // It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
    PushRenderer.addCurrentSession("fullFormGroup");
    portableRenderer = PushRenderer.getPortableRenderer();
}   


public void someBeanMethod(ActionEvent evt)
{
    // This is a backing bean method called by some UI event (e.g. clicking a button)
    // Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render

    copyExecuting = true;

    // Create a status thread and start it

    Thread statusThread = new Thread(new Runnable() {
        public void run() {
        try {
                        // message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
            message = "Copying...";
            // initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
            portableRenderer.render("fullFormGroup"); 
            do {
                progress = getProgress();
                portableRenderer.render("fullFormGroup"); // render the updated progress
                Thread.sleep(5000); // sleep for a while until it's time to poll again
            } while (copyExecuting);
            progress = getProgress();
            message = "Finished!";
            portableRenderer.render("fullFormGroup"); // push a render one last time
        } catch (InterruptedException e) {
            System.out.println("Child interrupted.");
        }
    });
    statusThread.start();

    // create a thread which initiates script and triggers the termination of statusThread
    Thread copyThread = new Thread(new Runnable() {           
        public void run() {
        File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
            scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
            copyExecuting = false; // this will caue the statusThread's do..while loop to terminate


        } 
    });
    copyThread.start();
}
0 голосов
/ 14 декабря 2011

Поскольку вы используете icefaces, вы можете использовать механизм ICEpush для рендеринга ваших обновлений.

...