I filed bug report on this, [ticket # 6,321]
(https://github.com/vaadin/flow/issues/6321).
In previous verions of Vaadin, the UI
object represented the entire content space of a web browser’s window/tab. So a Vaadin app would have one, and only one, UI
object per window/tab for as long as that browser window/tab was open. We should see UI
objects come and go only when a browser window/tab was opened or closed.
➥ Yet in Vaadin 14.0.1 I am seeing the UI
object being re-instantiated (or re-initialized?) over and over again for a single opened browser window. Is this a bug?
Use the [Get started with Vaadin]
(https://vaadin.com/start/latest) page to create a new Vaadin 14 app, of the “Plain Java Servlet” flavor. Make the fewest possible changes needed to show the problem, as discussed next.
Add the frontend-maven-plugin
via the Maven POM as [discribed on Stack Overflow]
(https://stackoverflow.com/a/57502853/642706).
Edit the MainView.java
to add this line:
System.out.println ( "BASIL - new MainView instantiated. " + Instant.now () );
…and disable the @PWA
line (as we do not need Progressive Web App features).
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 - new MainView instantiated. " + Instant.now () );
Button button = new Button("Click me",
event -> Notification.show("Clicked!"));
add(button);
}
}
Add another view, so we can practice routing.
package work.basil.example;
import com.vaadin.flow.component.Text;
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 - new OtherView instantiated. " + Instant.now () );
Text text = new Text ( "Other instantiated at: " + Instant.now () );
this.add(text);
}
}
Implement a VaadinServiceInitListener
as described [in the manual]
(https://vaadin.com/docs/v14/flow/advanced/tutorial-service-init-listener.html). In that code, add a[ UIInitListener
]
(https://vaadin.com/api/platform/14.0.1/com/vaadin/flow/server/UIInitListener.html) to react to a UI
object being initialized, as discussed [in the manual]
(https://vaadin.com/docs/v14/flow/advanced/tutorial-ui-init-listener.html).
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 )
{
serviceInitEvent.getSource ().addUIInitListener (
( UIInitEvent event ) -> {
System.out.println ( "BASIL - new UI instantiated. UI id # " + event.getUI ().getUIId () + " " + Instant.now () );
} );
}
}
Create a text file, to active the service listener:
/Users/basilbourque/IdeaProjects/uidisappearing/src/main/resources/META-INF/services/com.vaadin.flow.server.VaadinServiceInitListener
…contining the name of our listener class:
work.basil.example.ApplicationServiceInitListener
Run Maven clean
& install
. Then run the Vaadin app via the bundled Jetty server via Maven plugin, from within IntelliJ (in my case).
Open a web browser pointing to localhost:8080
. Click the “Click me” button a few times. Watch the console spew several notices. And manually change the URL to try routing: localhost:8080/other
.
When run with only a single web browser loading the app:
BASIL - new UI instantiated. UI id # 0 2019-08-24T02:26:37.336419Z
BASIL - new UI instantiated. UI id # 0 2019-08-24T02:26:37.336562Z
BASIL - new UI instantiated. UI id # 0 2019-08-24T02:26:37.336423Z
BASIL - new MainView instantiated. 2019-08-24T02:26:37.369187Z
BASIL - new UI instantiated. UI id # 1 2019-08-24T02:26:38.230508Z
BASIL - new UI instantiated. UI id # 2 2019-08-24T02:26:39.192811Z
BASIL - new UI instantiated. UI id # 3 2019-08-24T02:26:42.250735Z
BASIL - new UI instantiated. UI id # 4 2019-08-24T02:26:47.289394Z
➥ What is going on with the UI
class? Why is it not stable?
➥ Why is the UI
id number incrementing? Are new UI
objects being instantiated?
➥ Why on #0 is the listener running more than once? As the same UI
object being re-initialized? Why, and to what effects?
Enabling that @PWA
annotation line has a calming effect on UI
.
BASIL - new UI instantiated. UI id # 0 2019-08-24T03:15:04.675171Z
BASIL - new MainView instantiated. 2019-08-24T03:15:04.716987Z
BASIL - new UI instantiated. UI id # 1 2019-08-24T03:15:12.565014Z
BASIL - new MainView instantiated. 2019-08-24T03:15:12.565710Z
BASIL - new UI instantiated. UI id # 2 2019-08-24T03:15:14.205289Z
BASIL - new OtherView instantiated. 2019-08-24T03:15:14.208116Z
BASIL - new UI instantiated. UI id # 3 2019-08-24T03:15:16.190052Z
BASIL - new OtherView instantiated. 2019-08-24T03:15:16.190572Z
➥ Why does @PWA
affect UI
behavior? Is that another bug or a feature?
➥ But we seem to still be getting new UI
instances when routing. Why?
None of this fits my previous understanding of UI
class.