How to retrieve a session scoped managed bean in a PhaseListener?

andreaxi picture andreaxi · Sep 15, 2012 · Viewed 7.3k times · Source

I'm having troubles in setting an Authorization Listener (that implements PhaseListener) to manage authentication and autorization.

More specifically, I set a session scoped bean called SessionBean:

@ManagedBean
@SessionScoped
public class SessionBean{

   private String loggedUser;

   public SessionBean(){
    logger.info("Sono nel costruttore di SessionBean()");
   }
   public String login(){
       ....
   }
   ...
}

And in my sun-web.xml:

  <managed-bean>
    <managed-bean-name>SessionBean</managed-bean-name>
    <managed-bean-class>it.uniroma3.acme.auction.bean.SessionBean</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
  </managed-bean>

In login() I make controls on username/password and if successful I set "loggedUser".

My AuthorizationListener is:

public class AuthorizationListener implements PhaseListener {

    private String currentUser;

    private SessionBean sessionBean;

    public void afterPhase(PhaseEvent event) {
        SessionBean sessionBean = (SessionBean)event.getFacesContext().getExternalContext().getSessionMap().get("SessionBean");
        String currentUser = sessionBean.getLoggedUser();

        if (sessionBean != null) {
            ...
               String currentUser = sessionBean.getLoggedUser();
        }
            else {
                 ...
            }
    }

    ...
}

And in the sun-web.xml:

 <!-- Authentication and authorization block starting -->
    <lifecycle>
        <phase-listener>AuthorizationListener</phase-listener>
    </lifecycle>
    <navigation-rule>
        <from-view-id>/*</from-view-id>
        <navigation-case>
            <from-outcome>loginPage</from-outcome>
            <to-view-id>login.jsf</to-view-id>
        </navigation-case>
    </navigation-rule>
  <!-- Authentication and authorization block ending -->

But I receive a null pointe sessionBean.getLoggedUser(). So, the SessionBean is still not created when the AuthorizationListener check the user. This is why I added a "if SessionBean doesn't exists, create it and put it in SessionMap", but still not working.

I'm not forced to use this approach for authentication and authorization, but what I need is to avoid "session.setAttribute("username", username). So any other strategy would be really apreciated. Thanks, Andrea

EDIT: as BalusC suggested, I edited the afterPhase method. Still having troubles with always null SessionBean.

Answer

BalusC picture BalusC · Sep 15, 2012

The @ManagedProperty works in @ManagedBean classes only. Your PhaseListener isn't.

You need to manually get it from the session map.

SessionBean sessionBean = (SessionBean) event.getFacesContext()
    .getExternalContext().getSessionMap().get("SessionBean");

Note that it can be still null on the very first HTTP request.

The common approach, however, is to use a servlet Filter for the job, not a PhaseListener. The session scoped managed bean is available as a session attribute.

SessionBean sessionBean = (SessionBean) session.getAttribute("sessionBean");