Real-Time Chat and Commenting Components

You can add a real-time chat to your application by using the CollaborationMessageList and CollaborationMessageInput components.

Example of a CollaborationMessageList and CollaborationMessageInput

They enhance the regular MessageList and MessageInput components by automatically synchronizing the messages for all users connected to the same topic. The message list only renders the submitted messages, while the message input provides controls for submitting new messages. Here’s an example of setting them up:

User userEntity = userService.getCurrentUser();
UserInfo userInfo = new UserInfo(userEntity.getId(),
        userEntity.getName(), userEntity.getImageUrl());
String topicId = "general";

CollaborationMessageList messageList = new CollaborationMessageList(
        userInfo, topicId);
CollaborationMessageInput messageInput = new CollaborationMessageInput(
        messageList);
Note
Example classes
User and UserService are application-specific example classes, and not part of the Collaboration Engine API.

The CollaborationMessageList constructor takes two arguments: the information about the end user associated with this session, and a topic id. The user info is used to render the user name and avatar in the messages submitted by this user. Refer to the CollaborationAvatarGroup documentation for more details on how the avatars are rendered, or how to load images from a backend with the setImageProvider() method.

The topic id works in the same way as for other Collaboration Engine features. The data in Collaboration Engine is shared among those users who are connected to the same topic. With these components, you can consider the topic as a chat room. In the example above, the topic id is hard-coded as "general", which means that every user in this view sees each others' messages. You can dynamically change the topic with the setTopic() method, for example when the user makes a selection in the UI.

CollaborationMessageInput takes the message list component as its constructor argument. It hooks up with the list, to submit messages to its current topic. When the list component has null topic id, no messages are displayed, and the connected message input will be automatically disabled.

After constructing the components, the last required step is to place them somewhere in your view. Here’s an example of placing the message list and input on top of each other in a layout with a defined size:

VerticalLayout chatLayout = new VerticalLayout(messageList,
        messageInput);
chatLayout.setHeight("500px");
chatLayout.setWidth("400px");
chatLayout.expand(messageList);
messageInput.setWidthFull();
add(chatLayout);

Persisting Messages

The topic data in Collaboration Engine is stored only in the application memory. This applies also to messages in a CollaborationMessageList, which means that all the submitted messages will be lost when restarting the server.

To solve this issue, you can provide a CollaborationMessagePersister to store the messages in your own backend as described in the Message Manager documentation (this component uses the manager internally).

You can set the message persister in the message list’s constructor:

CollaborationMessageList createWithPersister(MyMessagePersister persister) {
    return new CollaborationMessageList(userInfo, "general", persister);
}

Using Custom Input Components

Instead of using the provided CollaborationMessageInput component, you can also configure your own component to submit messages. The component can be registered with CollaborationMessageList::setSubmitter().

The following example shows how to submit messages with the TextField and Button components:

TextField field = new TextField("Message");
Button button = new Button("Submit");
button.setEnabled(false);

messageList.setSubmitter(activationContext -> {
    button.setEnabled(true);
    Registration registration = button.addClickListener(
            event -> activationContext.appendMessage(field.getValue()));
    return () -> {
        registration.remove();
        button.setEnabled(false);
    };
});

The setSubmitter() method takes a callback; Collaboration Engine calls it when a new topic connection is established (topic ID is set to a non-null value). This callback should be used to set up any listeners for submitting new messages to CollaborationMessageList through the provided ActivationContext. The callback should return another callback for clean-up when the topic connection is deactivated (topic ID is changed). Note how the submit button is enabled only when there’s an active topic connection.

Tip
Submit messages through MessageManager
Messages can also be submitted to the list programmatically using a MessageManager instance with the same topic ID, as described in the Message Manager documentation.

Customizing Messages

CollaborationMessageList enables changing the properties of MessageListItem items after they are generated. You can do that by providing a MessageConfigurator.

The following example shows how to use a message configurator to add a custom style to the current user’s messages:

CollaborationMessageList collaborationMessageList =
        new CollaborationMessageList(userInfo, topicId);
collaborationMessageList.setMessageConfigurator((message, user) -> {
    if (user.equals(localUser)) {
        message.addThemeNames("current-user");
    }
});

Please refer to Styling in Message List documentation for details on how to style messages based on the theme.

The message configurator can also be used to change the text content of messages, for example, to censor certain words in messages, as is done in the following example.

CollaborationMessageList collaborationMessageList =
        new CollaborationMessageList(userInfo, topicId);
collaborationMessageList.setMessageConfigurator((message, user) -> {
    // Example: Replace all occurrences of "badword" with "***"
    String censored = message.getText().replaceAll("badword", "***");
    message.setText(censored);
});