Binding Spring View Provider into Navigator

Hi guys, i’m just starting new project vaadin 8.
i have 2 navigator which are Main Navigator (changing view from Login View to Dashboard View) and Menu Navigator (changing Dashboard content into sub view).
The problem is, when i’m binding Menu Navigator with Spring View Provider which one i’m binding it from Main Page (UI Scope annotation). The content still blank and it’s show this message at application log :

“The Navigator used does not extend SpringNavigator. View scope support may be limited, and future versions of Vaadin Spring may remove support for using a plain Navigator”.

But when i’m changing Spring View Provider with a new instance of ClassBasedViewProvider (i’m already registered every sub view), my Menu Navigator can’t find viewId of my sub view.

Could someone tell me why i’m not success changing content from Menu Navigator?

MenuNavigator.java (i’m marking a new instance of classbasedviewprovider)

[code]
package com.aribanilia.vapp.framework;

import com.aribanilia.vapp.entity.TblMenu;
import com.aribanilia.vapp.loader.MenuLoader;
import com.vaadin.navigator.Navigator;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewProvider;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.spring.navigator.SpringViewProvider;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.UI;
import org.springframework.beans.factory.annotation.Autowired;

@UIScope
public class MenuNavigator extends Navigator {

private MenuLoader menuLoader;

@Autowired
public MenuNavigator(final MenuLoader menuLoader, final ComponentContainer content, final SpringViewProvider viewProvider) {
    super(UI.getCurrent(), content);
    this.menuLoader = menuLoader;
    addProvider(viewProvider);

// initViewProviders();
}

// private void initViewProviders() {
// for (TblMenu menu: menuLoader.getAuthorizedMenu()) {
// Class<? extends View> c = menuLoader.getView(menu);
// if (c == null)
// continue;
// ViewProvider viewProvider = new ClassBasedViewProvider(menu.getMenuId(), c);
// addProvider(viewProvider);
// }
// }
}
[/code]MenuComponent .java (where i put listener on my menu, this class called from MainPage.java)

package com.aribanilia.vapp.framework;

import com.aribanilia.vapp.entity.TblMenu;
import com.aribanilia.vapp.entity.TblUser;
import com.aribanilia.vapp.loader.MenuLoader;
import com.aribanilia.vapp.service.SessionServices;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.ThemeResource;
import com.vaadin.server.VaadinSession;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.spring.navigator.SpringViewProvider;
import com.vaadin.ui.*;
import com.vaadin.ui.themes.ValoTheme;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;


@UIScope
public class MenuComponent extends CustomComponent {
    private MenuNavigator menuNavigator;
    private MenuLoader menuLoader;
    private SessionServices servicesSession;
    private MenuBar.MenuItem settingsItem;

    public static final String ID = "menu";
    private static final String STYLE_VISIBLE = "valo-menu-visible";
    private static final Logger logger = LoggerFactory.getLogger(MenuComponent.class);

    @Autowired
    public MenuComponent(MenuLoader menuLoader, SessionServices servicesSession, final ComponentContainer content, final SpringViewProvider viewProvider) {
        this.menuLoader = menuLoader;
        this.servicesSession = servicesSession;

        if (getCurrentUser() != null) {
            setPrimaryStyleName("valo-menu");
            setId(ID);
            setSizeUndefined();

            this.menuNavigator = new MenuNavigator(menuLoader, content, viewProvider);
            setCompositionRoot(buildContent());
        }
    }

    private Component buildContent() {
        final CssLayout menuContent = new CssLayout();
        menuContent.addStyleName("sidebar");
        menuContent.addStyleName(ValoTheme.MENU_PART);
        menuContent.addStyleName("no-vertical-drag-hints");
        menuContent.addStyleName("no-horizontal-drag-hints");
        menuContent.setWidth(null);
        menuContent.setHeight("100%");

        menuContent.addComponent(buildTitle());
        menuContent.addComponent(buildUserMenu());
        menuContent.addComponent(buildToggleButton());
        menuContent.addComponent(buildMenuItem());

        return menuContent;
    }

    private Component buildTitle() {
        Label logo = new Label("QuickTickets <strong>Dashboard</strong>",
                ContentMode.HTML);
        logo.setSizeUndefined();
        HorizontalLayout logoWrapper = new HorizontalLayout(logo);
        logoWrapper.setComponentAlignment(logo, Alignment.MIDDLE_CENTER);
        logoWrapper.addStyleName("valo-menu-title");
        logoWrapper.setSpacing(false);
        return logoWrapper;
    }

    private TblUser getCurrentUser() {
        return VaadinSession.getCurrent()
                .getAttribute(TblUser.class);
    }

