7 Replies Latest reply on Jul 21, 2010 7:34 AM by pmuir

    Get current user in non-managed bean (EntityListener)

    andersaa
      Hi guys
      I am trying to create an EntityListener that sets audit data automatically: timestamp and the current user's id. The user id is stored in a @SessionScoped bean and works as expected in the rest of the application.

      But it looks like I cannot do injection into an EntityListener, since it is not a managed bean.. A similar problem is discussed here:
      http://forums.java.net/jive/thread.jspa?threadID=57825

      I have tried using jndi to lookup a stateful or stateless EJB that has the injected UserData bean, but it seems like I get the same EJB instance and therefore the same UserData instance from two different sessions.

      Any suggestions on how to get the correct instance in this scenario?

      Regards,
      Anders
        • 1. Re: Get current user in non-managed bean (EntityListener)
          alin.heyoulin.qq.com

          I just say you can use seam2 or wait for seam3 persistence module

          • 2. Re: Get current user in non-managed bean (EntityListener)
            andersaa

            Thanks, I will have another look at seam2. It would be better if we can use seam3 (alpha), but what part of the persistence module is relevant here? I am not trying to inject the entity manager, but a @SessionScoped bean that holds the user id.


            Will check out the seam3 source now and have a look.


            -Anders

            • 3. Re: Get current user in non-managed bean (EntityListener)
              nickarls

              Show some code.


              If you're making a JPA EntityListener I don't see why you wouldn't be able to get a reference to the BeanManager from JNDI and the get a reference to the UserBean and set the data in a @PrePersist or something like that. How are you packing the listeners?

              • 4. Re: Get current user in non-managed bean (EntityListener)
                andersaa

                Hi again!


                Just as I saw your reply, I finally got it working.. I suspect it was a bug somewhere else. So now it works, but I can't really understand how..


                My entity listener now looks up a stateless EJB using JNDI:


                UserDataService userDataService = (UserDataService)context.lookup("java:module/UserDataService)";
                UserData userData = userDataService.getUserData();
                entity.setAuditUser(userData.getUid());



                This EJB has an injected UserData instance:


                @Stateless
                public class UserDataServiceImpl implements UserDataService {
                
                @Inject
                private UserData userData;
                
                @Override
                public UserData getUserData() {
                     return userData;
                }



                .. which in turn is a @SessionScoped bean:




                @SessionScoped
                public class UserData implements Serializable {
                
                     private String uid;
                     private String culture;
                     private OperatorRole operatorRole;
                ...



                So with two users writing entities at the same time, i get the different uid's in the different sessions. The UserData object is obviously session aware, but I thought that I only had one instance of the @Stateless bean. And that JNDI lookup did not know about sessions at all.


                Will have to debug some more to figure this stuff out. Thanks again guys!


                Oh and by the way, where can I find the BeanManager in jndi? I thought about this approach, but couldn't find it in the JNDI tree (I dumped the whole tree to the console but found no trace of it)..


                Regards,


                Anders




                • 5. Re: Get current user in non-managed bean (EntityListener)
                  nickarls

                  It should be in java:comp/BeanManager (per spec) or java:app/BeanManager (per JBoss) ;-)


                  Tried something like


                    BeanManager bm = // lookup it from JNDI
                    Bean<?> userDataBean = bm.resolve(bm.getBeans(UserData.class));
                    UserData userData = (UserData) bm.getReference(userDataBean, UserData.class, bm.createCreationalContext(userDataBean));
                  



                  That should pick up the instance.

                  • 6. Re: Get current user in non-managed bean (EntityListener)
                    andersaa

                    Tried that in Glassfish V3.0 (embedded) and got this exception:


                    javax.naming.NamingException: Error retrieving java:comp/BeanManager [Root exception is java.lang.IllegalStateException: Cannot resolve bean manager]
                         at org.glassfish.weld.BeanManagerNamingProxy.handle(BeanManagerNamingProxy.java:130)
                         at com.sun.enterprise.naming.impl.NamedNamingObjectManager.tryNamedProxies(NamedNamingObjectManager.java:84)
                         at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:153)
                         at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:428)
                         ... 67 more
                    Caused by: java.lang.IllegalStateException: Cannot resolve bean manager
                         at org.glassfish.weld.BeanManagerNamingProxy.handle(BeanManagerNamingProxy.java:120)
                         ... 70 more



                    So the JNDI path looked right, I got a different exception with a non-existing path. Any idea what the exception means?


                    -Anders

                    • 7. Re: Get current user in non-managed bean (EntityListener)
                      pmuir

                      It means it can't find BeanManager in JNDI. You would need to discuss this on the GF forums, GF is responsible for binding the BeanManager to JNDI (not Weld).


                      You could file a feature request in https://jira.jboss.org/jira/browse/SEAMPERSIST for supporting injection into EntityListener.