Есть ли способ обновить значение рычания во время выполнения actionlistener? - PullRequest
0 голосов
/ 23 января 2019

У меня есть диалоговое окно команд на веб-странице, которое использует кнопки команд, чтобы подтвердить, хочет ли пользователь запустить внутренний сценарий. Если пользователь подтвердит, что он хочет продолжить, должно появиться немедленное рычание, сообщающее ему, что сценарий начался. Затем скрипт запускается, блокируя все остальные процессы до его завершения. После завершения должно появиться другое рычание, сообщающее пользователю, что сценарий завершен.

Код xhtml настроен следующим образом:

<p:commandButton value="Yes Sure" actionListener="#{listBean.invokeBackend}"
onclick="PF('backendRun').hide()" update="invokeBackendGrowl"/>

Эти атрибуты не выполняются одновременно Порядок выполнения для этих атрибутов: onclick , затем actionlistener , затем update . В связи с тем, что мой элемент actionlistener ссылается на функцию, которая блокирует другие процессы, мне нужно выполнить атрибут update до того, как элемент actionlistener будет завершен.

onclick закрывает диалоговое окно команды

обновление работает для отображения самой последней версии рычаний

actionlistener выполняет метод bean-компонента, который использует компоновщик процессов для обеспечения бесперебойной работы сценария. Он также содержит код Java для обоих рычаний (уведомление о начале сценария и уведомление о конце сценария). Поскольку скрипт выполняется в одиночку, оба рычания отображаются одновременно после завершения скрипта, а не начальный рычажок, отображаемый сразу после запуска скрипта.

Элемент actionlistener выглядит следующим образом:

public void invokeBackend() throws IOException, InterruptedException {

     ProcessBuilder pb = new ProcessBuilder(<command for script to run>);

     pb.redirectErrorStream(true);
     File outputFile = new File(<location>);
     pb.redirectOutput(outputFile);

     Process p = pb.start();

     FacesContext context = FacesContext.getCurrentInstance();
     context.addMessage(null, new FacesMessage("Successful", "Script Called!"));

     p.waitFor();
     context.addMessage(null, new FacesMessage("Completed", "Script Complete!"));

}

Обновление

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

1 Ответ

0 голосов
/ 23 января 2019

Я решил эту проблему, используя следующий обходной путь:

Поскольку jsf всегда будет вызывать actionlistener перед атрибутом обновления, я изменил задание actionlistener'а, чтобы исключить скрипт блокировки процесса. actionlistener на кнопке команды теперь вызывает метод перенаправления , который просто выполняет первый рык, уведомляя пользователя о начале сценария.Затем запускается атрибут update, отображающий первое рычание.

Затем я ввожу удаленную команду для вызова invokeBackend (), которая такая же, как и раньше, за исключением кода для первого рыка.

Код xhtml теперь выглядит следующим образом:

<p:commandButton value="Yes Sure" actionListener="#{listBean.reroute()}"
onclick="PF('backendRun').hide();" update="invokeBackendGrowl" onsuccess="doAfter()" />
<p:remoteCommand name="doAfter" update="doneBackendGrowl" action="#{listBean.invokeBackend()}"/>  

Код Java теперь выглядит следующим образом:

public void invokeBackend() throws IOException, InterruptedException {

     ProcessBuilder pb = new ProcessBuilder(<command for script to run>);

     pb.redirectErrorStream(true);
     File outputFile = new File(<location>);
     pb.redirectOutput(outputFile);

     Process p = pb.start();

     FacesContext context = FacesContext.getCurrentInstance();

     p.waitFor();
     context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Backend complete! Please check email for the output."));            

}

public void reroute(){

     FacesContext context = FacesContext.getCurrentInstance();
     context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Backend invoked! ", "Please check back here for updates."));

}

Короче говоря, код теперь разделен так, чтоreroute () содержит код, который должен произойти до того, как скрипт заблокирует все другие процессы в invokeBackend ().

...