2

I have a stateful, session scoped (CDI) EJB that holds the info about the user session.

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

Now, I want to call cerrarSesion() (closeSession()) from an 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);
    }
  }
}

And I access the EJB from the webapp, directly (injecting using @EJB) into the beans that I use for JSF (they are also CDI managed beans).

The issue that I face is that it seems that the HttpSessionListener seems to be in a different "session scope" than the JSF beans. Two instances of GestorSession are created; one instantiated from the JSF and other instantiated from the HttpSessionListener.

I have tried injecting the bean via @Inject Instance<IGestorSesionLocal>, @Inject IGestorSesionLocal and BeanManager, with identical results.

This bug report suggests that it should to work correctly (the bug is solved for my version), but I still cannot get around it. I have looked around, but what I find are Q&A relating to JSF managed beans (yes, I could try to wrap a reference to the EJB in a JSF managed bean, but I would like to try it "correctly" first).

Working with WilFly 8.1.0 and JDK 7

Any ideas?

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • @BalusC I tried, but session invalidation does not trigger `@PreDestroy`. It is either that it expects the bean to timeout or (as I read somewhere but I somewhat doubt) that the container is passivating the EJBs and throwing away them without calling `PreDestroy` EJB. Either way, `@PreDestroy` is not being called (at least in the short term) unless I call `@Remove`. I do that for user-initiated logout, and I am trying to control that for timeout-initiated logout. – SJuan76 Jan 29 '15 at 17:06
  • Some things don't look right here. `@Stateful` will give you an EJB; `@SessionScoped` should give you a CDI managed bean (I'm not sure what the behaviour will be without `@Named`). If you're dealing strictly with `@Stateful`, two separate calls are not guaranteed to give you the same instance of the EJB. Applying both `@Stateful` and `@SessionScoped` on the same class will give you one EJB and one CDI bean, both of which don't necessarily have knowledge of each other. At best, what you get is an inconsistent bean state. Why are you combining a managed bean and EJB in one class definition? – kolossus Jan 30 '15 at 04:52

1 Answers1

4

I think your pb comes from here:

And I access the EJB from the webapp, directly (injecting using @EJB) into the JSF beans.

When use CDI with EJB (by putting a @Sessionscoped on it for instance) you got an CDI bean that also has an EJB nature but not the other way around. In other word CDI is aware of the EJB nature but EJB is not aware of CDI.

So if you want to inject an EJB as a CDI bean in your code use @Inject and not @EJB. From Java EE 6 the admitted good practice is to always use @Inject except for EJB remote.

Also be sure to only use CDI managed bean and not a mix of CDI and JSF managed bean.

Antoine Sabot-Durand
  • 4,875
  • 17
  • 33
  • Thanks for your help! I'll try switching `@EJB` to `@Inject` on monday (I am out of office today). For the "CDI vs JSF" point, I was not clear enough, the JSF beans *are* CDI managed beans (but used for displaying the JSF pages), I'll correct that into the question. – SJuan76 Jan 30 '15 at 10:07