0

HttpSessionListener内から特定のプロパティを変更するには、アプリケーションスコープのマネージドBeanにアクセスする必要があります。

私はすでに次のようなものを使用しました:

@Override
public void sessionDestroyed(HttpSessionEvent se) {
    HttpSession session = se.getSession();
    User user = userService.findBySessionId(session.getId());    

    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();

     ApplicationScopedBean appBean = (ApplicationScopedBean) externalContext.getApplicationMap().get("appBean");

     appBean.getConnectedUsers().remove(user);
}

externalContext = FacesContext.getCurrentInstance()。getExternalContext()は、ここですでにnullポインター例外を引き起こします。そうでない場合でも、上記の方法でappBeanにアクセスできるかどうかはわかりません。

何か案は?

4

1 に答える 1

3

FacesContext、を呼び出したWebブラウザによって開始されたHTTPリクエストを処理するスレッドでのみ使用できますFacesServlet。セッションの破棄中に、必ずしもHTTPリクエストの手段があるとは限りません。セッションは通常、コンテナによって管理されるバックグラウンドスレッドによって破棄されます。これは、を介してHTTPリクエストを呼び出しませんFacesServletFacesContextしたがって、セッションの破棄中に常にそこにあると期待するべきではありません。session.invalidate()JSFマネージドBean内で呼び出す場合にのみ、FacesContextが使用可能になります。

アプリケーションスコープのマネージドBeanがJSFによって管理されている場合は@ManagedBean、JSFがそれをの属性として内部に格納していることを知っておくとよいでしょうServletContext。次にServletContext、セッションリスナーで。によって使用できますHttpSession#getServletContext()

したがって、これは次のことを行う必要があります。

@Override
public void sessionDestroyed(HttpSessionEvent se) {
    HttpSession session = se.getSession();
    User user = userService.findBySessionId(session.getId());    
    ApplicationScopedBean appBean = (ApplicationScopedBean) session.getServletContext().getAttribute("appBean");
    appBean.getConnectedUsers().remove(user);
}

サーブレット3.0対応のコンテナを実行している場合は、アプリケーションスコープのBeanに実装させ、HttpSessionListener構築時にそのように登録することもできます。このようにして、connectedUsersプロパティを直接参照できます。

@ManagedBean
@ApplicationScoped
public class AppBean implements HttpSessionListener {

    public AppBean() {
        ServletContext context = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
        context.addListener(this);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        User user = userService.findBySessionId(session.getId());    
        connectedUsers.remove(user);
    }

    // ...
}

また、別の方法はUser、セッションスコープのマネージドBeanとしてセッションスコープ内に保持することです。次に、アノテーションを使用して@PreDestroy、セッションが破棄されたときに呼び出されるメソッドをマークできます。

@ManagedBean
@SessionScoped
public class User {

    @ManagedProperty("#{appBean}")
    private AppBean appBean;

    @PreDestroy
    public void destroy() {
        appBean.getConnectedUsers().remove(this);
    }

    // ...
}

Userこれには、がELコンテキストで利用できるという追加の利点があります#{user}

于 2012-05-15T16:38:37.323 に答える