I’m currently in the process of migrating from Vaadin 6 to 7 with my application .
Everything seems to be going smoothly, but the logout/session handling has me stumped.
Basically my application has two states: logged in and not logged in.
If you are not logged in, there’s a button that pops up a login window (a Vaadin window, not a browser window).
Once logged in, there’s a logout button that should close the current running application and start a new one so that the user is shown the state when the user is not logged in.
However, each time I try to do anything after pressing the logout button, I get a “Communication problem”. As if the application was closed, but not restarted.
What’s going wrong?
Some details:
using @PreserveOnRefresh
the logout action is directly triggered from a button within the main layout
BTW: the Vaadin 6 application is running at http://app.fctr.be if you want to take a look at specific details.
We managed to solve this by redirecting to “/?restartApplication”
Ideally, however, I would like to restart the application programmatically, because now, there’s a risk the user refreshes the changed URL and inadvertently restarts the application.
I use the following to logout , But note I make use of a JSR-196 Authentication Module ( form based login ) so your experience may very.
When I logout I have to destroy ALL the UI’s for my current Session since they share an api object provided by my login module.
The code below worked very nicely with Push enabled, unfortunately I ran into an issue with glassfish+cdi-utils+push so any other browser tabs will not automatically go to the index.html (The tab where the user clicked logout though will behave correctly ) , the other browser tabs will cause a Session Timed out if the user click on them , and then they will be directed to the login page by the login module ) , when I have some time I’ll go dig into the Client side Vaadin code to handle the login module redirect correctly ( without the red session screen ), it should be quite easy to fix this.
public void logout() {
// Logout will destroy our legacy Api, and to prevent reuse of a stale Api we destroy the Session,
// and for that to work we 1st close any other UI's that is also created for this Session
for (UI ui : UI.getCurrent().getSession().getUIs()) {
if (ui != UI.getCurrent()) {
ui.accessSynchronously(new Runnable() {
@Override
public void run() {
LOGGER.log(Level.INFO, "Closing UI {0}", UI.getCurrent());
UI.getCurrent().getPage().setLocation(UITools.getStartLocation()); // Go to the default page (index.html)
UI.getCurrent().close();
}
});
}
}
LOGGER.log(Level.INFO, "Closing UI {0}", UI.getCurrent());
UI.getCurrent().getPage().setLocation(UITools.getStartLocation()); // Go to the default page (index.html)
// Legacy application Api , provided by a custom login module, the one api is shared by the all the
// UI's of the same Session
try {
LOGGER.log(Level.WARNING, "Closing Api {0}", UI.getCurrent());
api.logout();
} catch (ApiException ex) {
LOGGER.log(Level.SEVERE, "Legacy api.logout failed", ex);
}
// Now to destroy our Session we get a reference to it.
final WrappedSession httpSession = getSession().getSession();
// Close the Current UI
close();
// Close the Current VaadinSession
try {
getSession().close();
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
// Destroy the Wrapped Session
try {
httpSession.invalidate();
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, null, ex);
}
}
The UITools …
public static String getStartLocation() {
final Page page = Page.getCurrent();
final StringBuilder sbuf = new StringBuilder();
sbuf.append(getServerLocation(page));
// ContextPath already has / infront
sbuf.append(VaadinServlet.getCurrent().getServletContext().getContextPath());
return sbuf.toString();
}
public static String getServerLocation(final Page page) {
final StringBuilder sbuf = new StringBuilder();
sbuf.append(page.getLocation().getScheme());
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, "Page getScheme {0}", page.getLocation().getScheme());
}
sbuf.append("://");
sbuf.append(page.getLocation().getHost());
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, "Page getHost {0}", page.getLocation().getHost());
}
sbuf.append(":");
sbuf.append(page.getLocation().getPort());
if (LOGGER.isLoggable(Level.FINER)) {
LOGGER.log(Level.FINER, "Page getPort {0}", page.getLocation().getPort());
}
return sbuf.toString();
}