2

I'm trying to put together a simple application using Vaadin + Spring Boot with just two views: login and dashboard. I'm using pieces of code from the Vaadin Dashboard demo. There is this method in the DashboardUI class:

private void updateContent() {
    User user = (User) VaadinSession.getCurrent().getAttribute(
            User.class.getName());
    if (user != null && "admin".equals(user.getRole())) {
        // Authenticated user
        setContent(new MainView());
        removeStyleName("loginview");
        getNavigator().navigateTo(getNavigator().getState());
    } else {
        setContent(new LoginView());
        addStyleName("loginview");
    }
}

As you see the views are instantiated via the new keyword. Since I'm using Spring I would like the container take care of that. But I cannot figure out how to have the views injected by Spring.

JAL
  • 41,701
  • 23
  • 172
  • 300
Pavel Bastov
  • 6,911
  • 7
  • 39
  • 48

3 Answers3

1

Annotate your view with @VaadinUIScope and @VaadinComponent. And then you can use @Autowired to inject your view.

Jumper
  • 133
  • 2
  • 15
1

You should probably setup two UI classes i.e LoginUI.class and MainUI.class. Have Spring Security redirect unauthorized to /login and authorized to /

LoginUI.class

@Theme("valo")
@SpringUI(path = "login")
@PreserveOnRefresh 
public class LoginUI extends UI {

   private SpringViewProvider viewProvider;

   @Autowired
   public LoginUI(SpringViewProvider viewProvider) {
      this.viewProvider = viewProvider;
   }

   @Override
   protected void init(VaadinRequest request) {
      Navigator navigator = new Navigator(this, this);
      navigator.addProvider(viewProvider);
      navigator.navigateTo(LoginView.VIEW_NAME);
   }

}    

MainAppUI.class

@Theme("valo")
@SpringUI
@PreserveOnRefresh
public class MainAppUI extends UI {

    private SpringViewProvider viewProvider;

    @Autowired
    public AppUI(SpringViewProvider viewProvider) {
       this.viewProvider = viewProvider;
    }

    @Override
    protected void init(VaadinRequest request) {

        getPage().setTitle("Main App");

        setSizeFull();

        Navigator navigator = new Navigator(this, viewDisplay);
        navigator.addProvider(viewProvider);

        setContent();//viewport

       navigator.navigateTo(DashboardView.VIEW_NAME);
    }
}

Then just use @SpringView(name = "moduleOne", ui = MainAppUI.class) on your module views for your app as suggested by Morfic to have the main navigator and module views registered only when a user has logged in to save on resources.

OchiengOlanga
  • 135
  • 1
  • 3
  • 11
0

Note: Taking a look at that example it seems that they're not actually using views & navigator, they're somewhat faking them. If you want to proceed on the same path you can simply autowire the fake views in the UI instead of using the navigator as below.

The Vaadin-spring boot wiki offers an introduction to this by the use of:

1) @SpringUI with autowired SpringViewProvider

@Theme("valo")
@SpringUI
public class MyVaadinUI extends UI {

    // we can use either constructor autowiring or field autowiring
    @Autowired
    private SpringViewProvider viewProvider;

    @Override
    protected void init(VaadinRequest request) {
        // other init stuff
        Navigator navigator = new Navigator(this, viewContainer);
        navigator.addProvider(viewProvider);
    }
}

2) @SpringView

@SpringView(name = DefaultView.VIEW_NAME)
public class DefaultView extends VerticalLayout implements View {
    public static final String VIEW_NAME = "";

    @PostConstruct
    void init() {
        addComponent(new Label("This is the default view"));
    }

    @Override
    public void enter(ViewChangeEvent event) {
        // the view is constructed in the init() method()
    }
}

For the decision whether the user should be redirected to the login view, or the other ones, I usually use a ViewChangeListener, something along the lines of:

navigator.addViewChangeListener(new ViewChangeListener() {
    @Override
    public boolean beforeViewChange(ViewChangeEvent event) {
        if (VaadinSession.getCurrent().getAttribute("user") == null) {
            navigator.getDisplay().showView(loginView);
            return false;
        } else {
            return true;
        }
    }

    @Override
    public void afterViewChange(ViewChangeEvent event) {
        // meh
    }
});
Morfic
  • 15,178
  • 3
  • 51
  • 61
  • It's not that I want to proceed the way they are doing it. What would be a better option? How would I do it with a navigator? Is it possible to have one navigator and navigate between those two views, and then, when the user is logged in, use it to navigate inside the dashboard? – Pavel Bastov Oct 03 '15 at 06:48
  • Any approach is valid and in the end it really depends what you need/want to do. Take a look at the [reasoning behind the navigator](https://vaadin.com/book/vaadin7/-/page/advanced.navigator.html) that the Vaadin book offers, think about what you're after, and then decide on which path to follow. – Morfic Oct 04 '15 at 10:43