2010-11-19 27 views
3

我有一個託管bean LoginBean:託管bean有時是零,有時不

@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; 
    } 

    ... 
} 

然後誰得到會話loginBean一個的PhaseListener。

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; 
      } 
     } 
     } 
} 

當我在管理控制檯按發射後的應用部署,通過Facebook登錄到我的應用程序有一個與下面的代碼沒有問題。我可以註銷並重新登錄,但仍然沒有問題。如果我再改瀏覽器,並試圖通過Facebook登錄這裏,我得到一個NullPointerException,我做

bean.setUser(facebookUser)

如果我關閉第一個瀏覽器也會發生這種情況,再次打開和試圖通過Facebook登錄。這是爲什麼發生?

我正在使用Glassfish v3。

回答

4

如果會話作用域bean是null那麼它只是意味着它尚未爲會話創建。這可能會在新會議的第一次請求期間發生。你必須自己創建它並將它放在會話範圍中。 JSF將在會話的剩餘部分重用它。

你抓取session scoped bean的方式有點笨拙。你從JSF的底層獲得了原始的Servlet API。您也可以使用ExternalContext#getSessionMap()來管理會話屬性。

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

請注意,您不應將bean聲明爲PhaseListener的實例變量。整個應用程序的生命週期中都有一個實例變量,因此所有實例變量都將在所有請求/會話中共享。換句話說:它不是線程安全的。

2

好像你正試圖使用​​這個bean,因爲你的PhaseListener在第一階段觸發了。你是否試圖將其轉移到後期階段?

編輯: 您設置爲true箱子標誌訪問會話:

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

因此,新創建的會話不會包括任何會話範圍豆。 框架將實例化會話範圍的Bean,並在評估引用bean的表達式時將會話對象放入會話對象中,但在此情況並非如此。

+2

布爾標誌不會強制刷新會話。它只是指示servletcontainer創建一個新的,如果它不存在。原因實際上是因爲在第一句話中掛鉤了一個太早階段(當bean尚未創建時)。 – BalusC 2010-11-19 14:21:03

+0

沒錯,但是如果沒有活動的會話,它會創建一個新的會話。在這種情況下,會話作用域bean不會是可用的。或者我在這裏錯過了什麼? ;-) – tasel 2010-11-19 14:39:30

+1

你的答案暗示它是由將create標誌設置爲true而引起的。這是錯誤的。 – BalusC 2010-11-19 15:33:27