Updating UI from another thread


Problem:

In an event listener data in e.g. a Table can be updated and will be visible to the user immediately. Doing the same thing in a background thread will not update the UI but if the user press refresh in the browser the UI is suddenly updated.


Reason:

Vaadin consists of a server side that runs in a servlet container and a client side that runs in a web browser. The application state is kept on server side but communication is initiated by the client side whenever needed e.g. when a button is clicked.

The server has no possibility to contact the web browser when the state has been updated by a background thread. Instead the change “waits” on the server until the client sends the next request e.g. clicks a button or requests a full repaint by refreshing the browser. At this point the change is sent to the client and the UI is updated.


How can this be solved:

There are two ways to deal with this:
poll
or
push
.


Poll
can be accomplished using the Refresher add-on available in the Directory. The refresher causes the client to periodically poll the server to see if any changes have been made. If there are changes, they are rendered in the client.


Push
can be accomplished using the ICEPush add-on available in the Directory. ICEPush causes the client to constantly keep a connection open to the server. If the changes take place in the server you can call the push() method to notify the client immediately that there are changes waiting. The client will then contact the server and fetch those changes.


Why are there two different approaches?


Push
and
poll
both have different pros and cons.


Push
will constantly keep a connection open to the server which is good for immediate updates but bad for the server if there are many clients connected. Most servlet containers allocate one thread per request, which consumes many threads and much memory when there are many clients. Servlet 3.0 contains asynchronous support which deals better with this.

A
poller
will not notice changes immediately but only when it happens to poll the following time. Setting a low polling time causes a lot of requests to the server and thus server load. A high polling time causes less server load but also longer times before the UI is updated.


What should I use?

What you should use really depends on your use case. If your data is seldom updated or you do not need immediate updates of the UI you will probably be fine with the Refresher. If immediateness is required then ICEPush is the way to go, provided your server can handle the long connections.

If you are using Google App Engine you should use Refresher as Google App Engine does not allow connections to stay open for more than 30s.

If you are creating portlets you cannot use ICEPush as there is currently no portlet support.


Other background thread considerations:

Remember to synchronize on the application instance whenever updating the UI from another thread.

I have got exactly similar problem regarding to this. the case is that I like to have some UI component (e.g. a list or table) in my app to refresh the data periodically. So I created a thread to do it in App init method, the thread is running at server-side so it can talk to fetch the server data then update the UI, the UI gets refreshed at first time, while it doesn’t work any more until refreshing the page manually or click some other widgets to cause a refresh to server.

Does vaadin support some other easy approach without the Add-on for this purpose? Like in the run method code of thread, I can call theUIComponent.repain or something like this, to bring a request (from server) to client for such a UI content update?

Thanks!

One work arround is to have the progressbar component be running.
This one (when activated) polls the server for status update to indicate the progress.

In your case you could have a progress indicator turning, just telling the user that the table data
is currently loading in background.

Using some of the non-polling solutions actually really needs one of the addons.

André

I have the some Problem, too. I use a BeanItemContainer to contain the data for a table. A background Thread updates values of an Bean in the container and call after this action the push method of the ICEPush, but nothing happens.
How i get value changes of Beans from an BeanItemContainer shown in the table?

Greetz,
Michel

Remember that in Vaadin, components have state information that is kept on the server - they are not fully re-constructed from the underlying data on every request. Push sends the component updates queued on the server, but the component is not told there was a change if you directly modify the bean. Therefore, the component thinks there are no changes to be communicated to the client.

If you modify the bean via the Property/Item/Container (instead of directly as a POJO), the Table is notified and therefore the next push will transfer the modified value. Otherwise, you have to somehow “kick” the Table to refresh everything or to (re)set the value via the Property.

If you don’t mind refreshing the whole visible buffer of the table and don’t know exactly what might have changed, you can reset the container data source for the table after making the changes - or try calling e.g. table.valueChange(new Property.ValueChangeEvent() { public Property getProperty() { return null; } }), but this depends on current “implementation details” and might not work in future versions.

Hi Artur Signell
I have create vaadin portlet but i see in another thread
here
you say can use icepush in vaadin
why here you say can not use icepush in vaadin portlet

If you look at the dates of the messages, the message that says there is a new version that works on Liferay is newer than the message that says there is no support.

Hi,

I have applications with kind of pages.
Sometimes, for performance issues on client browser, i would like to preload the next page without displaying it.

I achieved to do it with a poll mecanism, simply by putting a ProgressIndicator in my window and by building the second page in another thread.

Actually, it works if i let the setVisible indicator of the page set to true. Then, my second page is displayed after the first.

