Vaadin 7 Navigator problem

I’m trying to use Navigator, but it’s always failing when calling the constructor. First I tried this:

https://vaadin.com/wiki/-/wiki/Main/Creating%20a%20bookmarkable%20application%20with%20back%20button%20support

But it fails with IllegalArgumentException, when calling the constructor.

Then I tried with a VerticalLayout as ComponentContainer (from my main UI class’s init method):

ComponentContainer myViewContainer = new VerticalLayout();
this.setContent(myViewContainer);

Navigator navigator = new Navigator(this, myViewContainer);

But it fails with the same exception:

java.lang.IllegalArgumentException: Trying to navigate to an unknown state ‘’ and an error view provider not present
at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:525)
at com.vaadin.ui.UI.doInit(UI.java:528)
at com.vaadin.server.AbstractCommunicationManager.getBrowserDetailsUI(AbstractCommunicationManager.java:2457)
at com.vaadin.server.AbstractCommunicationManager.handleBrowserDetailsRequest(AbstractCommunicationManager.java:2352)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:325)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:201)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

jan. 18, 2013 9:26:08 DE org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Fitman Cloud]
in context with path
[/FitmanCloud] threw exception [java.lang.IllegalArgumentException: Trying to navigate to an unknown state ‘’ and an error view provider not present]
with root cause
java.lang.IllegalArgumentException: Trying to navigate to an unknown state ‘’ and an error view provider not present
at com.vaadin.navigator.Navigator.navigateTo(Navigator.java:525)
at com.vaadin.ui.UI.doInit(UI.java:528)
at com.vaadin.server.AbstractCommunicationManager.getBrowserDetailsUI(AbstractCommunicationManager.java:2457)
at com.vaadin.server.AbstractCommunicationManager.handleBrowserDetailsRequest(AbstractCommunicationManager.java:2352)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:325)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:201)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:45)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

Did something basically changed since that beta version? I tried it with beta11 and rc1.

Now I tried with:

VerticalLayout layout = new VerticalLayout();
ViewDisplay viewDisplay = new Navigator.ComponentContainerViewDisplay(layout);

Navigator navigator = new Navigator(this, viewDisplay);

And the same exception is thrown.

And as I can see, with beta9 it works well.

Your error-message says that the state “” is unknown. So I guess, that you have given your first (| primary | main) view a name. Try

navigator.addView("", myMainView);

Ok, but I cannot call ‘add’ method, before calling Navigation’s constructor, and this error occurs when calling constructor.

No, it doesn’t happen in the constructor.

I don’t have a Vaadin 7 ready here, so I can not check it, but my next assumption would be that you should first set up the Navigator and then call setContent() afterwards.

When I tried first, I didn’t call setContent, but the same error occured. And strangely, everything works well with beta9, but not with beta11 or rc1.

The reason for this is that since one of the later beta versions, the Navigator registers itself as a UI’s Navigator object in its constructor. Navigator’s navigateTo() method is now called automatically for you during your UI’s initialization. Therefore, a Navigator has to be fully configured at the end of method UI.init().

Tobias is right with what he said. You have to add your views to the Navigator in the init() method. The exception you got was thrown after your init() method and thus after Navigator’s constructor (Have a look at com.vaadin.ui.UI.doInit(VaadinRequest, int) to verify this).

Thanks, now I added views, and navigated to one of them, and it works.

Can we get some more insight here – what’s the logic for how Vaadin 7 looks for the “default” or first or whatever view to show after init() is done? I.e. the state is “” (empty) so how does one SET the state in init() so it navigates to the proper view to show from the ones I did an addView() to? I have a very simple (and normal) pattern where I have a loginView and a mainView … and the default view at init() (I would think?) is the login view…

I followed the tutorial on how to do login processing in views, etc. but that hasn’t been updated for RC1 (or am I on RC2?) that I can tell, in that the sample as it sits doesn’t work and gets the new “500 illegalStateException” thing …

