when an UI instance is created in Vaadin Flow ?

In vaadin flow, when an UI instance (of com.vaadin.flow.component.UI) is created ? and when it is cleaned up by framework ?.
It is right to say there is only one UI instance created for one Browser Tab, does not matter how many requests are called from that Tab ?

Also every time we navigate to a new View (using UI.navigate(NEWVIEWNAME)), then a new instance of that View is created ? or it is reused from previous created one if these Views are in same layout (can say same browser tab) ?

One of my biggest concern in Vaadin is memory management. Example, in same Tab of browser if user moves back and forth between VIEWs, then it possible many new instances of VIEWs created causing memory increasing. Then once user close that Tab, we need to ensure all unused instances are released and cleaned up properly.

Browser tab corresponds to a UI instance.
So it’s created when you first time open some view in a new browser tab.
It’s removed when you close your browser tab. But that happens after a some delay (timeout): every opened tab
sends from the client side a heartbeat message. When several heartbeat messages are missed on the serer side the UI is marked as inactive and will be closed.

It is right to say there is only one UI instance created for one Browser Tab, does not matter how many requests are called from that Tab ?

Yes.

Also every time we navigate to a new View (using UI.navigate(NEWVIEWNAME)), then a new instance of that View is created ? or it is reused from previous created one if these Views are in same layout (can say same browser tab) ?

View is recreated each time unless you are using DI framework and scopes (which allows to reuse the same instances) but that should be explicitely done.
It’s a bit different with layouts (parent layouts for views): if the new navigation target has the same layout then it’s reused. Otherwise it will be just GCed.

It’s not a problem to create new instances of views since they are not referenced from anywhere being discarded (recreated). So GC may free the memeory. It’s the same as a new pure Jaba object creation.

Thanks Denis Anisimov, it is useful inputs.

What if I want save state of Route view Accounts after navigate to Route AccountDetails in demo:
https://labs.vaadin.com/business-tabs/accounts ? I want return to Accounts and see that all components was not recreated. How can i control Route state lifecycle? In demo app using:

@Route(value = "accounts", layout = MainLayout.class)
@ParentLayout(MainLayout.class)
@PageTitle("Accounts")
public class Accounts extends ViewFrame implements RouterLayout 

@Route(value = "account-details", layout = MainLayout.class)
@PageTitle("Account Details")
public class AccountDetails extends ViewFrame implements HasUrlParameter<Long> 

public class ViewFrame extends Composite<Div> implements HasStyle {
@Override
    protected void onAttach(AttachEvent attachEvent) {
        super.onAttach(attachEvent);
        MainLayout.get().getAppBar().reset();
    }
}

What is right strategy? I don’t recreate Accounts View after return from AccountDetails.

I want return to Accounts and see that all components was not recreated.

This is not clear for me.
What does mean not recreated ? For a different user they have to be recreated since it’s not possible to reuse the same components in a different UI (or e.g. singleton component has no sense).
So there should be some scope: a “context” within the instances stay the same.

The question what scope do you need ?
As I said:

  • singleton scope doesn’t have any sense
  • session scope also doesn’t have sense : you don’t want to reuse the same instance within every UI (it’s just not possible).
  • the UI scope perhaps suites your need. At least not any wider scope. But it might be there can be narrow scope which you want here.

If we talk about navigation then “route scope” may work for you.

Depending on the scope the implementation will be different.

There are ready made scopes for Vaadin session and UI in Spring add-on and CDI add-on.
There is ready made “route scope” in CDI add-on.
There is nothing available by default in pure Flow for this. You have to write some custom code for this if you want this functionality by yourself.

Denis Anisimov:
What does mean not recreated ? For a different user they have to be recreated since it’s not possible to reuse the same components in a different UI (or e.g. singleton component has no sense).

I use Spring add-on. For clarify: for example, i’ll want add some Wizard component. Wizard have steps and I want back to previous step. Also I use backend service and autowired services in components. UI components must keep state for current user (@VaadinSessionScope). Can I use routing this (and what helps me keep state of route)? Or this ideologically wrong and I must use layout layers (and hide/show layouts). I want understand the concept in general. Thank you.

