aaronbartell

RPG / iSeries / Java / WDSC / RDi / XML / Web Services

JSF PhaseListener – Is This User Logged In?


   Dec 28

JSF PhaseListener – Is This User Logged In?

JavaServer Faces (JSF) is being touted as the next generation of web application development from the powers that be (IBM, Sun, Oracle), and has been tugging at my interest the past 8 months. In my quest to use it I quickly found myself drowning in the different complexities, but through much head to wall banging I have prevailed and would like to share some of those experiences with you through tips.

This tip shows how to register a PhaseListner at the Restore View phase of the JSF Lifecycle. The PhaseListener checks to see if the user has logged in, and if not it returns them to the login page. One could check to see if a user is logged in on each page and have code duplicated across many different backing beans, but going the PhaseListener route guards against that and allows you to have one point of checking for login credentials. To learn more about the JSF Lifecycle point your browser here.

Figure 1 shows how to register the PhaseListener using the lifecycle and phase-listener tags. This should be placed in your faces configuration file, often named faces-config.xml.

    Figure 1
<lifecycle>
 <phase-listener>com.loffler.copycenter.controller.LoggedInCheck</phase>
</lifecycle>

Figure 2 shows Java class LoggedInCheck implementing PhaseListener. The method getPhaseId is used to tell the PhaseListner which lifecycle phase this class should be called. In this example PhaseId.RESTORE_VIEW is used. You will have to understand the different phases to make sure a particular one fits for you. This one works in this case because it happens after backing beans have been updated form data from the web page.

    Figure 2
package com.mowyourlawn.controller;

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

public class LoggedInCheck implements PhaseListener {

    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }

    public void beforePhase(PhaseEvent event) {
    }

    public void afterPhase(PhaseEvent event) {
        FacesContext fc = event.getFacesContext();

        // Check to see if they are on the login page.
        boolean loginPage =
	  fc.getViewRoot().getViewId().lastIndexOf("login") > -1 ? true : false;
        if (!loginPage && !loggedIn()) {
            NavigationHandler nh = fc.getApplication().getNavigationHandler();
            nh.handleNavigation(fc, null, "logout");
        }
    }

    private boolean loggedIn() {
        return LoginController.loggedIn().booleanValue()c;
    }
}

Figure 3 shows what happens when a from-outcome of “logoutâ€? is encountered. Reference the nh.handleNavigation(fc, null, “logout”); line of code in Figure 2 to understand how the two are related. Again this should be placed in your faces-config.xml file.

    Figure 3
<navigation-rule>
  <from-view-id>*</from-view-id>
    <navigation-case>
      <from-outcome>logout</from-outcome>
      <to-view-id>/login.jsp</to-view-id>
    </navigation-case>
</navigation-rule>

The above article was written by Aaron Bartell and originally published in iSeriesNetwork.com’s Club Tech Tips email newsletter.

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

12 Comments

  1. Junyan says:

    your idea is very nice, and I want to use it in my code. But what is the LoginController, a javaBean?

    thanks!

  2. Uri R says:

    The link not explains what is LoginController, or in fact how to retrieve information if the current user logged in.

  3. Helper Dude says:

    I came across this while looking for other things and tried to implement it using Netbeans 6.0.1 and JSF 1.2.

    I had to make the following changes
    1) put all of the code in the afterPhase into the BeforePhase

    Notes:
    As for the LoginController question, I used a managed bean and called it like this (my managed bean name is LoginSession

    FacesContext fc = event.getFacesContent();
    ExpressionFactory expressionFactory = fc.getApplication().getExpressionFactory();
    ValueExpression valueExpression = expressionFactory.createValueExpression(fc.getELContext(),”#{SessionBeans$LoginSession}”,LoginSession.class);
    LoginSession ls = (LoginSession) valueExpression.getValue((fc.getELContext()));
    boolean logResults = ls.isHasLoggedIn();

    I dont think you need the line “*” I removed it and it seemed to work

  4. Thai says:

    Hi all,

    If I have the code in the afterPhase, I get the … error. So I put the code in the beforePhase as Helper Dude suggested. Then I cannot get the viewId because the event.getFacesContext().getViewRoot() returns a null. So I use ((HttpServletRequest)facesContext.getExternalContext().getRequest()).getRequestURI() to check if this is the login page. But there’s another problem: when the session expires and the page I’m trying to access (let’s call it X) is not the login page, JSF seems to try to restore the view of the page X before the navigationHandler leads us to the login page. Because the view of the page X requires information of a logged in user, there are exceptions. And I get stuck here :(

  5. Armen says:

    Hello people, can anyone provide me full version of
    Login phase listener with all attributes(Login Controller and /etc). Pls send me simple working example.
    More thanks.
    armen.arzumanyan@googlemail.com

  6. aaronbartell says:

    That’s asking for more than I can pull together right now (because I would have to strip a whole bunch of stuff out). Could you detail the specific part you have having an issue with?

    Aaron Bartell
    http://mowyourlawn.com

  7. Brian Leathem says:

    What a great tip, thanks! I ended up using the phase listener to catch whether multiple managed beans have yet been set (other than simply their login), and re-directing accordingly.

    Great stuff,
    Thanks.

  8. bala says:

    Nice stuff.
    is there any possibilities to add more listeers in once life cycle? I am using my listener in RAD. But RAD itself creating one listener. if i delete that its throwing exception.

    thanks in advance.

  9. aaronbartell says:

    Bala,

    Yeah, I don’t see why you couldn’t have more than one listener. I haven’t worked with JSF in a number of months so I am a little rusty and don’t have my environment setup to test it.

    Aaron

  10. abc says:

    hey dude,
    i want to use initilized context , just once after it is initilized,
    for that i tried

    public class MyApplicationContextListener implements ServletContextListener {

    DataBean var;

    public MyApplicationContextListener() {
    }

    public DataBean getVar() {
    return var;
    }

    public void setVar(DataBean var) {
    this.var = var;
    }

    public void contextInitialized(ServletContextEvent event) {
    DataBean dataBean = new DataBean();
    //event.getServletContext().setAttribute(“bookBean”, dataBean);
    // FacesContext context = FacesContext.getCurrentInstance();
    // DataBean dataBean1 = (DataBean) context.getApplication().createValueBinding(“#{myApplicationContextListener}”).getValue(context);

    System.out.println(“contextInitialized >>>>>>>>>>>>>>>>>>>” + dataBean1);
    // System.out.println(“” + findBean(“bookBean”, DataBean.class));

    }

    public void contextDestroyed(ServletContextEvent event) {
    System.out.println(“contextDestroyed >>>>>>>>>>>>>>>>>>>>>>>”);
    }

    }
    nut i am getting injected proporty var as null,
    how to do dude ?

  11. Dai says:

    Hey.

    Just wanted to tell you, how I did it and it works so fine!

    package handlers;

    import beans.LoginBean;
    import javax.faces.application.NavigationHandler;
    import javax.faces.context.FacesContext;
    import javax.faces.event.PhaseEvent;
    import javax.faces.event.PhaseId;
    import javax.faces.event.PhaseListener;
    import javax.servlet.http.HttpServletRequest;

    /**
    *
    * @author Dai
    */
    public class LoginPhaseListener implements PhaseListener {

    public void afterPhase(PhaseEvent event) {
    FacesContext context = event.getFacesContext();
    NavigationHandler navi = context.getApplication().getNavigationHandler();
    String viewid = context.getViewRoot().getViewId();

    if(!loggedIn(context) && !viewid.equals(“/index.jsp”))
    navi.handleNavigation(context, null, “logout”);
    }

    public void beforePhase(PhaseEvent event) {
    }

    private boolean loggedIn(FacesContext cont)
    {
    LoginBean b = (LoginBean)((HttpServletRequest) (cont.getExternalContext().getRequest())).getSession().getAttribute(“loginBean”);

    if(b != null)
    if(b.getLoggedIn())
    return true;

    return false;
    }

    public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
    }

    }

    You can just get your bean out of the session (of course just if it’s a sessionbean!)

Leave a Reply