我有一个ICEfaces的web应用程序包含具有连接至辅助bean变量的性质的组分。 从理论上讲,变量值被编程修改,并且部件看到变化并相应地更新它的外观/属性。
然而,似乎在变量的变化不是“发现”由组件直到JSF周期(其中,从我的基本认识,是年底呈现响应阶段 )。
问题是,我有很长的文件复制操作执行,我想了inputText组件表现出周期性的状态更新。 然而,由于该组件是在渲染响应阶段才更新,它不显示任何输出,直到Java方法已经执行完毕,它显示了它在一次积累的所有变化。
我已经尝试使用FacesContext.getCurrentInstance().renderResponse()
和其他功能,如PushRenderer.render(String ID)
来强制XMLHttpRequest来早初始化,但无论怎样,组件的外观不会改变,直到Java代码完成执行。
我想到的一个可能的解决方案是什么地方有一种无形的按钮,它会自动“按下”由bean时长操作的第1步完成,并通过点击它,它会调用第2步,等等等等。 这似乎是它的工作,但我不想花时间一起黑客这样一个不雅的解决方案时,我希望有内置JSF / ICEfaces的一个更好的解决方案。
我缺少的东西,或诉诸难看黑客以达到所期望的行为的唯一途径?
多线程是缺失的一环,与PushRenderer和PortableRenderer(见一起http://wiki.icesoft.org/display/ICE/Ajax+Push+-+APIs )。
我现在有三个线程我支持bean-一个用于执行长时间的操作,一个用于轮询状态,和一个“主”线程产卵的新主题和返回UI控件到客户端浏览器。
一旦主线程序幕两个执行和轮询线程,它终止和它完成原来的HTTP请求。 我PortableRenderer被声明为PortableRender portableRenderer;
在我的init()方法(在类的构造函数调用)包含:
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
对于螺纹部,我用implements Runnable
上我的课,并在一个类中处理多个线程,我跟着这个StackOverflow上一篇: 如何处理多个线程在一个班?
下面是一些源代码。 我不能透露,我用了明确的源代码,但是这是一个煮下来的版本不会泄露任何机密信息。 我没有测试它,我写在gedit中,所以可能有语法错误或两个,但至少应该让你在正确的方向开始。
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}
我建议在看我们的展示演示:
http://icefaces-showcase.icesoft.org/showcase.jsf?grp=aceMenu&exp=progressBarBean
在的进度条实例列表被一个叫推。 它使用了Ajax推(带有ICEfaces的一个功能)做什么,我想你想要的。
还有这个页面调用Ajax的简单推送引导您通过使用Ajax推的一个简单的例子上的教程。
http://www.icesoft.org/community/tutorials-samples.jsf