Can I use routing this

Sorry, I don’t understand this question.

UI components must keep state for current user (@VaadinSessionScope).

If I understood you correctly then this may not work.
@VaadinSessionScope is a scope which is wider than @UIScope.
You may not use any wider scope than @UIScope for UI components.
As I wrote already: UI is 1:1 with your browser tab. Several tabs are inside the same @VaadinSessionScope.
So if you have several tabs open then the same component with @VaadinSessionScope will be reused in every tab . This will simply cause an exception.

You may use a wider scope only for data beans where reusing the same data across tabs or even withing an app is OK.

Be aware that at least in Vaadin 14.0.1, the UI object is replaced each time you use routing even despite using the new @PreserveOnRefresh. Ditto for user hitting the browser’s Refresh button. See other recent forum threads for gory details.

You will also find disussion of how to preserve your views between routes.

when an UI instance is created in Vaadin Flow ?

I suggest you see for yourself. Track the UI instances in your own code. Tracking is quite easy, as explained in the manual [here]
(https://vaadin.com/docs/v14/flow/advanced/tutorial-ui-init-listener.html) and [here]
(https://vaadin.com/docs/v14/flow/advanced/tutorial-service-init-listener.html).

Let’s walk through the steps, and see example code.

For a new Vaadin 14 project, add the following to your POM to get the necessary Node.js & npm tools added to your project. [Discussed on Stack Overflow]
(https://stackoverflow.com/q/57502852/642706).

<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <!-- Use the latest released version:
    https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ -->
    <version>1.8.0</version>

    <executions>
        <execution>
            <!-- optional: you don't really need execution ids, but it looks nice in your build log. -->
            <id>install node and npm</id>
            <goals>
                <goal>install-node-and-npm</goal>
            </goals>
            <!-- optional: default phase is "generate-resources" -->
            <phase>generate-resources</phase>
        </execution>
    </executions>
    <configuration>
        <nodeVersion>v10.16.3</nodeVersion>

        <!-- optional: with node version greater than 4.0.0 will use npm provided by node distribution -->
        <!--                    <npmVersion>2.15.9</npmVersion>-->

        <!-- optional: where to download node and npm from. Defaults to https://nodejs.org/dist/ -->
        <!--                    <downloadRoot>http://myproxy.example.org/nodejs/</downloadRoot>-->
    </configuration>
</plugin>

On whatever content you are showing, such as a MainView class, spill to console when instantiating. Notice the System.out.println I added to the MainView class created by default in the Vaadin starter project.

package work.basil.example;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;

import java.time.Instant;

/**
 * The main view contains a button and a click listener.
 */
@Route ( "" )
@PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
public class MainView extends VerticalLayout
{
    public MainView ( )
    {
        System.out.println ( "BASIL - MainView constructor." + Instant.now () );

        Button button = new Button ( "Click me" ,
                event -> Notification.show ( "Clicked!" ) );
        add ( button );
    }
}

Add the listeners that are called when (a) the VaadinService begins, and (b) a UI object is being initialized. Both are done in this single class shown next.

Notice how we interregate the UI object for its ID number. I expect you will see that number increase, presumably because a new UI object was instantiated.

package work.basil.example;

import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.UIInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;

import java.time.Instant;

public class ApplicationServiceInitListener
        implements VaadinServiceInitListener
{

    @Override
    public void serviceInit ( ServiceInitEvent serviceInitEvent )
    {
        System.out.println( "BASIL - ServiceInitEvent." + Instant.now() );

        serviceInitEvent.getSource().addUIInitListener(
                ( UIInitEvent uiInitEvent ) -> {
                    System.out.println( "BASIL - UIInitEvent. UI id # " + uiInitEvent.getUI().getUIId() + ". " + Instant.now() );
                } );
    }
}

To activate that class, we must hook it into the [Java Server Provider Interface (SPI)]
(https://docs.oracle.com/javase/tutorial/ext/basics/spi.html).

Inside the src folder of your project, in the nested resources folder, create a folder META-INF. This is [part of the JAR format]
(https://stackoverflow.com/q/70216/642706), not to be confused with[ WEB-INF]
(https://stackoverflow.com/questions/19786142/what-is-web-inf-used-for-in-a-java-ee-web-application). Inside that new META-INF folder, create a new folder named services.

Inside that services folder, create a plain text file. It must be name exactly: com.vaadin.flow.server.VaadinServiceInitListener. This is the fully-qualified name of the interface for which we want to supply an implementation. Inside that file, add this one line, the fully-qualified name of the listener class we created. In the case of this example here: work.basil.example.ApplicationServiceInitListener. See attached screenshot.

If starting with a fresh project, you may want to add another view class with @Route to see the effects of routing.

package work.basil.example;

import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

import java.time.Instant;

@Route ( "other" )
public class OtherView extends VerticalLayout
{
    public OtherView ( )
    {
        System.out.println( "BASIL - OtherView constructor." + Instant.now() );

        H1 h1 = new H1( "Other" );
        this.add( h1 );
    }
}

Do a Maven clean. Run your web app.

I believe you will see a new UI object (a) when routing, and (b) when user clicks the browser Reload button. The new @PreserveOnRefresh annotation has no effect on this behavior. You may see the UI init occur in other cases as well. So you cannot count on the UI object sticking around.

Example output in Vaadin 14.0.2. The 4th & 5th lines appeared whet I clicked the browser Reload button.

BASIL - ServiceInitEvent.2019-08-28T05:59:07.882575Z
BASIL - UIInitEvent. UI id # 0. 2019-08-28T05:59:07.981299Z
BASIL - MainView constructor.2019-08-28T05:59:07.994759Z
BASIL - UIInitEvent. UI id # 1. 2019-08-28T05:59:21.101277Z
BASIL - MainView constructor.2019-08-28T05:59:21.101884Z

The 4th & 5th lines appeared when I clicked the browser Reload button.

If I add a @PreserveOnRefresh to my MainView, and hit Reload button, I see line # 4 (UIInitEvent), but not # 5 (MainView constructor).

17815006.png

Thanks Basil

But if this is a bug on Vaadin then it is better for Vaadin team to fix it than to do a workaround by app developer. I am waiting for next vaadin release fixing this issue.

Thang Le:
Thanks Basil

But if this is a bug on Vaadin then it is better for Vaadin team to fix it than to do a workaround by app developer. I am waiting for next vaadin release fixing this issue.

No, as far as the UI object being replaced on routing, that is a documented feature, not a bug.

The UI class in Vaadin Flow seems to have changed in in purpose since Vaadin 8. In Vaadin Flow, UI is more like the Page class in that is more about connecting to the browser and the Request than it is about representing our app content.

Our app content is now separate from the UI object. Using @PreserveOnRefresh annotation on your @Route annotated content preserves the life of that content even as the UI object is replaced by a new UI when the user clicks the browser Reload button.

The key seems to be learning more about RouterLayout, and reading the post by Joni Uitto near the bottom of [this other forum thread]
(https://vaadin.com/forum/thread/17810577/ui-being-instantiated-over-and-over-again-in-default-vaadin-14-0-1-app). I am right now trying to grok that post, and studying the RouterLayout mentions in the manual.

Again, just try it to see for yourself. Add the listeners I described above. As I experiment, it is making more sense to me now. The problem for me is that the intent of UI class seems to change changed in Vaadin 10+ from what I recollect in Vaadin 8. I am adjusting my thinking now.

I do however have one more problem/mystery: Disabling the @PWA ( name = "Project Base for Vaadin", shortName = "Project Base" ) line on my MainView results in many more UI instantiations. I have no idea why, nor do I know if this is a bug or a feature.

Basil Bourque:
The UI class in Vaadin Flow seems to have changed in in purpose since Vaadin 8. In Vaadin Flow, UI is more like the Page class in that is more about connecting to the browser and the Request than it is about representing our app content.

Our app content is now separate from the UI object. Using @PreserveOnRefresh annotation on your @Route annotated content preserves the life of that content even as the UI object is replaced by a new UI when the user clicks the browser Reload button.

Is this change in how UI is used documented someplace? My code worked well in Vaadin 7, but something is messing me up with how UIs are used in flow.

Anthony Baldarelli:

Basil Bourque:
The UI class in Vaadin Flow seems to have changed in in purpose since Vaadin 8. In Vaadin Flow, UI is more like the Page class in that is more about connecting to the browser and the Request than it is about representing our app content.

Our app content is now separate from the UI object. Using @PreserveOnRefresh annotation on your @Route annotated content preserves the life of that content even as the UI object is replaced by a new UI when the user clicks the browser Reload button.

Is this change in how UI is used documented someplace? My code worked well in Vaadin 7, but something is messing me up with how UIs are used in flow.

At least here: https://vaadin.com/docs/v14/flow/migration/3-general-differences.html#the-ui-class-is-different-and-it-is-optional

Thanks. Yep, I don’t use the UI in that way. I am only talking about the fact that in Vaadin 7 ( don’t know about Vaadin 8 ), I could rely on one UI per browser tab. Yes, that was because my UI filled the entire page, so maybe it was by dumb luck that it worked for me. Of note is this comment from the Vaadin 7 docs ( https://vaadin.com/docs/v7/framework/application/application-overview.html ):

A UI represents an HTML fragment in which a Vaadin application runs in a web page. It typically fills the entire page, but can also be just a part of a page. 

I guess we cannot depend on that behavior from Flow, based on Basil’s comments, I was just looking for confirmation. Every time I have read the link you provided, I saw that UI now connected to body tag and so I just assumed it behaved the same as Vaadin 7, one UI per browser tab. But I guess that is not true.

Anthony Baldarelli:
…I am only talking about the fact that in Vaadin 7 … I could rely on one UI per browser tab. … so maybe it was by dumb luck that it worked for me.

No, not dumb luck. In the previous generation of Vaadin, you were indeed following the intended design: One UI object representing all your content of that web browser window/tab. And that one UI object was stable for the life of thet browser window/tab. Your UI subclass was the entry point of the Vaadin web app from our viewpoint as programmers writing Vaadin apps. (Vaadin actually does more stuff related to Java Servlets before our UI subclass gets running, but that is largely transparent to us, and beside the point here.)

Now the UI class serves a different role, [as documented]
(https://vaadin.com/docs/v14/flow/migration/3-general-differences.html#the-ui-class-is-different-and-it-is-optional). So much so that I wish the Vaadin team had changed the name of this class. I suspect this very different behavior of UI will be baffling to anybody moving from Vaadin 7/8 to Vaadin Flow. The UI object is definitely not stable as demonstrated in my post above. One UI object is replaced by another many times, sometimes several times in a second. Some of those UI replacements may be a feature, and some may be a bug, how much of feature/bug is still unclear. You can read several recent threads on this forum about the matter, as well as posts on Stack Overflow, and some tickets on the Vaadin Flow Github site. But no matter, the Vaadin team has made clear that a UI object is not meant to be constant through the life of a browser window/tab in Vaadin Flow – you should expect any UI to be swapped out and a new one swapped in certain points.

If you go further back into Vaadin history, the UI class was originally added to (in part) avoid the previous generation’s use of a layout provided at the start of the app in which you placed your own layout. This extra layout on the outside was a bit confusing and superflous. So UI eliminated that extra layout. Now, ironcially, we are back to that condition where we need to establish an extra layout as our stable outer shell inside of which we place our changing content (login dialog, initial layout, alternate layouts) since the UI object is rapidly replaced and no longer serves to hold our content.