Vaadin 14 is finally out, but we still have miles to walk on our mission to simplify developer experience. Vaadin shines when it comes to data binding. Mostly due to the architecture that allows you to put the Java UI code to the same execution environment as your services. But there are things we can do to improve this further.
I have a couple of improvement ideas I’d like to present, to make connecting data to Vaadin components both easier and better performing. If we can get the ideas and prototypes validated, I hope these will appear in some upcoming Vaadin version in the near future.
What is lazy data binding in Vaadin?
In a server-centric Vaadin code, the easiest way to populate data to components like Grid or ComboBox is to use setItems method with a java.util.List of your entities. This is a fast and straightforward method, but if you have a lot of data in your components and a lot of users, your server’s memory consumption skyrockets.
To save memory on the server, Vaadin components like Grid and ComboBox support lazy data binding. It is done using interface called DataProvider or a pair of lambda expressions: the first allows component to request a range of rows from your backend and the other tells how many rows there are in total.
With lazy data binding, the framework needs to load only a minimal amount of data to the server memory. You can display tens of thousands of rows in your application for many concurrent users without running out of memory. But the system has a couple of annoyances that we could maybe get rid of in the future.
Improvement idea 1: No need to calculate the size of the dataset
Grid and ComboBox components in Vaadin both need to get the number of rows there are in the data set. For a developer, this is an extra method to implement, and for many databases, an expensive operation. Although the count query may be easy to write with SQL, it often forces the database to scroll through all tables. If a Vaadin component would make a minor reduction in UX, we could significantly improve database performance and DX (developer experience).
Together with our framework engineers, I wrote a prototype of this to my Vaadin 8 add-on called Viritin. The prototype appears to work rather well, but the UX drawbacks are there. When you scroll towards the end of the Grid, the scrollbar may make an odd jump as the component notices that more rows are arriving from the database than expected. Also, you can’t scroll directly to the last row, but often one can do that by sorting the Grid. To feel how it could work in real life, try out the live demo.
The code difference is visualized below.
On the performance side, the improvement depends on your database and dataset, but in specific scenarios, we can even talk of minutes getting down to milliseconds. Indexes can help database to get the first results quickly, but all rows need to be traversed to count the number of results. Those users who have had this performance issue will remember if for life.
If we end up developing this feature to an upcoming Vaadin version, we will probably make both configurations possible: if you’d need a best possible UX, you’ll need to cope with the count query.
Improvement idea 2: Paged requests
Another improvement idea relates to how Vaadin components access your backend. Currently, the API allows components to access data sets from an arbitrary index with any limit the component decides. The behavior is easy for the component developer and in many cases for you too. But it is a horror for caching (in all levels of your architecture) and for certain backends. For example, the popular Spring Data project gives you “paged access” to your data, which makes the data binding code really complex.
For the same Viritin add-ons LazyGrid, I wrote a prototype that buffers requests inside the grid so that calls to the backend happens in a paged manner, with a page size defined by you. This way the binding code doesn’t require a masters degree in mathematics and is easier for your stack to optimize.
From the before-after code snippets below, you’ll see how much simpler things can get with this change - even though the framework doesn't yet calculate the page number. The limit parameter in the “after” code example will always be 100 as we configure it using the setPageSize method.
Note that both examples above already avoid reporting the size (~ Improvement idea 1), so you can’t write either of with default Vaadin releases today.
So, what do you think? Has the lazy data binding been an issue for you? Would these make you more productive? Before we get from prototyping to actual implementation, I want to hear your war stories and ideas about the subject. All channels accepted: fill in the anonymous survey about this topic or write comments to this blog. Or ping me directly with email or twitter and let's chat more!