サーバーに対して20秒ごとにRESTful GETリクエストを行い、返されたデータを表示する必要があるJSF + Primefaces Web Appに取り組んでいます。これは現在、「10 秒ごと」の部分を除いて機能します。コマンド ボタンをクリックして、データを取得して表示できます。ScheduledExecutorService で繰り返しを実装しようとしました。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>
ジャワ
@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
です。明確にするために: バッキング機能は最初のクリックで実行されますが、2 回目、3 回目、4 回目などで 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 を使用しており、タスクが完了するたびにデータをプッシュしようとしていることに注意してください。何か案は?