2010-11-19 20 views
3

j'ai un LoginBean de haricot géré:managed bean est parfois nul et parfois

@ManagedBean(name = "loginBean") 
@SessionScoped 
public class LoginBean implements Serializable { 

    private String email, password; 
    private BasicUser user; 

    /** Creates a new instance of LoginBean */ 
    public LoginBean() { 
    } 

    public void setUser(BasicUser user) { 
     this.user = user; 
    } 

    public BasicUser getUser() { 
     return user; 
    } 

    ... 
} 

Et puis un PhaseListener qui obtient le loginBean sessions.

public class FacebookSignInListener implements PhaseListener, UserService { 
private LoginBean bean;  
.... 

    @Override 
    public PhaseId getPhaseId() { 
     return PhaseId.RENDER_RESPONSE; 
    } 

    @Override 
    public void afterPhase(PhaseEvent event) { 
    HttpSession session = (HttpSession) event.getFacesContext().getExternalContext().getSession(true); 
    bean = (LoginBean) session.getAttribute("loginBean"); 
    bean.setUser(facebookUser); 
} 
    @Override 
    public void beforePhase(PhaseEvent event) { 
    FacesContext fc = FacesContext.getCurrentInstance(); 
    request = (HttpServletRequest) fc.getExternalContext().getRequest(); 
    boolean isLoginPage = 
      (fc.getViewRoot().getViewId().indexOf("welcome") > -1); 
    if (isLoginPage) { 
     try { 
      FBOauth fbo = new FBOauth(this); 
      fbo.doLogin(request); 
     } catch (IOException ex) { 
      Logger.getLogger(FacebookSignInListener.class.getName()).log(Level.SEVERE, "Could not exchange code for access_token. Page where not found.", ex); 
     } 
    } 
} 

    @Override 
    public boolean authFacebookLogin(String accessToken, FacesContext fc) throws FacebookException { 
     if (accessToken != null) { 
      FacebookClient facebookClient = new DefaultFacebookClient(accessToken); 
      User fbUser = facebookClient.fetchObject("me", User.class); 

      UserHelper uh = new UserHelper(); 
      FacebookUser facebookUser = (FacebookUser) uh.getByFacebookId(fbUser.getId());   
// Does the user already exist and is he already connected with facebook. 
      if (facebookUser != null) {    
       return true; 
      } 
     } 
     } 
} 

Quand je déploie après sur l'application de lancement de presse de la console d'administration, les journaux dans mon application via Facebook il n'y a pas de problème avec le code ci-dessous. Je peux me déconnecter et me reconnecter et toujours pas de problème. Si je change ensuite navigateur et tente de se connecter via facebook ici je reçois un NullPointerException où je

bean.setUser (facebookUser)

Cela se produit également si je ferme le premier navigateur, ouvre à nouveau et essaie de se connecter via facebook. Pourquoi cela arrive-t-il? J'utilise Glassfish v3.

Répondre

4

Si le bean de portée de la session est null, cela signifie simplement qu'il n'a pas encore été créé pour la session. Cela peut arriver lors de la toute première demande d'une nouvelle session. Vous devez le créer vous-même et le placer dans la portée de la session. JSF va juste le réutiliser dans le reste de la session.

Votre façon de saisir le bean session est un peu maladroite. Vous obtenez l'API Servlet brute sous les hottes du JSF. Vous pouvez également utiliser ExternalContext#getSessionMap() pour gérer les attributs de session.

Map<String, Object> sessionMap = externalContext.getSessionMap(); 
LoginBean loginBean = (LoginBean) sessionMap.get("loginBean"); 
if (loginBean == null) { 
    loginBean = new LoginBean(); 
    sessionMap.put("loginBean", loginBean); 
} 
// ... 

Notez que vous ne devez pas déclarer la fève comme une variable d'instance du PhaseListener. Il y a une seule instance PhaseListener pendant toute la durée de vie de l'application, donc toutes les variables d'instance seraient partagées entre toutes les requêtes/sessions. En d'autres termes: ce n'est pas threadsafe.

2

On dirait que vous essayez d'utiliser le bean avant qu'il ne soit créé car votre PhaseListener est en train de tirer dans la première phase. Avez-vous essayé de passer à une phase ultérieure?

Edit: Vous accédez à la session avec le drapeau de caisse est défini sur true:

HttpSession session = (HttpSession) externalContext.getSession(true); 

Ainsi, votre session nouvellement créée comprend wont une session scope haricots. Le Framework instanciera le bean de portée de session et placera l'objet de session lorsqu'une expression référençant le bean est évaluée, ce qui n'est pas le cas ici.

+2

L'indicateur booléen ne force pas la session en cours d'actualisation. Il indique simplement au servletcontainer d'en créer un nouveau s'il n'existe pas déjà. La cause est en effet due à l'accrochage sur une phase trop précoce (quand le haricot n'est pas encore créé) comme dans votre 1ère phrase. – BalusC

+0

À droite, mais au cas où il n'y a pas de session active, il en créera une nouvelle. Dans ce cas, la session scoped bean ne sera pas disponible. Ou est-ce que je manque quelque chose ici? ;-) – tasel

+1

Votre réponse implique qu'il est provoqué en définissant l'indicateur de création à true. C'est faux. – BalusC