Cannot override User Navigation handling (Vaadin 24.4)

Hi there,

The doc says:

If you want to manually handle navigation events, you can replace it by setting a handler for navigation events using history.setHistoryStateChangeHandler(HistoryStateChangeHandler) .

The problem is that if I set a custom HistoryStateChangeHandler when the UI is just initialized, the handler is overwritten by the internal logic of the UI class.

For example, how I set HistoryStateChangeHandler:

@Component("demo_CustomVaadinServiceInitListener")
public class CustomVaadinServiceInitListener implements VaadinServiceInitListener {

    private static final Logger log = LoggerFactory.getLogger(CustomVaadinServiceInitListener.class);

    @Override
    public void serviceInit(ServiceInitEvent serviceInitEvent) {
        VaadinService source = serviceInitEvent.getSource();
        source.addUIInitListener(this::uiInit);
    }

    private void uiInit(UIInitEvent uiInitEvent) {
        UI ui = uiInitEvent.getUI();
        History history = ui.getPage().getHistory();
        history.setHistoryStateChangeHandler(this::onHistoryStateChange);

    }

    private void onHistoryStateChange(History.HistoryStateChangeEvent event) {
        log.info("History state changed: {}", event.getLocation());
    }
}

The following code overwrites previously set HistoryStateChangeHandler: flow/flow-server/src/main/java/com/vaadin/flow/component/UI.java at main · vaadin/flow · GitHub

if (firstNavigation) {
    firstNavigation = false;
    getPage().getHistory().setHistoryStateChangeHandler( // <1>
            e -> renderViewForRoute(e.getLocation(), e.getTrigger()));

    if (getInternals().getActiveRouterTargetsChain().isEmpty()) {
        // Render the route unless it was rendered eagerly
        renderViewForRoute(location, navigationTrigger); // <2>
    }
}

1 - Overwrites HistoryStateChangeHandler
2 - Uses internal logic regardless HistoryStateChangeHandler

So it seems that the only way to override User Navigation handling is to override UI class, which is also challenging.

  1. com.vaadin.flow.server.communication.JavaScriptBootstrapHandler#createAndInitUI ignores passed UI class and creates com.vaadin.flow.component.UI
  2. Public BrowserLeaveNavigationEvent class doesn’t have public getters.

Both problems are not show-stoppers at first glance, but they require extra code copying and pasting.

Could you please advice the best way to completely handle user navigation using custom code?

Please, let me know if you need any additional information.

Regards,
Gleb