Jsf 无法在HttpSessionListener中注入CDI@SessionScoped

Jsf 无法在HttpSessionListener中注入CDI@SessionScoped,jsf,jakarta-ee,cdi,wildfly-8,Jsf,Jakarta Ee,Cdi,Wildfly 8,我有一个有状态的会话作用域(CDI)EJB,它保存有关用户会话的信息 @Stateful @SessionScoped public class GestorSesion implements IGestorSesionLocal, Serializable { private final static long serialVersionUID = 1L; private static final Logger log = Logger.getLogger(GestorSesion

我有一个有状态的会话作用域(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

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);
    }
  }
}
public类gestorsessionweb实现HttpSessionListener{
私有静态最终记录器log=Logger.getLogger(GestorSesionWeb.class.getName());
@注入
私人案例管理;
@凌驾
已创建公共无效会话(HttpSessionEvent se){
if(日志可隔离(级别精细)){
log.fine(“Iniciada sesión web”);
}
get().GETSESIONFO();
}
@凌驾
public void sessionDestroyed(HttpSessionEvent se){
if(日志可隔离(级别精细)){
log.fine(“Limpiando sesión al-salir”);
}
试一试{
this.gestorSesion.get().cerrarSesion();
if(日志可隔离(级别精细)){
log.fine(“Sesión limpiada罪恶问题”);
}
}捕获(例外e){
log.log(Level.WARNING,“Excepción limpiando sesión”,e);
}
}
}
我从webapp直接访问EJB(使用
@EJB
)到我用于JSF的bean中(它们也是CDI管理的bean)

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

我尝试过通过
@injectinstance
@injectigestorsesionlocal
BeanManager
注入bean,结果相同

建议它应该能够正常工作(错误在我的版本中已经解决),但我仍然无法摆脱它。我环顾四周,但我发现的是与JSF托管bean相关的Q&A(是的,我可以尝试在JSF托管bean中封装对EJB的引用,但我想先“正确地”尝试一下)

使用WilFly 8.1.0和JDK 7


有什么想法吗?

我认为您的pb来自这里:

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

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

因此,如果您想将EJB作为CDIBean注入代码中,请使用
@inject
而不是
@EJB
。从JavaEE6中,公认的良好实践是始终使用
@Inject
,EJB远程除外


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

@BalusC我尝试过,但会话无效不会触发
@PreDestroy
。要么它期望bean超时,要么(正如我在某处读到的,但我有点怀疑)容器正在钝化EJB并丢弃它们,而不调用
PreDestroy
EJB。无论哪种方式,
@PreDestroy
都不会被调用(至少在短期内),除非我调用
@Remove
。对于用户发起的注销,我会这样做,对于超时发起的注销,我会尝试控制它
@Stateful
将为您提供一个EJB
@SessionScoped
应该为您提供一个CDI管理的bean(我不确定如果没有
@命名
,会有什么行为)。如果您严格处理的是
@Stateful
,则两个单独的调用不能保证为您提供相同的EJB实例。在同一个类上应用
@Stateful
@SessionScoped
将为您提供一个EJB和一个CDIBean,它们不一定相互了解。充其量,您得到的是一个不一致的bean状态。为什么要将托管bean和EJB组合在一个类定义中?感谢您的帮助!周一我将尝试将
@EJB
切换到
@Inject
(我今天不在办公室)。对于“CDI vs JSF”这一点,我还不够清楚,JSF bean是CDI管理的bean(但用于显示JSF页面),我将在问题中纠正这一点。