App Layout State Changes causing issues

I have an AppLayout whose available nav and current page is driven by various parts of a users state including role and license.

Through these state changes, I am t getting a “Can’t move a node from one state tree to another” but I am not sure how to go about debugging what is actually triggering this.

Is there an easy way to track down what is doing this?

The basic flow right now that is causing it:

  1. Register new user.
  2. Login as new user.
  3. Supposed to redirect to a page that prompts for a token, but this is where the node tree error is occurring.

I’ve been playing around with a lot of different strategies for the redirect and layouts, but I feel like I’m throwing random darts.

This error Can’t move a node from one state tree to another is when you are trying to use the same component instance in 2 places in a view (or views).
One example is when you are using the same component instance in multiple rows in a Grid. But it can be tricker and hard to detect (for example if you are using @SpringComponent on a Vaadin component without a Scope annotation. or a static variable)

It most deifnitely is tricky! I’ve tried everything. It seems I have a navigation logic problem somewhere, but I cannot seem to find it. The user verification page continuously gets reloaded via network requests. Even when I’ve gone through and removed all of the components from that class.

The user verification page continuously gets reloaded via network requests
That doesn’t seem to be related to the javascript error (or maybe it’s a side effect of a previous bug). Is it loaded on the server side ? (afterNavigation…)
If you can , you should probably show some code. Or add some logs/breakpoints to your code.
The basic flow seems quite easy to follow, How do you redirect to the user verification page?

It is related because of what was triggering the tree creation. I am doing redirects in the afternNavigation of the AppLayout (not sure if that is the correct place) so the if statement that appears to be causing the issue is:
if (authenticatedUser.get().isPresent() &&
authenticatedUser.get().get().getStatus() == AccountStatus.REGISTERED &&
) {
UI.getCurrent().navigate(UserVerification.class);

I think I might either need to add a condition to that if or change the “'navigate” to a different method. One other challenge is making sure that the AppNav loads correctly as the menu choices are also partily driven by state.

That looks wrong: authenticatedUser.get().get() (the get get)

Same here:

authenticatedUser.get().isPresent()

That’s just a wrapper class around context to add some different functionality that I was calling a lot. The “get” is an optional return. Probably more complicated than it needs to be.

How are you building your views? Are you injecting / autowiring components? Are you views annotated with Spring annotations?

Most are annotated with Spring annotations, but the flow is controlled by the AppLayout.

I fixed this issue by looking at the page title in the afterNavigation conditionals.

protected void afterNavigation() {
if (authenticatedUser.accountStatus() == AccountStatus.REGISTERED
&& !getCurrentPageTitle().equals(“Email Verification”)) {
UI.getCurrent().navigate(UserVerification.class);
} else if (authenticatedUser.accountStatus() == AccountStatus.ACTIVE &&
!hasActiveLicense() && !getCurrentPageTitle().equals(“License Management”)) {
UI.getCurrent().navigate(LicenseView.class);
} else if (authenticatedUser.get().isPresent() &&
(getContent().getClass().equals(LoginView.class) || getContent().getClass().equals(UserVerification.class) ||
getContent().getClass().equals(ForgotPasswordView.class))) {
UI.getCurrent().navigate(ProjectsView.class);
}
super.afterNavigation();
viewTitle.setText(getCurrentPageTitle());
}

Thanks for your help everyone!

I don’t wanna destroy your hopes, but I would doubt that this fixes the issue in the long run :sweat_smile: normally that issue comes up with wrong usage of scoped views or components and is going to bite you really hard once multiple users at the same time are using your app.

Okay, so since it appears that I was wrong and your warning was well served. Where do I go from here?

Check that all Vaadin components you have used with Spring’s Annotation like @Component also has proper scope Annotation like Request Scope, UI Scope or Route Scope https://vaadin.com/docs/latest/integrations/spring/scopes

I’m not using any that aren’t part of the AppLayout process. All of those components are defined using the general form:
@Route(value =“license”, layout = MainLayout.class)
@PageTitle(“License Management”)
@RolesAllowed(“USER”)

I do have a static image that I am using for a logo across all pages.

Like so? “static Image”?

(no Vaadin component is allowed to be static → that’s 100% explaining the exception)

It’s a class defined as:
public class PortalLogo {
private static Image logo = new Image(“”, “”);

public static Image getLogo() {
    logo.setWidth("486px");
    logo.setHeight("150px");
    return logo;
}

}

Jop there is your problem :+1:

So much for trying to be efficient. LOL