It turns out even logout needs to do some research and figure out...
Answer:
// getUI().getSession().close();
VaadinService.getCurrentRequest().getWrappedSession().invalidate();
getUI().getPage().setLocation(
VaadinService.getCurrentRequest().getContextPath());
(reference https://vaadin.com/wiki/-/wiki/Main/Handling%20logout)
The first line (commented out) is to remove Vaadin session. But something (my @SessionScoped things I guess, they are not Vaadin session scoped by servlet session scoped) still there and made a mess
Getting wrapped session gets the server (not vaadin) session.
Then mind where to redirect - if redirect to the same URL, browser won't reload and user will not see login page.