【问题标题】:Cannot inject CDI @SessionScoped in HttpSessionListener无法在 HttpSessionListener 中注入 CDI @SessionScoped
【发布时间】:2015-03-28 21:57:39
【问题描述】:

我有一个有状态的会话范围 (CDI) EJB,其中包含有关用户会话的信息。

@Stateful
@SessionScoped
public class GestorSesion implements IGestorSesionLocal, Serializable {

  private final static long serialVersionUID = 1L;

  private static final Logger log = Logger.getLogger(GestorSesion.class.getName());

  @PostConstruct
  private void init() {
    log.info("Configurando información de usuario");
    log.info("****************************************************************************");
  }

  @Override
  public void cerrarSesion() {
  }

  @Override
  public ISessionInfo getSesionInfo() {
    return null;
  }
}

现在,我想从HttpSessionListener 拨打cerrarSesion() (closeSession())

public class GestorSesionWeb implements HttpSessionListener {


  private static final Logger log = Logger.getLogger(GestorSesionWeb.class.getName());

  @Inject
  private Instance<IGestorSesionLocal> gestorSesion;

  @Override
  public void sessionCreated(HttpSessionEvent se) {
    if (log.isLoggable(Level.FINE)) {
      log.fine("Iniciada sesión web");
    }
    gestorSesion.get().getSesionInfo();
  }

  @Override
  public void sessionDestroyed(HttpSessionEvent se) {
    if (log.isLoggable(Level.FINE)) {
      log.fine("Limpiando sesión al salir");
    }
    try {
      this.gestorSesion.get().cerrarSesion();
      if (log.isLoggable(Level.FINE)) {
        log.fine("Sesión limpiada sin problemas");
      }
    } catch (Exception e) {
      log.log(Level.WARNING, "Excepción limpiando sesión", e);
    }
  }
}

我从 webapp 直接访问 EJB(使用 @EJB 注入)到我用于 JSF 的 bean(它们也是 CDI 管理的 bean)。

我面临的问题是,HttpSessionListener 似乎与 JSF bean 处于不同的“会话范围”中。创建了两个GestorSession 实例;一个从 JSF 实例化,另一个从 HttpSessionListener 实例化。

我尝试通过@Inject Instance&lt;IGestorSesionLocal&gt;@Inject IGestorSesionLocalBeanManager 注入bean,结果相同。

This bug report 建议它应该可以正常工作(我的版本已解决该错误),但我仍然无法解决它。我环顾四周,但我发现的是与 JSF 托管 bean 相关的问答(是的,我可以尝试在 JSF 托管 bean 中包装对 EJB 的引用,但我想先“正确”尝试)。

使用 WilFly 8.1.0 和 JDK 7

有什么想法吗?

【问题讨论】:

  • @BalusC 我试过了,但会话失效不会触发@PreDestroy。要么是它期望 bean 超时,要么(正如我在某处读到的,但我有些怀疑)容器正在钝化 EJB 并在没有调用 PreDestroy EJB 的情况下丢弃它们。无论哪种方式,除非我打电话给@Remove,否则不会调用@PreDestroy(至少在短期内)。我为用户启动的注销执行此操作,并且我正在尝试控制超时启动的注销。
  • 有些东西在这里看起来不正确。 @Stateful 会给你一个 EJB; @SessionScoped 应该给你一个 CDI 托管 bean(我不确定如果没有 @Named 会有什么行为)。如果您严格处理@Stateful,则不能保证两个单独的调用会为您提供相同的EJB 实例。在同一个类上同时应用@Stateful@SessionScoped 将为您提供一个EJB 和一个CDI bean,它们不一定相互了解。充其量,你得到的是一个不一致的 bean 状态。为什么要将托管 bean 和 EJB 组合在一个类定义中?

标签: jsf jakarta-ee cdi wildfly-8


【解决方案1】:

我认为你的 pb 来自这里:

我直接从 webapp 访问 EJB(使用注入 @EJB) 进入 JSF bean。

当将 CDI 与 EJB 一起使用时(例如,通过在其上放置 @Sessionscoped),您会得到一个 CDI bean,它也具有 EJB 特性,但反之则不然。换句话说,CDI 知道 EJB 的性质,但 EJB 不知道 CDI。

因此,如果您想在代码中将 EJB 作为 CDI bean 注入,请使用 @Inject 而不是 @EJB。从 Java EE 6 开始,公认的良好做法是始终使用 @Inject,EJB 远程除外。

还要确保只使用 CDI 托管 bean,而不是 CDI 和 JSF 托管 bean 的混合。

【讨论】:

  • 感谢您的帮助!我会在星期一尝试将@EJB 切换为@Inject(我今天不在办公室)。对于“CDI 与 JSF”这一点,我还不够清楚,JSF bean CDI 托管 bean(但用于显示 JSF 页面),我会在问题中更正这一点。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-02
  • 1970-01-01
  • 2012-03-30
  • 2019-08-04
  • 2011-07-11
  • 2016-12-04
相关资源
最近更新 更多