2010-11-19 5 views
3

時々nullで、時にはません。マネージドBeanは、私が管理Bean LoginBeanを持って

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経由のログインしようとすると、ここで私は私が

を行うNullPointerExceptionがbean.setUser(facebookUser)

を得るこれは私が最初にブラウザを閉じた場合にも、起こり再び開き、 Facebook経由でログインしようとします。なぜこうなった?

私はGlassfish v3を使用しています。

答えて

4

セッションスコープのBeanがnullの場合、まだセッション用に作成されていないことを意味します。これは、新鮮なセッションの最初の要求時に発生する可能性があります。自分で作成してセッションスコープに入れてください。 JSFはセッションの残りの部分でJSFを再利用します。

セッションスコープの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); 
} 
// ... 

PhaseListenerのインスタンス変数としてBeanを宣言することはできません。つまり、アプリケーションの存続期間中に単一のPhaseListenerインスタンスが存在するため、すべてのインスタンス変数はすべての要求/セッションで共有されます。つまり、スレッドセーフではありません。

2

PhaseListenerが最初のフェーズで起動しているので、作成前にBeanを使用しようとしているようです。後の段階に移行しようとしましたか?

編集: あなたがtrueに設定さクレートフラグとのセッションにアクセス:

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

このように、新しく作成されたセッションは文句を言わない任意のセッションは、豆をスコープ含まれています。 フレームワークはセッションスコープのBeanをインスタンス化し、Beanを参照する式が評価されたときにセッションオブジェクトを配置しますが、ここでは該当しません。

+2

ブール値フラグはセッションを強制的にリフレッシュしません。サーブレット・コンテナがまだ存在していない場合は、新しいサーブレット・コンテナを作成するよう指示します。この原因は、実際には、最初の文のように(まだBeanが作成されていない)あまりにも早い段階でフックすることによるものです。 – BalusC

+0

そうですが、アクティブなセッションがない場合、新しいセッションが作成されます。その場合、セッションスコープBeanは使用できません。または私はここに何かを逃していますか? ;-) – tasel

+1

あなたの答えは、それがtrueにcreateフラグを設定することによって引き起こされることを意味しています。これは間違っています。 – BalusC

関連する問題