如何才能JSF / ICEfaces的组件的参数可以立即更新?(How can a JSF/ICEf

2019-07-29 17:52发布

我有一个ICEfaces的web应用程序包含具有连接至辅助bean变量的性质的组分。 从理论上讲,变量值被编程修改,并且部件看到变化并相应地更新它的外观/属性。

然而,似乎在变量的变化不是“发现”由组件直到JSF周期(其中,从我的基本认识,是年底呈现响应阶段 )。

问题是,我有很长的文件复制操作执行,我想了inputText组件表现出周期性的状态更新。 然而,由于该组件是在渲染响应阶段才更新,它不显示任何输出,直到Java方法已经执行完毕,它显示了它在一次积累的所有变化。

我已经尝试使用FacesContext.getCurrentInstance().renderResponse()和其他功能,如PushRenderer.render(String ID)来强制XMLHttpRequest来早初始化,但无论怎样,组件的外观不会改变,直到Java代码完成执行。

我想到的一个可能的解决方案是什么地方有一种无形的按钮,它会自动“按下”由bean时长操作的第1步完成,并通过点击它,它会调用第2步,等等等等。 这似乎是它的工作,但我不想花时间一起黑客这样一个不雅的解决方案时,我希望有内置JSF / ICEfaces的一个更好的解决方案。

我缺少的东西,或诉诸难看黑客以达到所期望的行为的唯一途径?

Answer 1:

多线程是缺失的一环,与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();
}


Answer 2:

我建议在看我们的展示演示:

http://icefaces-showcase.icesoft.org/showcase.jsf?grp=aceMenu&exp=progressBarBean

在的进度条实例列表被一个叫推。 它使用了Ajax推(带有ICEfaces的一个功能)做什么,我想你想要的。

还有这个页面调用Ajax的简单推送引导您通过使用Ajax推的一个简单的例子上的教程。

http://www.icesoft.org/community/tutorials-samples.jsf



文章来源: How can a JSF/ICEfaces component's parameters be updated immediately?