Documentation versions (currently viewingVaadin 23)

You are viewing documentation for Vaadin 23. View latest documentation

Production Configuration

Enabling production mode for a Vaadin application is described in Deploying to Production. If your application uses Collaboration Kit, it requires some extra steps when you take your application to production. These steps are described here.

Before configuring your Vaadin application for production mode, you need to:

  1. Get a license file with a user quota.

  2. Configure where Collaboration Kit files are stored.

  3. Store the license file in the right location.

  4. Implement a LicenseEventHandler to get notified when the license needs to be updated.

Getting a Free "Universal" License File

All Vaadin applications receive a free 20 users per month quota with a universal license file. If you don’t have a commercial Vaadin subscription (Pro, Prime, or Enterprise), you can download the universal license file.

The name of the license file is ce-license.json. It informs Collaboration Kit that you are entitled to receive a quota of 20 users per month.

You can upgrade to a commercial license to increase your monthly user quota.

Getting a Commercial License File

If you need to use Collaboration Kit powered features for more than 20 users / month, request a commercial license file.

First, you need to have a commercial Vaadin subscription (Pro, Prime, or Enterprise) to request this license. Each Vaadin subscription offers a bundled quota of users per month. Visit, the official feature page to learn more about the bundled quotas.

To get your license, contact Vaadin. You can also request and purchase a larger quota of users than provided by your commercial Vaadin subscription. A starting package for 199 € / 500 users / month is available without the need for any other Vaadin commercial subscription.

The name of the license file is ce-license.json. It defines how many unique users can use collaborative features per month and when the license expires.

Configuring File Storage Location

Follow the steps in this section after you receive your license file.

You need to configure which directory should be used by Collaboration Kit to store files by setting the vaadin.ce.dataDir property. This directory is used by Collaboration Kit to automatically store usage data to keep track of users for each month. You should also put your ce-license.json file in the same directory for Collaboration Kit to find it.

You can configure the directory path by either:

  1. configuring the data directory in project files or

  2. passing it in as a parameter on the server startup.

If both are present, the server startup parameter is used.

Configuring the Data Directory in Project Files

Storing the path into the project files is a good way if you always deploy your application into the same environment and the folder doesn’t change.

Spring Applications

If you have a Spring application, you can provide a bean of type CollaborationEngineConfiguration from your main Spring class by annotating a method with the @Bean annotation and returning a configuration instance with the data directory path set using the setDataDir method.

