Vaadin14 Navigation Issue

Hi,

I started a new server-side only Vaadin Project. I observe a strange behaviour which I am not able to comprehend nor fix.

Observation:
The project is setup with a few pages. Menus and ClickableCards have event handlers that navigate across pages, with View class. These work fine. However, once a page is rendered, any navigation through url (string) such as href in <a> tags, or Breadcrumb, or direct url on the browser breaks the app. I find this stacktrace on the server logs.

ERROR com.vaadin.flow.router.InternalServerError - There was an exception while trying to navigate to 'h/su'
java.lang.IllegalStateException: Can't move a node from one state tree to another. If this is intentional, first remove the node from its current state tree by calling removeFromTree
        at com.vaadin.flow.internal.StateNode.doSetTree(StateNode.java:717)
        at com.vaadin.flow.internal.StateNode.lambda$setTree$3(StateNode.java:370)
        at com.vaadin.flow.internal.StateNode.visitNodeTree(StateNode.java:670)
        at com.vaadin.flow.internal.StateNode.setTree(StateNode.java:370)
        at com.vaadin.flow.internal.StateNode.setParent(StateNode.java:270)
        at com.vaadin.flow.internal.nodefeature.NodeFeature.attachPotentialChild(NodeFeature.java:78)
        at com.vaadin.flow.internal.nodefeature.StateNodeNodeList.add(StateNodeNodeList.java:53)
        at com.vaadin.flow.internal.nodefeature.ElementChildrenList.add(ElementChildrenList.java:42)
        at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.insertChild(AbstractNodeStateProvider.java:102)
        at com.vaadin.flow.dom.Node.insertChild(Node.java:294)
        at com.vaadin.flow.dom.Node.appendChild(Node.java:141)
        at com.vaadin.flow.component.internal.UIInternals.showRouteTarget(UIInternals.java:733)
        at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:252)
        at com.vaadin.flow.router.Router.handleNavigation(Router.java:249)
        at com.vaadin.flow.router.Router.navigate(Router.java:220)
        at com.vaadin.flow.router.Router.navigate(Router.java:186)
        at com.vaadin.flow.router.Router.initializeUI(Router.java:93)
        at com.vaadin.flow.server.BootstrapHandler.createAndInitUI(BootstrapHandler.java:1516)
        at com.vaadin.flow.server.BootstrapHandler.synchronizedHandleRequest(BootstrapHandler.java:472)
        at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
        at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1545)
        at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247)
        at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:120)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:547)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:608)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1607)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1577)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:161)
        at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:79)
        at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141)
        at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177)
        at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:755)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617)
        at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:590)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1607)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1297)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1577)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1212)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.Server.handle(Server.java:500)
        at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
        at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
        at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
        at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
        at java.base/java.lang.Thread.run(Thread.java:835)

I do not know how to get the app to working in these valid navigation scenarios. For e.g., I cannot get Breadcrumb to accept View class for navigation target (it only accepts href), or I would like to share a url that would help my users go directly to a part of application.Would appreciate all help I can get.

Thanks

One thing that can cause that error is adding the same component multiple times. E.g.

  TextField tf = new TextField();
  add(tf):
  ..
  ..
  ..
  add(tf);

In any case it’s almost impossible to give more help unless you include a small code sample that will produce the error.

Cheers.

Thanks @Martin… I saw some similar advice on other thread too. How do I troubleshoot this? I mean how do I identify which component is being duplicated? I have a set of pages that link to each other. I had already pored over my pages and there is no duplicate addition…

Its not easy for me to decide which part of code to share without dumping all of my project. One thing I can confirm is that I implement all my pages as views (own layout instances) and I do not use RouteLayout/ parentLayout yet (I am still new to Vaadin and I have to unlearn Angular concepts to be able to wrap my head around with Vaadin). Just that I did not want to create an engineering crisis that I know nothing about :slight_smile: I am learning everyday but not there yet.

Having said that, its just human eyes and thats why I would like to know how to zero-in on the offending duplicate to troubleshoot this scenario. Can you please help me with some pointers to put in a tracer-ink to localize the issue?

Thanks in advance.

The fact that you are not using parentLayouts here is good for finding the error, as you can now be sure in which exact component the error must lie, and navigation errors are pretty much out of the picture, as there is no main layout that keeps attached to the page while the child content is being replaced. Btw.

Does this happen on multiple views of yours, or just the one? Which vaadin version are you using? How do you navigate exactly?
Are you maybe using @PreserveOnRefresh because I think this has caused some similar errors for me.

One thing you could do is to add a breakpoint somewhere on a line mentioned in your stacktrace, and try to see if you can find out which component/node is throwing the error.

Hi @Kaspar,

Thanks for helping out. I have been tinkering, basically trying to ensure my logic parts dont offend anything in the framework… So I placed all my dynamic logic under a catch-all exception handler. Now I can confirm that this navigation error happens only when the navigation is setup thru urls (string). This error never happens when navigating thru view class. So right now, accessing any page breadcrumb component seems to be the issue (because navigation target cannot be set with view class in the component for some reason).

I also observed, when I open developer tools in Chrome, the browser stops in a debugger when this situation occurs. Just an observation. My project use only server-side apis, so no html/css/js/ts from my side, so the code under debugger is unrecognizable or comprehensible to me unfortunately.

Oh yes, I have placed @PWA on my app and also use @PreserveOnRefresh on all my pages. May be I can try removing the page annotation to see if the breadcrumb offends it.

Thanks :slight_smile:

This sounds indeed like Breadcrumb component has an issue with preserveonrefresh. If the problem vanishes if you either remove @PreserveOnRefresh or Breadcrumb, then you should open an issue in the [github of Breadcrumb]
(https://github.com/vaadin-component-factory/breadcrumb/issues).

For reference, @PreserveOnRefresh is a feature that was added after many core components were already finished. And when this feature was released, some of the components are not reinitialized exactly to the same state they were before. See [Upload]
(https://github.com/vaadin/vaadin-upload-flow/issues/147#issuecomment-632895953), [Image]
(https://github.com/vaadin/flow/issues/6478) (fixed), [Button click shortcuts]
(https://github.com/vaadin/flow/issues/8247) (fixed), and now apparently Breadcrumbs too (if confirmed).

Personal opinion: I expect even more preserve-on-refresh issues with other components to be found in the future, and find that too unreliable to use in production yet because of it.

TLDR;
Stay away from @PreserveOnRefresh if you can.

PS: Breadcrumb seems to use anchor tags, which do not navigate using Vaadins Router but instead “mimick entering a new URL”. The Breadcrumbs components looks not very complex and you could easily implement a similar component showing multiple RouterLinks. This should solve the preserveonrefresh issue, makes you able to set a Viewclass as navigation target instead of a String path, and also utilize the Router more.

Hi @Kaspar,

I got into more or less same conclusion… After your original comment, I started making prototypes simulating my UI View pattern (Setting up common and configurable parts of page layouts through an abstract class extending AppLayout; each page than simply has to fill up the relevant portions of the screen inside the hook methods defined in the parent class). With different combinations of preserveOnRefresh and Breadcrumbs (all 4 possibilities)… I found the issue is only when the URL is accessed directly and not when using PageViewInstance.class mechanism. This is because AppLayout and UI work with each other thru Router, the details I still cannot comprehend. But the behaviour is similar to some websites where you cannot navigate using back and forward buttons from browser.

I am now experimenting with setting up some event frameworks, just to see if this error happens when the navigation is triggered before the framework had time to complete something/ anything it is supposed to do during UI initialization but was not able to complete. WIll post more on my findings… your insights are really helpful… Thanks for the same :slight_smile: