Updating ProgressBar using custom listener (interfaces)

Hello!

Within my application, what I have is a long-lasting process which processes some calculus in the server (best routes of some vehicles and so on). I want to show to the user a progress bar indicating the current status of the process.

In theory, everything seem easy. I have a ProgressBar object in my View. This progress bar will be updated via a Listener, which will be written as a normal Interface, say IProgressListener, which one method called notifyProgress(float pValue). When a new value is generated in the server (running the calculate()) notifyProgress() will be called. In my view, it will be defined an instance of IProgressListener overriding the notifyProggress(float pValue) method, which will do the progressBar.setValue(pValue); stuff.

Unfortunately, when running my webapp, the progress bar remains stuck, with no value update, until the long-taking process is finished. Here is when the progress bar goes ahead, repidly, to the end at 100%

Does anybody know why is this happening?

Thank you in advance.

Hi Jon,

In normal HTTP, the server has no way of notifying the client of any changes to its state unless the client makes a request asking for an update. The deprecated ProgressIndicator component
polls
the server at regular intervals to update itself; ProgressBar does not do that itself because Vaadin now supports both
server push
, allowing the server to send changes proactively, and
UI polling
, making it possible for the client to poll changes in arbitrary components.

Both of these are disabled by default, however; it depends on your application which update mechanism suits your needs better. Polling can be enabled via [font=courier new]
UI.setPollInterval(milliseconds)[font=arial]
; you should disable it by passing -1 when you don’t need it anymore. Push is easiest to enable by adding the
@Push
annotation to your UI.

Push especially has important caveats, though: it is a somewhat experimental technology and may not work well in all cases, especially in the presence of proxy servers or other traffic manipulation hardware of software.
[/font]
[/font]

I was guessing something similar @Johannes Dahlström…

However I do not have any idea how to use the server push feature. I will take a look at Vaadin documentation.

Otherwise, if I am not wrong, you might be suggesting that it would be a workaround to make a method which return the current progress made, so that this method can be run from the client using a loop (until the progress gets finished).

I have found this page: https://vaadin.com/book/es/-/page/advanced.push.html

Here it is explained that UI elements cannot be modified from other threads. What I guess is that, when calling the Listener method, we are not in the UI thread, that is why UI does not get updated until it has finished.

Anyway, I have tried implementing it but with no success, here there are the examples:

private final void actualizarValor(float valor){
    progresoAlgoritmo.setValue(valor); // progresoAlgoritmo it's a ProgressBar object
}

[code]
private IProgressListener listenerAlgoritmo = new IProgressListener() {

    boolean inicio = true;
    
    @Override
    public void notifyProgress(float pProgreso, ProgressBar pBar) {
        System.out.println("Progreso general - Vamos por... " + pProgreso);

        if(inicio){
            System.out.println("Inicio ejecución algoritmo.");
            inicio = false;
            ui.access(new Runnable() {
                
                @Override
                public void run() {
                    //pBar.setValue(0.0f);
                    actualizarValor(0.0f);
                    estadoProgresoAlgoritmo.setValue("Ejecutando algoritmo...");
                }
                
            });
        }else{
            System.out.println(String.format("WizardStep2: Proceso completado al %.2f%%", pProgreso));
            
            ui.access(new Runnable() {
                public void run() {
                    //pBar.setValue(pProgreso + 0.0f);
                    actualizarValor(pProgreso);
                }
            });
            
        }
        
    }
    
};

[/code]I pass the IProgressListener object as a parameter to the calculate() method:

Main.generateResultCluster(/* other attributes */, listenerAlgoritmo, listenerAlgoritmoDirections); This method is called when the user clicks over a button.

Am I doing something wrong?

Anyway, my tomcat tells me that Async is enabled:

mar 06, 2015 10:19:43 AM org.atmosphere.cpr.AtmosphereFramework info INFORMACIÓN: Atmosphere is using async support: org.atmosphere.container.JSR356AsyncSupport running under container: Apache Tomcat/8.0.18 using javax.servlet/3.0 and jsr356/WebSocket API

I’ve defined Push in both web.xml and inside my UI (here using the annotation @Push). Finally, I’ve been able to make it work. I’ve replaced the usage of IProgressListener and I’ve implemented the Observer Pattern. Strange as it may seem, I’ve not wrapped the UI updates between the ui.access( () → { //code here }); snippet (otherwise, UI changes wouldn’t work if introduced here). Thanks for your help!

I read the other day that Push has some issues with Tomcat. This might come in handy:


https://vaadin.com/wiki/-/wiki/Main/Working+around+push+issues

Thanks for your help :slight_smile: