我需要在服务器中执行一些任务并使用JSF(primefaces)显示状态。
下面我描述了我的最后一次尝试:
default.xhtml
<p:commandButton
value="execute"
action="#{controller.init()}" /> <!-- initialize and validate data and call task1() -->
<p:fieldset id="messages" legend="Status:">
<ul>
<li>
<h:panelGrid columns="2" id="msg1" styleClass="#{controller.status1}">
<p:outputLabel value="#{controller.msg1}" />
<span class="#{controller.classToIconClass(controller.status1)}"></span>
</h:panelGrid>
</li>
<li>
<h:panelGrid columns="2" id="msg2" styleClass="#{controller.status2}">
<p:outputLabel value="#{controller.msg2}" />
<span class="#{controller.classToIconClass(controller.status2)}"></span>
</h:panelGrid>
</li>
...
<p:remoteCommand name="task1" action="#{controller.task1()}" update="messages" />
<p:remoteCommand name="task2" action="#{controller.task2()}" update="messages" />
每一步都是这样的:(Controller.java)
@SessionScoped
...
public void task1() {
if(stopExecution) return;
long returnCode = -1;
String errorMessage = "An error occurred in the task1 execution.";
try {
returnCode = execute(comandString);
} catch (Exception e) {
Logger.getLogger(getClass()).error(errorMessage, e);
returnCode = -1;
stopExecution = true;
}
if(returnCode != 0 && returnCode != 4) {
msg1 = errorMessage;
status1 = "error";
stopExecution = true;
return;
} else {
msg1 = "Task1 is finished.";
status1 = "successful";
}
msg2 = "Running task2...";
status2 = "running";
RequestContext requestContext = RequestContext.getCurrentInstance();
requestContext.execute("task2();"); // Calls next step
}
// Everything is like task1() and always call next task at the end:
public void task2() {...}
public void task3() {...}
public void task4() {...}
public void finish() {...}
这样一切运行正常,但用户有时会刷新页面并且执行链会破坏。
有没有办法做我想做的事情并在页面刷新后幸存下来?
PS:
我还尝试在它们之间执行任务RequestContext.getCurrentInstance().update("form:messages");
,但页面只在最后一个任务结束时更新。
修改
正如Michele和Xtreme Biker所说,我是在一个单独的线程中做到的:
Controller.java
@SessionScoped
...
RequestContext requestContext;
Callable<Long> task1 = new Callable<Long>() {
@Override
public Long call() throws Exception {
long returnCode = -1;
String errorMessage = "An error occurred in the task1 execution.";
returnCode = execute(comandString);
if(returnCode != 0 && returnCode != 4) {
msg1 = errorMessage;
status1 = "error";
return returnCode;
} else {
msg1 = "Task1 is finished.";
status1 = "successful";
msg2 = "Running task2...";
status2 = "running";
}
requestContext.update("form:messages");
return returnCode;
}
};
public void init() {
requestContext = RequestContext.getCurrentInstance();
List<Future<Long>> tasks = new ArrayList<Future<Long>>();
ExecutorService executor = Executors.newSingleThreadExecutor();
tasks.add(executor.submit(this.task1));
tasks.add(executor.submit(this.task2));
tasks.add(executor.submit(this.task3));
tasks.add(executor.submit(this.task4));
tasks.add(executor.submit(this.finish));
executor.shutdown();
}
即使我刷新页面,所有任务都会运行,很好。 但是这个观点并没有更新。
我认为requestContext.update("form:messages");
位置错误。
但是如果从Callable.call中获取RequestContext.getCurrentInstance()
,我会得到一个NullPointerException,因为我不在JSF生命周期中。
出了什么问题?
感谢您的建议。