Ways to pass additional data to Custom RevisionEntity in Hibernate Envers?
<p>It's RESTful web app. I am using Hibernate Envers to store historical data. Along with revision number and timestamp, I also need to store other details (for example: IP address and authenticated user). <a href="http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#envers" rel="noreferrer">Envers</a> provides multiple ways to have a custom revision entity which is awesome. I am facing problem in setting the custom data on the revision entity. </p>

<pre><code>@RevisionEntity( MyCustomRevisionListener.class )
public class MyCustomRevisionEntity extends DefaultRevisionEntity {
    private String userName;

    private String ip;

    //Accessors
}

public class MyCustomRevisionListener implements RevisionListener {
    public void newRevision( Object revisionEntity ) {
        MyCustomRevisionEntity customRevisionEntity = ( MyCustomRevisionEntity ) revisionEntity;
        //Here I need userName and Ip address passed as arguments somehow, so that I can set them on the revision entity. 
    }
}
</code></pre>

<p>Since newRevision() method does not allow any additional arguments, I can not pass my custom data (like username and ip) to it. How can I do that?</p>

<p>Envers also provides another approach as: </p>

<blockquote>
  <p>An alternative method to using the org.hibernate.envers.RevisionListener is to instead call the getCurrentRevision( Class revisionEntityClass, boolean persist ) method of the org.hibernate.envers.AuditReader interface to obtain the current revision, and fill it with desired information. </p>
</blockquote>

<p>So using the above approach, I'll have to do something like this:</p>

<p>Change my current dao method like:</p>

<pre><code>public void persist(SomeEntity entity) {
     ...
     entityManager.persist(entity);
     ...
}
</code></pre>

<p>to </p>

<pre><code>public void persist(SomeEntity entity, String userName, String ip) {
     ...
     //Do the intended work
     entityManager.persist(entity);
     //Do the additional work
     AuditReader reader = AuditReaderFactory.get(entityManager)
     MyCustomRevisionEntity revision = reader.getCurrentRevision(MyCustomRevisionEntity, false);
     revision.setUserName(userName);
     revision.setIp(ip);

}
</code></pre>

<p>I don't feel very comfortable with this approach as keeping audit data seems a cross cutting concern to me. And I obtain the userName and Ip and other data through HTTP request object. So all that data will need to flow down right from entry point of application (controller) to the lowest layer (dao layer). </p>

<p>Is there any other way in which I can achieve this? I am using Spring. </p>

<p>I am imagining something like Spring keeping information about the 'stack' to which a particular method invocation belongs. So that when <code>newRevision()</code> in invoked, I know which particular invocation at the entry point lead to this invocation. And also, I can somehow obtain the arguments passed to first method of the call stack. </p>