Security context aware and buffered event dispatching for asynchronous UI updates with Vaadin
Often there is the requirement to push data updates from the server to the client. Imagine a chat app showing incoming messages in the client's browser. New messages should get displayed automatically without polling, the user shouldn't need to trigger some action to fetch new messages. In general, Vaadin UI push updates are pretty straightforward to implement by default, but there are some special cases we have to deal with.
In this article I want to show you a way to achieve asynchronous UI updates with Vaadin without data flooding or overloading the server-to-client connection when many concurrent push requests arrive. In addition, if you use Spring Security with Vaadin, we probably want to have access to the user's security context to authorize push updates before they get dispatched to the client's browser.
First, let me describe the environment of one of my larger projects my colleagues and I are working on. I think this project is a good production example for server-to-client push. We use Apache Kafka as a centralized event streaming platform. The whole truth is stored in Kafka in the form of domain events. We have a few self-contained services (SCS) powered by Vaadin and Spring Boot. For example, when a stream listener of some SCS consumes a domain event, the users get notified immediately about the data change via server push.
Let's concentrate on the important part. Imagine each inbound event would trigger an asynchronous UI update. What do you think happens if many events get consumed concurrently (> 1.000)? — In the best case this causes an unnecessary high server and client/browser load, in the worst case our app is going to crash. In event-driven architectures it's common to deal with a huge number of messages/events.
For Vaadin 14+ there is no existing solution for this problem as I know. Conventional event buses like Guava aren't going to help here because they don't offer buffering or security context awareness out-of-the-box.
Buffering
Buffering: periodically gather items emitted by an Observable into bundles and emit these bundles rather than emitting the items one at a time
To avoid triggering a UI update for each inbound domain event, one could use buffering. So we introduced a simple class called
UiAwareBufferingEventDispatcher
. Our event dispatcher collects all incoming events within a defined time span. Then it emits just one
event containing a list of all collected events to the consuming Vaadin components:
The consuming component can decide how to handle the buffered events. For example, if the component triggers a simple user notification - like "New data available" - just the last buffered event in the list will be enough most of the time. It depends on the use case if none, one, multiple or all events are interesting for the component or view.
Under the hood we use RxKotlin for buffering, a great library for reactive programming:
I've published a demo project containing the full code on GitHub:
- https://github.com/ajgassner/vaadin-playground/tree/master/buffering-event-dispatcher
- UiAwareBufferingEventDispatcher.kt
Spring's SecurityContext
awareness
The following snippet shows a sample of a consuming view/component. When an event arrives, the session's SecurityContext
is available in the async handler.
The event dispatcher is able to access the component's underlying HTTP session and
sets the thread-bound SecurityContext
before the handler gets executed:
I hope you can benefit a bit from this blog post. The code is MIT-licensed, so feel free to use it in your projects!