I’m trying to implement some sort of auditing in a Java EE JPA (2.0) application on GlassFish 3.
I have added a @EntityListeners annotation on my @MappedSuperclass entity, the listener has the @PrePersist and @PreUpdate annotation on its methods which are invoked happily at runtime.
In these methods, I’m trying to use (@Inject) a @Named, @Stateful, @SessionScoped bean (UserSession) in order to get current user’s id. The listener class has no annotations at all.
The problem is that I can’t get the UserSession bean injected; I always end up with a null value. To this time, I tried the plain @Inject UserSession us; which always injects a null value.I also tried UserSession us = (UserSession) ctx.lookup("java:global/application/module/UserSession"); which always returns a new object (I verified the constructor call, plus the object is empty).
I’m pretty sure I have missed something very important regarding CDI but I can’t figure out what. Could someone please point me to the right direction?
I eventually found a workaround, which allows me to get a reference of the
@Statefulbean:I created a
@Named @Singleton @Startupbean SessionController which holds a localHashMap<String, UserSession> sessionMapwith the references of my@Statefulbeans:}
I add the references from within each bean’s
@PostConstructmethod:Notice the
.getSession(true)which is required since the Session might not be created yet. Also notice thatthisis safely passed since the@PostConstructis not the constructor…After all these, I can get the reference in my EntityListener (and any other place) like this:
or like this in CDI beans
The only drawback I see is that this approach works well only for web applications (where
FacesContext context = FacesContext.getCurrentInstance()is meaningful). Some of my beans (and finally my EntityListeners) are also exposed via@javax.jws.WebServiceas@Statelessbeans. In this context (actually: absence of), my Singleton wouldn’t work (haven’t tested yet) since there is no sessionId of any kind (no session at all to be exact). I will have to use a workaround for this, possibly using SessionContext of the bean or inventing a usable sessionId of some sort. I will post back if I create something usable…