Here is my init …

	// Create the navigator use for this UI
	navigator = new Navigator(this, this) ;
	
	// Now add the possible views (we have 2 so far) 
	
	navigator.addView(  "" , new LoginView( navigator, MainView.NAME) );		// This appears to be the default view initialized after init()
	
	navigator.addView( MainView.NAME, new MainView(navigator)) ;
	
	navigator.addView( LoginView.NAME, new LoginView( navigator, MainView.NAME));

	// we'll handle permissions with a listener here, you could also do
    // that in the View itself.
    navigator.addViewChangeListener(new ViewChangeListener() {

        @Override
        public boolean beforeViewChange(ViewChangeEvent event) {
        	if (((JTOnlineUI)UI.getCurrent()).getLoggedInUser() == null) {
        		// Show to LoginView instead, pass intended view
        		String fragmentAndParameters = event.getViewName();
        		if (event.getParameters() != null) {
        			fragmentAndParameters += "/";
        			fragmentAndParameters += event.getParameters();
        		}
        		navigator.getDisplay().showView(new LoginView(navigator,
        				fragmentAndParameters));
        		return false;

        	} else {
        		return true;
        	}
          }
              
        @Override
        public void afterViewChange(ViewChangeEvent event) {
        }          
        
    });
    
    Until I added the (to me bogus) addView("") thing, which adds an identical view to the loginView I was getting the 500... 

So how do I set the initial thing to be the login page or am I thinking wrong about this new navigation system?

Hi,

Could you just try navigator.navigateTo(“login”) for instance? You shouldn’t need to add a bogus “” view, just forward the user to the view you wish.

Hi,

it seems that following
this tutorial
, any view which is added and then called through the navigator object MUST implement View:

 /** Main view with a menu */
    public class MainView extends VerticalLayout implements View {

/*Create your class as usual here*/

 }

Cheers

Hi,
Sorry to re-visit this topic, but I’m seeing the dreaded “java.lang.IllegalArgumentException: Trying to navigate to an unknown state ‘main’ and an error view provider not present” message when I hit the RELOAD button in the browser while I’m in this “main” view.

Like Steven, I have a “login” view and a “main” view. In my init() method of my UI class (MyUI) I create an instance of the Navigator class and call:
navigator.addView(“”, new LoginView(MyUI.this));
In my LoginView’s handler for the “Login” button click, I check for correct login and then add the “main” view and navigate to it:
navigator.addView(“main”, new MainView(MyUI.this));
navigator.navigateTo(“main”);

But if I hit the browser’s reload button while in the “main” view, I get the exception :frowning:

Perhaps I don’t understand the life-cycle of my UI? What happens in Vaadin when the browser’s “reload” is hit on one of the views? If the UI’s “init()” method is called again, I guess that would explain things as in init() a new navigator is created and that one doesn’t know about the “main” view - since I don’t create that until the user goes through LoginView. If this is the case, is the solution to not create a new navigator every time init() is called (i.e. maintain a static member for it in the UI class?)

Any advice is much appreciated.

While I’m posting for the first time, another quick question: I’ve been successfully using addStyleName(“myView”) on my views in order to do some styling from within the app’s styles.css - e.g.
.myView {
background-color: green;
}
But when I try to do the same with MenuBar, styling seems to have no effect:
MenuBar bar = new MenuBar(); bar.addStyleName(“mybar”);
.mybar {
background-color = purple;
}

Any suggestions much appreciated.
Tom

Sorry about the premature post (at least the first part) - I did see in the Book of Vaadin, Chapter 4.7, that by default a browser refresh causes a new UI to be instantiated. Once I added the @PreserveOnRefresh annotation, the error went away.

But my question regarding the menu bar still stands: the menu bar itself doesn’t change color with the styling. But I did noticed that the menu items (the drop downs from the menu bar) do have the above-mentioned styling (they show up with purple background). This is odd - since they’re not MenuBar objects! How do change the background color of the bar itself?

A separate question should be asked in a separate thread.

Most likely some other (more specific) CSS rules override what you are trying to set for your MenuBar so you need to make your rules more specific. Tools such as FireBug or Chrome developer tools can help see exactly what CSS rules are there and what overrides what.

Hi Henri Sara, I have a small question regarding navigation between view. I wanted to build a sample application where user first login using LoginView and then go to MainView which also have the contentLayout. This contentLayout should display the rest of Views in that area depending on which menu user click . I have tried so many examples but i have not figured out how to do it.

I faced with the same problem and , it took a while for me to relaize that they need the name of the first view to be empty . (“” ) . We can’t give a name to the first view if it’s the fist page.

I used the following:


this.navigator.setErrorView(myView);

and it fixed the error with the empty fragment.

Thanks a lot for that. I never found that part in the documentation.

protected void init(VaadinRequest request) {
getPage().setTitle(“Navigation Example”);

     navigator = new Navigator(this,this);
     navigator.addView("startview", new StartView());
     navigator.addView("mainview", new StartView());

here by then i created two classes as startview and mainview and kept buttons in both the class, in the event of button i used navigate to method and gave names as in startview navigateto mainview and in mainview navigate to startview still getting that error unkown state.