3

When I logout from my application it doesn't show my logout message

I have an outputText trying to show the message in my view (<h:outputText id="message" value="#{loginMB.message}" />):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:o="http://omnifaces.org/ui"
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    template="/WEB-INF/templates/template.xhtml">
    <ui:define name="content">
        <o:form id="login" includeViewParams="true">
            <h:outputText id="message" value="#{loginMB.message}" />
            ... Another components ...
        </o:form>
    </ui:define>
</ui:composition>

And this is my backing bean:

@ManagedBean
@SessionScoped
public class UserBB implements Serializable {

    private String message;

    public void logout() {
        try {
            message = "You have been logout successfully";

            SecurityUtils.getSubject().logout();
            Faces.invalidateSession();
            Faces.redirect("login.xhtml");
        } catch (Exception exception) {
            ... Another code ...
        }
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Why it doesn't show my logout message?

Edit:

Logout method:

public void logout() {
    SecurityUtils.getSubject().logout();
    Messages.addFlashGlobalInfo("You have successfully log out");
    Faces.invalidateSession();
    Faces.redirect("login.xhtml?faces-redirect=true&lo=t");
}

logout button:

<p:commandButton action="#{userBB.logout}" value="log out" />
John Alexander Betts
  • 4,718
  • 8
  • 47
  • 72

3 Answers3

5

Why it doesn't show my logout message?

Because you've assigned it as a property of a session scoped bean and are then invalidating the session and sending a redirect. The invalidation of the session will destroy the session scope and all objects stored in it, including session scoped managed beans. The redirect thereafter will create a brand new request and session and all session scoped managed beans will be newly recreated, with all properties set to default.

There are 2 problems with this approach:

  1. Using <h:outputText> instead of <h:message(s)> to display the message(s).
  2. Storing the message in the session scope instead of the flash scope.

To solve your problem, use <h:message(s)> to display the message(s) and use FacesContext#addMessage() or, as you're already using OmniFaces, its Messages utility class, to add a message to the faces context. You can use <h:messages globalOnly="true"> to display only global messages (i.e. those with a null client ID). You can use Flash#setKeepMessages() to tell JSF to store all messages of the current request in the flash scope instead.

Thus, all in all, this should do:

<h:messages id="messages" globalOnly="true" />

with

@ManagedBean
@RequestScoped // Doesn't need to be session scoped for the particular task.
public class UserManager {

    public void logout() throws Exception {
        SecurityUtils.getSubject().logout();
        Messages.addFlashGlobalInfo("You have been logged out successfully");
        Faces.invalidateSession();
        Faces.redirect("login.xhtml");
    }

}

For the interested, here's how it would look like using "plain JSF":

    public void logout() throws Exception {
        SecurityUtils.getSubject().logout();
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(null, new FacesMessage("You have been logged out successfully"));
        ExternalContext externalContext = context.getExternalContext();
        externalContext.getFlash().setKeepMessages(true);
        externalContext.invalidateSession();
        externalContext.redirect("login.xhtml");
    }

Important note is that the flash scope is severly broken in older Mojarra versions. You need a minimum of 2.1.27 to get rid of all those problems.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
2
Faces.invalidateSession();

This will destroy the session and since the bean is session scoped all the data will be lost.

Solution:

 Faces.redirect("login.xhtml?msg=You have been logged out sucessfully");

and in your xhtml

<h:outputText id="message" value="#{param['msg']}"/>

If not want to show in url

Create another file logout.xhtml (Actually logout.xhtml will have same code as login.xhtml just add extra line you want)

Makky
  • 17,117
  • 17
  • 63
  • 86
1

you can also hide the mesage with url paramter.

Faces.redirect("login.xhtml?faces-redirect=true&logoutMsg=true");

and xhtml

<h:outputText value="You have been logged out sucessfully" 
rendered="#{not empty param['logoutMsg']}"/>
bhdrk
  • 3,415
  • 26
  • 20