如何实现一个"任务监视器"与JSF

时间:2014-04-03 19:35:35

标签: jsf primefaces

我需要在服务器中执行一些任务并使用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生命周期中。

出了什么问题?

感谢您的建议。

0 个答案:

没有答案