Vaadin 7 refresh views leads to error

Hi everybody!

Please note I do not want @PreserveOnRefresh since it preserves ALL states and that’s annoying (unless there is a way to turn off refresh state for certain Views).

I am using Vaadin navigator. I have (from the get go), a navigator in the UI, and create a LoginView(). The LoginView involves two text fields and a button. I click the button to authenticate. if authentication is correct, I add a new View using UI.getCurrent().getNavigator().addView(“mainscreen”, new MainView(String username)); and then UI.getCurrent().getNavigator().navigateTo(“mainscreen”);

This works fine. The MainView by the way (for simplciity and reproduction) only consists of a label with the username. However, when I refresh the browser page (in the main view), I get an error view. View not found, error view provider not found exception. What can I do to resolve this problem?

If i understood you correctly, you initialize the Navigator in the UI’s init method and add the MainView when the LoginEvent occurs.
When you refresh the page, the UI’s init method is executed again, so a new Navigator instance is created but the main view is not added again…Try to add your MainView also in the UI’s init method and set the username later via setter-Method (or enter Method of the view) or better, create a custom ViewProvider.

You understood me correctly. Thanks, I was quite vague, I was sleepy and had first day of school in 4 hours though…ew. First thing i do when I get home is check forum, and yay there’s an answer.

Okay thats a very valuable piece of info. I did not know that init is called again. But I wonder, is the UI reinitalized all together (completely new instance variables, for example?) or is the init method just rerun? I could store the MainView in an instance variable if the UI isn’t recreated altogether.

I do not think a setter method will alleviate the issue, however, because if the view is recreated (if the browser refresh is done), then the username will be reset ALSO. In fact, I am almost positive, I tried something along these lines.

How would I implement a custom ViewProvider? Sounds interesting. Maybe if you want to give a link to example code? Or write some yourself?

That would really help me. Thanks!

Hello. Okay it seems I have a cheeky solution, ironically using @PreserveOnRefresh. The reason I dislike this annotation is because it preserves ALL application states, which means sometimes exposed user data, confidential information, basically anything that should NOT be preserved. However, this is cool little trick I think works well, when working in multiple views.

@PreserveOnRefresh
public class MyUI extend UI {

    Navigator navigator;
    View currentView;
    
    @Override
    public void init(VaadinRequest request) {
        
        navigator = new Navigator(this, this);

        LoginView loginview = new LoginView();

        navigator.addView("", loginview);

        currentView = loginview;
        
        //Note, the login view is the first screen shown. It consists of a username/password
        //signin button, which authenticates user. If successful, it creates a new View based
        //on user-specific data. So LoginView has the following code statements:

        //MainView mainview = new MainView(usernameField.getValue());
        //UI.getCurrent().getNavigator().addView("main", mainview);

        
     
    }
    
    @Override
    public void refresh(VaadinRequest request) {
        
        //Basically if the current screen is the login page, and you refresh, it creates a new
        //instance, essentially nullifying @PreserveOnRefresh.
        
        //currentView can be constantly changed. For example, if I am in mainview, I can set
        //currentView to be mainview, and if I refresh the page, since currentView is not an 
        //instance of LoginView anymore, it will preserve state, thus hereby doing "selective
        //state preservation", based on the type of view. Obviously more specific parameters
        //such as specific things in the view can be refreshed while others aren't, but this
        //presents the general idea..
        
        if (currentView instanceof LoginView) {
            navigator.addView("", new LoginView());
            navigator.navigateTo("");
        }
    }

}