Most web applications are collaborative. You have multiple users, all working with the same underlying data in the database. However, in most existing business applications, this collaboration doesn't happen in real time, which can lead to mistakes, inconsistent data, and lost working time.
Why real-time collaboration is important
Consider a shopping list shared by two family members, Bob and Alice.
Bob logs in and adds some items to the list:
Bob |
1 Carton of milk 6 Bananas 12 Eggs |
While Bob is still logged in, Alice logs in and makes some modifications to the list:
Bob |
Alice |
1 Carton of milk 6 Bananas 12 Eggs |
1 Carton of milk 6 Bananas 18 Eggs 6 Apples 1 Bag of flour |
Bob doesn't see Alice's changes. He decides they don't need that many eggs, so he modifies the list:
Bob |
Alice |
1 Milk 6 Bananas 6 Eggs |
1 Milk 6 Bananas 18 Eggs 6 Apples 1 Bag of flour |
At this point, Bob gets a save conflict as Alice has already changed the same item.
We now have a situation where Bob, Alice, and the database all contain different data – none of it correct.
Now contrast that with this collaborative version of the same app. Bob can see that Alice is looking at the shopping list. Alice can let Bob know that she wants to add some things to the list. Bob can see Alice's changes in real time.
This time, there's no confusion, no error, and we only have one version of the shopping list that is correct.
This is what Vaadin Collaboration Engine does. It allows you to add real-time collaboration to your Vaadin app in just a few lines of code. The four steps below walk through the changes needed.
1. Enable Collaboration Engine
Vaadin 20 includes Collaboration Engine by default. If you are using Vaadin 14, you need to add the dependency to your pom.xml file:
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>collaboration-engine</artifactId>
<version>3.1.0</version>
</dependency>
Next, add a @Push
annotation on your Application.java
class to enable a two-way web socket connection.
@Push
@SpringBootApplication
public class Application extends SpringBootServletInitializer implements AppShellConfigurator {
public static void main(String[] args) {
LaunchUtil.launchBrowserInDevelopmentMode(SpringApplication.run(Application.class, args));
}
}
You can now start to use Collaboration Engine.
2. Identify and display online users
Collaboration Engine uses a UserInfo object to identify users. Create a UserInfo object based on your authenticated user:
var userInfo = new UserInfo(user.getId(), user.getName(), user.getAvatar());
Only the ID is required, but defining the name and avatar will improve the collaboration experience.
You can now display online users in a CollaborationAvatarGroup by passing in the UserInfo object and a topic:
var avatars = new CollaborationAvatarGroup(userInfo,
"shopping-list");
The topic is a string that defines the context or scope of collaboration. For example, the topic could be:
- "app" if you are showing all online users in the entire app
- "shopping-list-chat" if you have a chat on a specific view
- "item/12" for collaborative editing of a specific item
3. Add context-aware discussions
You can add a context-specific discussion with the CollaborationMessageList and CollaborationMessageInput components:var messageList = new CollaborationMessageList(userInfo, "shopping-list-chat");
var messageInput = new CollaborationMessageInput(messageList);
var chatLayout = new VerticalLayout(
messageList,
messageInput
);
Remember to define an appropriate topic to scope the chat to the correct context.
4. Enable collaborative form editing
You can turn an existing form that uses Binder into a collaborative form by using CollaborationBinder instead:
CollaborationBinder<ShoppingListItem> binder = new CollaborationBinder<>(
ShoppingListItem.class, userInfo);
CollaborationBinder does not use the
readBean
/setBean
API that Binder
uses. Instead, you should define the topic and a method that provides the initial value. This way, binder
will use the shared value, if one exists, and use the provider method to initialize itself, if needed.public void setItem(long id) {
binder.setTopic("item/" + id, () -> service.findById(id));
}
You can find the source code for the Shopping List app on GitHub.
Next steps
In addition to these built-in components, the Collaboration Engine Topic API supports creating shared data structures that you can use to synchronize any other data you need between all online clients.
Read the Collaboration Engine Docs for more help on how to enable collaboration in your Flow app.
Don't have a flow app yet? No problem! You can configure and download a starter project with Collaboration Engine installed from start.vaadin.com.