Heartbeat setting for Vaadin push

Hi!

A user is reporting an error that sometimes occurs when working with our internal Vaadin Flow application. He says that after just a minute of changes he could no longer save his work.
We are using @Push and Vaadin 25


(the missing favicon will be fixed and not related)

The application is deployed on Azure App Service and after consulting AI I got recommendation to lower the heartbeat interval to keep the connection live.

Not sure if it would help but I wanted to give it a try but the suggested way of changing it seems overly complicated, isn’t there an easier way to configure the Atmosphere heartbeat with Vaadin?

@Configuration
public class PushConfiguration {

  // Naming the bean "servletRegistrationBean" cleanly overrides Vaadin's default Spring Boot
  // auto-configuration
  @Bean(name = "servletRegistrationBean")
  public ServletRegistrationBean<SpringServlet> customVaadinServlet(SpringServlet servlet) {
    ServletRegistrationBean<SpringServlet> registration =
        new ServletRegistrationBean<>(servlet, "/*");

    // Force the Heartbeat Interceptor into the Vaadin Servlet
    registration.addInitParameter("org.atmosphere.cpr.AtmosphereInterceptor",
        "org.atmosphere.interceptor.HeartbeatInterceptor");
    registration.addInitParameter(
        "org.atmosphere.interceptor.HeartbeatInterceptor.clientHeartbeatFrequencyInSeconds", "60");

    // Ensure async is supported for websockets
    registration.setAsyncSupported(true);
    registration.setName("springServlet"); // Required so internal Spring routing doesn't break
    return registration;
  }
}

Not really. It is sort of easy already now, it is just that configuring web init parameters has a bit clumsy logistics in Spring Boot as you are not overriding servlet and cannot use normal servlet init parameter annotation. As you see in vanilla app the same thing looks much simpler: vaadin-create23/vaadincreate-ui/src/main/java/org/vaadin/tatu/vaadincreate/Servlet.java at master · TatuLund/vaadin-create23 · GitHub

Thanks for quick response.

The initial suggestion that AI gave me was incorrect, but this seems to work:

import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class PushConfiguration {

  @Bean
  public ServletContextInitializer pushHeartbeatInitializer() {
    return servletContext -> {
      servletContext.setInitParameter("heartbeatInterval", "120");
      servletContext.setInitParameter("org.atmosphere.cpr.AtmosphereInterceptor",
          "org.atmosphere.interceptor.HeartbeatInterceptor");
      servletContext.setInitParameter(
          "org.atmosphere.interceptor.HeartbeatInterceptor.clientHeartbeatFrequencyInSeconds",
          "60");
    };
  }
}

We use push to show progress in UI grids, when we load data in background tasks on the server.

If the user has an unreliable network would it be better to switch Push to Long Polling?

Reading this it seems it should downgrade automatically though: Websocket transport downgraded to long-polling after being disconnected for some time · Issue #20747 · vaadin/flow

It downgrades only if the websocket cannot be established at all after several attempts. But if the WebSocket channel is established but then dies unexpectedly, Atmosphere will not immediately fall back to long-polling.

Ok, so what is your recommendation regarding Push vs Long Polling?
We have around 10 daily users and this error has occurred 8 times this month.

If you are mainly pushing Grid updates, the payload will be larger, and the benefit of the WebSocket smaller header size is not so big. WebSocket is better for small frequent pushes. With bigger push loads there is the performance difference is neglible.

1 Like