public CollaborationEngineConfiguration ceConfigBean() {
    CollaborationEngineConfiguration configuration = new CollaborationEngineConfiguration(
            licenseEvent -> {
                // See <<ce.production.license-events>>
    return configuration;

Other Applications

If you have a non-Spring application, you can implement a VaadinServiceInitListener where you create a CollaborationEngineConfiguration instance and set it using the CollaborationEngine.configure() method.

public class MyVaadinInitListener implements VaadinServiceInitListener {

    public void serviceInit(ServiceInitEvent serviceEvent) {
        VaadinService service = serviceEvent.getSource();

        LicenseEventHandler licenseEventHandler = licenseEvent -> {
            // See Notifications for Updating the License

        CollaborationEngineConfiguration configuration = new CollaborationEngineConfiguration(
        CollaborationEngine.configure(service, configuration);


Then, you need to register the listener via Java Service Provider Interface (SPI) loading facility. You do this by providing a file, src/main/resources/META-INF/services/com.vaadin.flow.server.VaadinServiceInitListener with a fully qualified class name to your listener as content, for example,

The location of the configuration file
The location of the configuration file

Configuring the Data Directory on Server Startup

For another way, you can pass the data directory as a parameter on server startup. This way assumes that you have already a production-ready build available and want to run the package on the server. Read Deploying to Production to learn more about building your application for production.

Spring Boot Applications

You can set the data directory with the vaadin.ce.dataDir system property for Java, for example as follows on the command line:

java -Dvaadin.ce.dataDir=/Users/steve/.vaadin/collaboration-engine -jar my-app-1.0-SNAPSHOT.jar

The system property should be before the -jar parameter.

Other Servlet Containers

You can pass the data directory parameter as a context parameter to the servlet container. You should see your servlet container’s documentation on how to provide it. You need to set the vaadin.ce.dataDir context parameter. The value should be the directory path.

For example, you can pass the context parameter to Jetty as follows:

mvn jetty:run -Dvaadin.ce.dataDir=/Users/steve/vaadin/collaboration-engine/

See Configuration Properties for more information.

The directory should be both readable and writable by the user running the Vaadin application.

Placing the License File

After getting the license file and the data directory, you need to put the license file in that directory on the server. For example, if you configured the folder to be /Users/steve/vaadin/collaboration-engine/, you should place the license file so that the application can read it as /Users/steve/vaadin/collaboration-engine/ce-license.json.

Collaboration Kit uses the file to verify that you have a proper license. The application doesn’t require an internet connection to Vaadin servers to verify the license.

Providing a Data Directory for a Docker Container

It’s recommended to provide the data directory to a Docker container on runtime by either using a volume or a bind mount. It isn’t recommended to copy the license file into the container image, as the data directory is erased every time you deploy a new version of your application.

If you are deploying to a cloud provider, you may not have access to the host file system to be able to make use of bind mounts. Consult the documentation for your cloud provider to get instructions on how to set up and provide a volume to your application.

While a volume is preferred, if you have access to the host’s file system or want to test the Docker image locally, you can do it with a bind mount with the following steps:

  1. Set up a data directory on the host’s file system. For example: /Users/steve/.vaadin/collaboration-engine.

  2. Copy the ce-license.json file into the folder above.

  3. Pick a suitable folder within your Docker image where the container mounts the host folder. For example: /usr/app/ce.

  4. Configure your Dockerfile to start up the server with the vaadin.ce.dataDir parameter pointing to the internal folder. For example:

    java -Dvaadin.ce.dataDir=/usr/app/ce -jar /usr/app/app.jar
  5. Build the Docker image, for example (in the project directory):

    docker build --tag my-app .
  6. Start up the Docker container by giving the -v parameter mapping the host folder to the image folder. For example:

    docker run --name=myapp -dp 8080:8080 -v /Users/steve/.vaadin/collaboration-engine:/usr/app/ce myapp

When using volumes, you would replace the absolute path to the directory with the name of the volume, for example:

docker run --name=myapp -dp 8080:8080 -v myapp-volume:/usr/app/ce myapp

Notifications for Updating the License

The licensing model may cause collaborative features to be disabled for some of your application’s users. To avoid this situation, you need to get a new license if your old license is about to expire, or if your user base increases and the number of users exceeds the quota for one month.

To know when to update the license, you need to implement a license event handler for Collaboration Kit. Collaboration Kit can fire the following types of license events a maximum of once each during the license’s lifecycle:

  1. the first time the user quota is exceeded and the grace period begins (more details in Going Over the Quota),

  2. when the grace period ends,

  3. 30 days before the license expires, and

  4. when the license expires.

If you take care of updating the license when events 1 and 3 are fired, the other two events shouldn’t happen at all.

One potential way to handle the event is to send a message to any existing application monitoring system you might have. Another option is to send an email to the relevant people, for example, those who maintain the deployment and those who are responsible of the Collaboration Kit license. You need to ensure that your application notices and handles the events.

The listener can be configured when creating the CollaborationEngineConfiguration as described earlier in Configuring the Data Directory in Project Files.

LicenseEventHandler licenseEventHandler = licenseEvent -> {
    switch (licenseEvent.getType()) {
    sendEmail("Vaadin Collaboration Kit license needs to be updated",

In the above example, the license event handler logs the event messages using the SLF4J logging API, and sends an email. When it’s time to update the license, the message is logged as a warning. If the license isn’t updated in time, the message is logged as an error. The default event messages provide information of what has happened, how it affects the application, and what’s the recommended action to take.

Below is an example implementation of the sendEmail() method. It requires the javax.mail.mail package as a dependency.

private void sendEmail(String subject, String content) {
    // Replace the following information:
    String from = "";
    String password = "*****"; // Read, for example, from encrypted config
                               // file.
    String to = "";
    String host = "";

    Properties properties = System.getProperties();
    properties.put("", host);
    properties.put("mail.smtp.port", "465");
    properties.put("mail.smtp.ssl.enable", "true");
    properties.put("mail.smtp.auth", "true");

    Session session = Session.getInstance(properties, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(from, password);
    try {
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress(from));
                new InternetAddress(to));
    } catch (MessagingException e) {
        LOGGER.error(e.getMessage(), e);
Exception thrown if events aren’t handled
Collaboration Kit throws an exception in production mode if a configuration hasn’t been defined. The purpose is to make sure that your application handles the events, and to avoid the situation where the license expires by accident.

User Quota

Your license includes a quota for how many unique users are supported within a month, for example, a limit of 1.000 users. Collaboration Kit counts how many users use its features during each calendar month. The count of users starts over on the first day of each month.

Definition of a User

When you use any Collaboration Kit features, you have to provide a UserInfo object with a unique ID.

String userId = "";
String name = "Steve";
UserInfo userInfo = new UserInfo(userId, name);
CollaborationAvatarGroup avatarGroup = new CollaborationAvatarGroup(
        userInfo, "app");

Collaboration Kit records the ID of each user that accesses collaborative features in the ongoing month and counts towards your quota for the current month. Each user ID is counted only once per month.

Going Over the Quota

When you exceed the limit the first time, nothing changes from the user’s perspective. When that happens, Collaboration Kit starts a 30-day grace period, during which time the quota is ten times bigger. The grace period gives you time to react to exceeding your limit without impacting your application in any way. For example, if you have a license for a 500-user quota, your effective quota is 5.000 users during the grace period. After 30 days, your effective quota goes back to 500, and you won’t get another grace period until the next billing period.

If the number of users in a month exceeds 10x the quota during the grace period, or if it exceeds the normal quota after the grace period is over, the collaborative features are disabled for the excess users. Your application continues to work, but CollaborationAvatarGroup shows only the user’s own avatar, and forms built with CollaborationBinder don’t show edits made by other users. The users who are registered within the allowed quota have collaborative features available throughout the month.

Consider, for example, a situation where you have a quota of 500 users, you have used your grace period, and 520 users have used collaborative features this month. The first 500 users can collaborate throughout the month. Users from 501 through 520 can use the application, but it works as if Collaboration Kit wasn’t in use. They can only see their own presence and edits. When the calendar month changes, counting starts over, and the first 500 users again get full access for the whole month.

Entering the Grace Period

The engine enters the grace period when you have a higher demand than expected when getting the license. It’s recommended that you get a new license with a higher quota to have collaborative features available for all your users before the grace period expires. Contact Vaadin to get a new license file with a higher quota. You can change your quota at any time. When you replace the license file with the new one, Collaboration Kit resets your grace period. If you exceed your new quota in the future, you again receive a 30-day grace period.

Checking for User Access

You can determine whether a user has access by passing a callback to the requestAccess() method in the CollaborationEngine instance. The callback gets an AccessResponse instance as a parameter. You can call its AccessResponse::hasAccess() method to determine the user’s access. You can use the status to adapt the UI according to whether the user can use collaborative features.

For example:

UserInfo userInfo = new UserInfo("", "Steve");
CollaborationEngine.getInstance().requestAccess(userInfo, response -> {
Cache the results
To avoid calling this method multiple times per user, it’s suggested to cache the result during the login process, for example, in the session.

Limiting Collaborative Features to Some Users

Collaboration Kit only counts those users towards the quota whose UserInfo objects are passed to collaborative features.

You can limit usage to a subset of your users in two different ways:

  1. Only use Collaboration Kit in views that you have restricted with user access. For example, if you only use collaborative features in the admin views, only those users who access the admin views are counted.

  2. Check the details of the user before initializing the collaboration features. For example, by checking the role or privileges or the user, you can decide in code if the users should have collaborative features enabled or not.

An example of how to enable collaboration by checking user permissions:

User userEntity = userService.getCurrentUser();
if (userEntity.getRoles().contains(Role.ADMIN)) {
    UserInfo userInfo = new UserInfo(userEntity.getId(),
            userEntity.getName(), userEntity.getImageUrl());

    CollaborationAvatarGroup avatarGroup = new CollaborationAvatarGroup(
            userInfo, "avatars");