how to handle views/routers changes in V14 ?

In V7 I do this to control if an user is logged, if not it is redirected to LoginView


     getNavigator().addViewChangeListener(new ViewChangeListener() {
            @Override
            public boolean beforeViewChange(ViewChangeListener.ViewChangeEvent event) {
				if(!isLogged()) {
				//if not, redirected to login view
				 getNavigator().navigateTo("login");
				return false;
				}
				return true;
				
			}

How can I do this in v14? I can’t find something similar to Navigator, tried to implement BeforeEnterListener, NavigatorHandler but couldn’t achieve that control over views yet.

on this new proyect in v14, I have a main class, MainLayout and a few others view annotated with @Route(value = “orden”, layout = MainLayout.class), I want to force it to go to the router Login if is not logged yet.

PD: I don’t want to use Spring to handle this

Also tried this but is only triggered when changing between secondary views app/ → app/view1


UI.getCurrent().addBeforeEnterListener( evt ->

The way you describe at the end is usually the way to go. This code can be defined globally for all UIs, see [this tutorial]
(https://vaadin.com/learn/tutorials/securing-your-app-with-spring-security/setting-up-spring-security#_secure_router_navigation). The tutorial itself is about Spring, but that part can be used without spring as well (you just need to tell vaadin explitly where to find your VaadinServiceInitListener ([more info]
(https://vaadin.com/docs/v14/flow/advanced/tutorial-service-init-listener.html))).

However, I was not aware that this only works when switching views and not when manually entering the url (but maybe it does work and your method of finding out the login status has faults? I don’t know). Maybe this part is being done by [springs WebSecurityConfigurerAdapter]
(https://github.com/vaadin-learning-center/spring-secured-vaadin/blob/master/src/main/java/org/vaadin/paul/spring/app/security/SecurityConfiguration.java#L49) - I wouldn’t know how to do that without spring.

Thanks, VaadinServiceInitListener seems to be the earliest possible place to control and re-direct to a loginView

I could achieve what I wanted (for a week), now suddenly stop working and I am getting null instance of UI

This piece of code was working and stopped. UI.getCurrent is returning null

    @Override
    public void serviceInit(ServiceInitEvent event) {
        System.out.println("serviceInit...");
        event.addRequestHandler((session, request, response) -> {
            UI.getCurrent().addBeforeEnterListener(evt -> {

No matter how I try, every possible way to get an UI instance at this point is null or throws java.lang.IllegalStateException: Cannot access state in VaadinSession or UI without locking the session.

Complete class

public class ApplicationServiceInitListener implements VaadinServiceInitListener {

    public ApplicationServiceInitListener() {
        System.out.println("Init ApplicationServiceINitListener");
    }

    @Override
    public void serviceInit(ServiceInitEvent event) {
        System.out.println("serviceInit...");
        event.addRequestHandler((session, request, response) -> {
//            UI ui3 = event.getSource().findUI(request); //returns null
//            UI ui2 = session.getUIs().iterator().next(); // throws Illegal
            UI ui = UI.getCurrent();
            ui.addBeforeEnterListener(evt -> {
                Location location = evt.getLocation();
                if (isLogged()) {
                    if (location.getPath().equals("login")) {
                        //si se quiere ir a login, ya logeado, vuelve al inicio
                        evt.forwardTo("");
                        Notification.show("Ya te logeaste mono");
                    }
                } else {
                    if (!location.getPath().equals("login")) {
                        //if try to skip the login
                        evt.forwardTo("login");
                        Notification.show("No te hagas del vivo");
                    }
                }
            });
            return false;
        });
        event.getSource().addUIInitListener(evt -> {
            System.out.println("UI Init listener");
        });
    }

You should define the UI-beforeEnterListener in the UIInitListener. In the UIInitEvent you can call event.getUI() to get the ui instance.

public class ApplicationServiceInitListener implements VaadinServiceInitListener {

    public ApplicationServiceInitListener() {
        System.out.println("Init ApplicationServiceINitListener");
    }

    @Override
    public void serviceInit(ServiceInitEvent event) {
        System.out.println("serviceInit...");
       
        event.getSource().addUIInitListener(evt -> {
            System.out.println("UI Init listener");
			evt.getUI().addBeforeEnterListener(evt -> {
                Location location = evt.getLocation();
                if (isLogged()) {
                    if (location.getPath().equals("login")) {
                        //si se quiere ir a login, ya logeado, vuelve al inicio
                        evt.forwardTo("");
                        Notification.show("Ya te logeaste mono");
                    }
                } else {
                    if (!location.getPath().equals("login")) {
                        //if try to skip the login
                        evt.forwardTo("login");
                        Notification.show("No te hagas del vivo");
                    }
                }
            });
        });
    }
}

I realize you wrote earlier that using a BeforeEnterListener alone only works in some cases for you. I would tackle that issue instead and use this code, because the RequestHandler has no 100%-successful way of getting the current UI instance, because it can be that there is no UI set. The javadoc on the method VaadinService::findUI explains this better:

/**
 * Finds the {@link UI} that belongs to the provided request. This is
 * generally only supported for UIDL requests as other request types are not
 * related to any particular UI or have the UI information encoded in a
 * non-standard way. The returned UI is also set as the current UI (
 * {@link UI#setCurrent(UI)}).
 *
 * @param request
 *            the request for which a UI is desired
 * @return the UI belonging to the request or null if no UI is found
 */