我正在开发一个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,并且只是在每次任务完成时尝试推送一些数据。有什么想法吗?
答案 0 :(得分:2)
您应该尝试使用Primefaces poll标记。这将每隔x秒触发一次ajax事件。您可以使用它在您的辅助bean上调用您的“getData”方法。这会将轮询的逻辑移动到您的JSF页面,而不是支持bean。
例如:
<p:poll interval="10" listener="#{decryptionBean.getData}" update="dataPanelGrid" />
这要求您在支持bean中使用简单的“getData”方法,而不需要调度代码。