How can a JSF/ICEfaces component's parameters be updated immediately?

南笙酒味 提交于 2019-12-04 18:22:50
StockB

Multithreading was the missing link, in conjunction with PushRenderer and PortableRenderer (see http://wiki.icesoft.org/display/ICE/Ajax+Push+-+APIs).

I now have three threads in my backing bean- one for executing the long operation, one for polling the status, and one "main" thread for spawning the new threads and returning UI control to the client browser.

Once the main thread kicks off both execution and polling threads, it terminates and it completes the original HTTP request. My PortableRenderer is declared as PortableRender portableRenderer; and in my init() method (called by the class constructor) contains:

PushRenderer.addCurrentSession("fullFormGroup");    
portableRenderer = PushRenderer.getPortableRenderer();

For the threading part, I used implements Runnable on my class, and for handling multiple threads in a single class, I followed this StackOverflow post: How to deal with multiple threads in one class?

Here's some source code. I can't reveal the explicit source code I've used, but this is a boiled-down version that doesn't reveal any confidential information. I haven't tested it, and I wrote it in gedit so it might have a syntax error or two, but it should at least get you started in the right direction.

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();
}

I suggest looking at our Showcase Demo:

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

Under the list of Progress Bar examples is one called Push. It uses Ajax Push (a feature provided with ICEfaces) to do what I think you want.

There is also a tutorial on this page called Easy Ajax Push that walks you through a simple example of using Ajax Push.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!