When i want to set the setVisible indicator to false on my second page, my content is not downloaded in the page. My conclusion is based on network logs and real html content of the page in which i can’t find the word of my second page (i use Firebug for watching this).

Did anyone try to do it ? Is there a way to force the download of my components even if the container is not visible ?

Regards,

Pierre

If the attribute “visible” is false for a component, information about that component is not sent to the client.

As a workaround, you could try to make its size 0 if you really need to preload it, or add a style name for it and hide it with CSS. Note, though, that some layout calculations might have to be performed when actually making the component visible.

Hey

I am currently using your ICEPush add-on, in a chat application, with a rather complex session management, since I allow for app-level windows. These are the basics:

  1. Chat session per application, not per app-level window.
  2. User can open the chat window in multiple tabs, however it obviously should only add him to the list once. Also, all the other chat windows within the same user session are still responsive and produce no out-of-sync errors.
  3. User only gets removed from the current user list, when ALL of his chat windows are closed. In other words, he can have the chat open in 3 tabs, closes 2 of them and nothing happens.

I have implemented all of these features already, and the whole thing is working rather nicely, but I have noticed a few issues.

I am adding ICEpush to my app-level window(one ICEPush per tab), and I am noticing that push() gets fired more times than it should, and am wondering whether it is somewhat normal, or if it gets fired for every eventlistener in the list and that list needs to be cleared on close() and if the ICEpush component should be removed/cleared as the window is closed.

Currently, It only updates the chat text once, since I do a check for data present that gets cleared after update, but if I add a println() statement for error checking it still gets processed.

I am basing parts of my eventHandler on your MUCEventProvider in MUCalendar application, and I could not see a point where you clear your listener list when the app/window is closed (I did not see anything in the servlet class either). You have an addListener() method, which gets fired for every app instance, but no removeListener().

Once I am done, I would like to provide the UI as an add-on, since a chat window with private msging, themses, and menu options is a lot of work in itself, and at least write a wiki (since most do not use app-level windows) for session and event management, so your input would be extremely valuable. If you need a better explanation of my problem I would be glad to provide more details.

Thank You.

Can some body share some client code using icePush plugin … I am trying to use it in Chat App as well.
Thanks

Ok, I tried ICEPUsh too. The thread runs fine, backgorund process finishes and UI component is created and added to the window. BUt it is never rendered(or visible). When the next request goes to server, the UI componenet shows up. Even a simple resize window request or clicking on the firebug in firefox browser or just by clicking some button(which is nowhere related to the UI component that should be rendered) renders the UI component.
I have a vertical layout, which inturn have many buttons, labels etc… that should be rendered once the background thred finishes. But it never shows up, as i said untill the next request goes to the server.

Any idea how can i force the rendering of the UI once the background thread finishes…?

I have two vaadin web applications, one is an admin application and one is a user application
on the admin application there is a users table with a beanitemcontainer displaying a
list of users and their online status. whenever a user logs in/out to the user application
that change should immediately be reflected on the admin applications table.

given that these two are different applications and not a single application running diff threads
will the push/poll solution described on the first post here be of any help to me?

If the two applications can communicate some way with each others then yes. If one of the application back-ends gets the message over to the other back-end, then the second back-end can use push to move the info to the UI and the user.

Hi Vath,

Were you able to resolve your issue? I am having the same issues as well. Thanks,

Are you calling the push() method at the end of the thread’s run() method?

Cheers,
Bobby

As far as I understand the new Vaadin-7-APIs, synchronization for UI-updates from background-threads must be done by calling VaadinSession#lock() and VaadinSession#unlock(). Am I correct?

Yes, with a try-finally making sure that the unlock() is called if lock() has been called.

Sorry for the late reply. Yes, the rendering was the problem for me. I had to use the refresher add on. You can add this refresher to a layout or window. You can add it to the layout where you want to render the component. You have to set the interval to the refresher. This refreshes(just renders) the layout for every “interval time” you set and you can stop it once the component is added to the layout.

For ex :
Refresher r=new Refresher();
r.setRefreshInterval(2000)// refreshes for every 2 secs.
layout.addComponent(r);

Once you add the component, you can set the refresh interval to 0.
layout.addComponent(the component you want to add dynamically or from another thread);
r.setRefreshInterval(0); //At this point, the refresher stops running.

Hope that helps. Good Luck.

Hi,
We are using activiti explorer app from Vaadin. I would like to stop the user clicking anything ( completely graying out ) the mainWindow untill a expensive server activiti returns the result set.

Thanks
Niaz