I'm trying to figure out how to log out a user with an f:ajax
call using JSF and a backing managed bean. The problem I'm having is that I can't quite figure out why the call order for the Ajax listener and the rerender of the login form.
Below is the very simplified code. The basic idea of the code is this
if (uid != null) {
// show log out
} else {
// show log in
}
I am clearly not understanding something about how the ajax listeners and the form rerender is done.
The JSF page
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<f:view>
<h:form id="loginForm">
<c:choose>
<c:when test="${userBean.uid != null}">
<span>Hi, #{userBean.uid}</span>
<h:commandButton value="Logout">
<f:ajax event="click" listener="#{userBean.logout}" render="loginForm"/>
</h:commandButton>
</c:when>
<c:otherwise>
<span>User name: </span>
<h:inputText value="#{userBean.uid}" id="uid" />
<h:commandButton value="Login" action="#{userBean.login}" />
</c:otherwise>
</c:choose>
</h:form>
</f:view>
</h:body>
</html>
The Bean
package test.auth;
import java.io.Serializable;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
@Named(value="userBean")
@SessionScoped
public class UserBean
implements Serializable
{
private static final long serialVersionUID = -4292770567982457272L;
private String uid;
/** Creates a new instance of UserBean */
public UserBean() {
}
public String getUid()
{
return uid;
}
public void setUid(String uid)
{
this.uid = uid;
}
public String login () {
return "faces/index.xhtml";
}
public void logout (AjaxBehaviorEvent event) {
this.uid = null;
}
}
The problem with the code is that when clicking logout
the form reloads but it is still in the logged in state even though the uid
has been set to null
. I've checked this with the debugger. So how do I make the render be executed AFTER the ajax listener?
The JSTL tags are executed during view build time, not during view render time. At the moment JSF is reusing the view state for re-render, the JSTL tags won't be re-executed, simply because they are not there anymore.
You want to use JSF rendered
attribute instead.
<h:form id="loginForm">
<h:panelGroup rendered="#{userBean.uid != null}">
<span>Hi, #{userBean.uid}</span>
<h:commandButton value="Logout">
<f:ajax event="click" listener="#{userBean.logout}" render="loginForm"/>
</h:commandButton>
</h:panelGroup>
<h:panelGroup rendered="#{userBean.uid == null}">
<span>User name: </span>
<h:inputText value="#{userBean.uid}" id="uid" />
<h:commandButton value="Login" action="#{userBean.login}" />
</h:panelGroup>
</h:form>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With