p:commandbutton update不会立即更新ScheduledExecutorService

时间:2013-08-08 09:46:51

标签: jsf jsf-2 primefaces scheduled-tasks

我正在开发一个JSF + Primefaces Web App,我需要每隔20秒向服务器发出一次RESTful GET请求,并显示返回的数据。除了“每10秒”部分之外,这当前有效。我可以单击我的命令按钮来检索和显示数据。我试图用ScheduledExecutorService实现repitition。现在,当我单击commandButton时,后备函数每10秒运行一次(我可以通过System.out.println输出看到这一点),但是在第二次单击该按钮之前,该表不会更新以显示数据。以下是我的代码:

HTML(这是嵌入在表单中)

<p:commandButton id="andon_layout--board0--loadboard0"
    value="Load board"
    actionListener="#{decryptionBean.loadBoardListen0}"
    update="dataPanelGrid" />
<div id="andon_layout--board0--display_div"
    class="ui-datatable ui-widget ">
    <h:panelGrid id="dataPanelGrid"
        columns="#{decryptionBean.displayBoardArray[0].datatableNumberOfCols}"
        headerClass="ui-datatable ui-widget-header ">
        <f:facet name="header">
            <h:outputText
                value="#{decryptionBean.displayBoardArray[0].locationName}" />
        </f:facet>
        <c:forEach var="row"
            items="#{decryptionBean.displayBoardArray[0].displayData}">
            <c:forEach var="value" items="#{row}">
                <div class="ui-dt-c">#{value}</div>
            </c:forEach>
        </c:forEach>
    </h:panelGrid>
</div>

JAVA

@ManagedBean
@ViewScoped
public class DecryptionBean implements Serializable {
...

private Updater left = new Updater(0);
public void loadBoardListen0(ActionEvent event){
    left.stopBoardLoading();
    left.beginBoardLoading();
}

public final class Updater {

    @PreDestroy
    public void destroy() {
        fScheduler.shutdownNow();
    }

    private ScheduledExecutorService fScheduler;
    //
    private long fDelayBetweenRuns = 10;
    int boardNumber;

    /**
     * If invocations might overlap, you can specify more than a single
     * thread.
     */
    private int NUM_THREADS = 1;
    public int isRunning = 0;
    private boolean DONT_INTERRUPT_IF_RUNNING = false;
    private ScheduledFuture<?> loadBoardFuture;
    private class BoardLoaderTask implements Runnable {
        private int boardNumber;

        public BoardLoaderTask(int boardNumber) {
            this.boardNumber = boardNumber;
        }

        public void run() {
            DecryptionBean.this.loadBoard(boardNumber);
        }
    }

    public Updater(int boardNumber){
        this.boardNumber = boardNumber;
        fScheduler = Executors.newScheduledThreadPool(NUM_THREADS);
    }

    void beginBoardLoading(){
        if(isRunning == 1){
            this.stopBoardLoading();
        }
        isRunning = 1;          
        Runnable boardLoaderTask = new BoardLoaderTask(this.boardNumber);
        loadBoardFuture = fScheduler.scheduleWithFixedDelay(boardLoaderTask,
                0, fDelayBetweenRuns, TimeUnit.SECONDS);
    }

    void stopBoardLoading(){
        if(isRunning == 1){
        isRunning = 0;
        Runnable stopBoard = new StopLoadingTask(loadBoardFuture);
        fScheduler.schedule(stopBoard, 0, TimeUnit.SECONDS);
        }
        isRunning = 0;
    }

    private class StopLoadingTask implements Runnable {
        StopLoadingTask(ScheduledFuture<?> aSchedFuture) {
            fSchedFuture = aSchedFuture;
        }

        private ScheduledFuture<?> fSchedFuture;

        @Override
        public void run() {
            // TODO Auto-generated method stub
            fSchedFuture.cancel(DONT_INTERRUPT_IF_RUNNING);
        }
    }
}

loadBoard(int boardNum)是一个很大的功能,所以我没有在这里发布,但如果你们认为有必要,我会这样做。

在我看来,问题来自p:commandbutton update属性:似乎dataPanelGrid正在loadBoardListen0的开头更新,而不是结束。需要说明的是:支持功能在第一次单击时运行,但仅在第二次,第三次,第四次等更新GUI时单击此处的任何指导?提前谢谢!

编辑1: 我现在正尝试使用PrimePush和套接字来做这件事,但我也遇到了麻烦。我把它添加到我的代码中: HTML <p:socket onMessage="handleMessage" channel="/IPVS" autoConnect="false"/> ...

function handleMessage(data) {
    console.log("data received: " + data);
    var elm = "andon_layout--board" + data + "--display_div";
    elm.style.display="none";
    var redrawFix = elm.offsetHeight;
    elm.style.display="block";
}

JAVA(在loadBoard(int)的末尾)

System.out.println("Loading data... no exceptions thrown");
System.out.println("context created");
PushContextFactory.getDefault().getPushContext().push("/IPVS", Integer.toString(displayBoardNum));
System.out.println("Just pushed to /IPVS");

每当我尝试运行代码时,它只会在PushContextFactory行停止。我得到的输出如下:

Loading data... no exceptions thrown
context created

根本就没有了。这也可以防止循环运行。请注意,我仍在使用ScheduledExecutorService,并且只是在每次任务完成时尝试推送一些数据。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您应该尝试使用Primefaces poll标记。这将每隔x秒触发一次ajax事件。您可以使用它在您的辅助bean上调用您的“getData”方法。这会将轮询的逻辑移动到您的JSF页面,而不是支持bean。

例如:

<p:poll interval="10" listener="#{decryptionBean.getData}" update="dataPanelGrid" />

这要求您在支持bean中使用简单的“getData”方法,而不需要调度代码。