6 Replies Latest reply on Feb 10, 2012 4:49 PM by Adam Warski

    Custom Revision Listener - Getting user related information

    Chetan M Newbie



      This might sound trivial.The example in the documentation relies on a Context object being available.

      We have a webapp where the user information is in the session(http).How do i get hold of it in my CustomRevisionListener,especially since its not part of the bean configurations that the Spring container takes care of.

      There was a similar question somewhere else but no replies.Not sure if the poster got the answers he/she was looking for.


      Any thoughts about how do I go about this.?




        • 1. Re: Custom Revision Listener - Getting user related information
          Adam Warski Master

          The not-so-nice approach, but working, is to use a ThreadLocal (that's in fact how all static lookups in Weld or such work).

          Alternatively, you can get the current revision entity from the AuditReader.



          1 of 1 people found this helpful
          • 2. Re: Custom Revision Listener - Getting user related information
            Chetan M Newbie

            Thanks Adam,I did the same and then realised it is rather easier/safer to rely on Springcontext rather than my own ThreadLocal variable.

            So,modified the LoginFilter that we had to add the Principal there and then in my listener use

            Springcontextholder.getContext().getAuthentication() to

            1) get the Principal

            2)typecast to my UserInfo object and

            3) finally get the user attribute that I'm interested in.




            • 3. Re: Custom Revision Listener - Getting user related information
              Chetan M Newbie

              I have a new problem now.Haven't still got to the the root of it.While i had all of this working,a few team members introduced one more step in the save and on their branch of code Envers Auditing fails always.The root cause is a Nullpointer exception in my RevisionListener where I do a SecurityContextHolder.getContext().getAuthentication().

              The authentication object is null.


              Interestlingly,since I couldn't trace any kind of conflicts/bugs that may have been introduced in the new changes I mentioned earlier on,I added a SecurityContext.setStrategy(THREADMODE_INHERITABLE).

              With this stratgey I don't get any null pointer now.So my hunch is that Envers auditing code is executed by a seperate thread and hence the ThreadLocal Authentication object was null.

              Is this how Envers works?

              I had it working before without having to set the strategy as I have done now.


              Any pointers will be a great help.


              Here is the stack trace for your reference




              ERROR 2012-01-27 16:15:18,617 [Thread-27] (org.hibernate.AssertionFailure) - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)


                              at com.mycomp.dealworks.domain.DWRevisionListener.getLoggedInUserSid(DWRevisionListener.java:47)

                              at com.mycomp.dealworks.domain.DWRevisionListener.newRevision(DWRevisionListener.java:33)

                              at org.hibernate.envers.revisioninfo.DefaultRevisionInfoGenerator.generate(DefaultRevisionInfoGenerator.java:86)

                              at org.hibernate.envers.synchronization.AuditProcess.getCurrentRevisionData(AuditProcess.java:121)

                              at org.hibernate.envers.synchronization.AuditProcess.executeInSession(AuditProcess.java:104)

                              at org.hibernate.envers.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:143)

                              at org.hibernate.engine.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:543)

                              at org.hibernate.engine.ActionQueue.beforeTransactionCompletion(ActionQueue.java:216)

                              at org.hibernate.impl.SessionImpl.beforeTransactionCompletion(SessionImpl.java:571)

                              at org.hibernate.jdbc.JDBCContext.beforeTransactionCompletion(JDBCContext.java:250)

                              at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:138)

                              at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)

                              at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)

                              at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)

                              at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)

                              at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)

                              at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)

                              at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)












              • 4. Re: Custom Revision Listener - Getting user related information
                Adam Warski Master

                You should see if it's the same thread or not from the stack trace. Normally it is the same thread - I haven't seen it implemented otherwise yet. Maybe Spring already clears some contexts?



                • 5. Re: Custom Revision Listener - Getting user related information
                  Chetan M Newbie

                  Yes you are right.Nothing wrong with Spring.We were the culprits again.There was an explicit Thread being spawned for the save to show some progress bar (to allow for some documents that are uploaded also to be stored in a seperate thread).This thread was actually incharge of the entire save and as such the spawned thread did not have access to the SecurityContext.

                  Having got to this point and realised why the null pointer was happening, we spotted that SecurityContext has a strategy that allows for spawned threads to inherit ThreadLocal objects from their parent threads.

                  So finally ended up adding a ContextListener to web.xml,that sets this strategy on the SecurityContextHolder.

                  Now it works like a charm again.