    private Component buildUserMenu() {
        final MenuBar settings = new MenuBar();
        settings.addStyleName("user-menu");
        final TblUser user = getCurrentUser();
        settingsItem = settings.addItem("",
                new ThemeResource("img/logo.jpg"), null);
        settingsItem.addItem("Edit Profile", menuItem ->  {
//                ProfilePreferencesWindow.open(user, false);
            Notification.show("Edit Profile Clicked");
        });
        settingsItem.addItem("Preferences", menuItem ->  {
//                ProfilePreferencesWindow.open(user, true);
            Notification.show("Preferences Clicked");
        });
        settingsItem.addSeparator();
        settingsItem.addItem("Sign Out", menuItem ->  {
            VaadinSession.getCurrent().setAttribute(TblUser.class.getName(), null);
            getUI().getNavigator().navigateTo(LoginPage.VIEW_NAME);
        });
        return settings;
    }

    private Component buildToggleButton() {
        Button valoMenuToggleButton = new Button("Menu", event -> {
            if (getCompositionRoot().getStyleName()
                    .contains(STYLE_VISIBLE)) {
                getCompositionRoot().removeStyleName(STYLE_VISIBLE);
            } else {
                getCompositionRoot().addStyleName(STYLE_VISIBLE);
            }
        });
        valoMenuToggleButton.setIcon(FontAwesome.LIST);
        valoMenuToggleButton.addStyleName("valo-menu-toggle");
        valoMenuToggleButton.addStyleName(ValoTheme.BUTTON_BORDERLESS);
        valoMenuToggleButton.addStyleName(ValoTheme.BUTTON_SMALL);
        return valoMenuToggleButton;
    }

    private Component buildMenuItem() {
        CssLayout menuItemsLayout = new CssLayout();
        menuItemsLayout.addStyleName("valo-menuitems");
        try {
            if (!validateUserSession()) {
                return null;
            }
            for (final TblMenu view : menuLoader.getAuthorizedMenu()) {
                AbstractScreen screen = menuLoader.getScreen(view.getMenuId());
                if (screen == null) {
                    logger.error("Screen Error : " + view.getMenuClass());
                    continue;
                }
                Button menuItemComponent = new Button();
                menuItemComponent.setPrimaryStyleName(ValoTheme.MENU_ITEM);
                menuItemComponent.setCaption(view.getMenuName().substring(0, 1).toUpperCase()
                        + view.getMenuName().substring(1));
                menuItemComponent.addClickListener(event -> {
                    menuNavigator.navigateTo(view.getMenuId());
                });
                menuItemsLayout.addComponent(menuItemComponent);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return menuItemsLayout;
    }

    private boolean validateUserSession() throws Exception {
        TblUser user = VaadinSession.getCurrent().getAttribute(TblUser.class);
        String sessionId = VaadinSession.getCurrent().getSession().getId();
        if (!servicesSession.sessionCheck(user.getUsername(), sessionId)) {
            Notification.show("Anda telah keluar", "Anda Telah Keluar/Login dari Komputer Lain!", Notification.Type.HUMANIZED_MESSAGE);
            VaadinSession.getCurrent().close();
            return false;
        }
        return true;
    }

    @Override
    public void attach() {
        super.attach();
    }

}

MainPage.java

package com.aribanilia.vapp.framework;

import com.aribanilia.vapp.loader.MenuLoader;
import com.aribanilia.vapp.service.SessionServices;
import com.vaadin.navigator.View;
import com.vaadin.spring.annotation.SpringView;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.spring.navigator.SpringViewProvider;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.HorizontalLayout;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;

@UIScope
@SpringView(name = MainPage.VIEW_NAME)
public class MainPage extends HorizontalLayout implements View {
    public static final String VIEW_NAME = "main";

    @Autowired private MenuLoader menuLoader;
    @Autowired private SessionServices servicesSession;
    @Autowired private SpringViewProvider viewProvider;

    @PostConstruct
    public void init() {
        setSizeFull();
        addStyleName("mainview");
        setSpacing(false);

        // Create Content
        final ComponentContainer content = new CssLayout();
        content.addStyleName("view-content");
        content.setSizeFull();

        final MenuComponent menuComponent = new MenuComponent(menuLoader, servicesSession, content, viewProvider);
        addComponent(menuComponent);
        addComponent(content);
        setExpandRatio(content, 1.0f);
    }

}

Thank you.

I think you are trying to construct this in a bit odd way. I wouldn’t make custom Navigator class by extending Navigator.

The proper way to use Navigator in Vaadin with Spring, is to autowire, SpringViewProvider, NavigationManager and MainView in your main UI. Since you autowire many, you can do constructor autowiring.

Each navigable view you create should implement ViewDisplay and be annotated as @SpringView(name = “myview”) and autowire NavigationManager if you need to e.g. logout in main view. If you use access control in views, you need to autowire SecuredViewAccessControl in each as well.

One good source to check how to implement this is to download the Bakery app starter Spring version at vaadin.com/start.

Hi Tatu,

> Each navigable view you create should implement ViewDisplay...

Shouldn’t the navigable views implement View interface instead?

Best regards,
Erik