This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

place for auditing interception

I intend to do auditing of database tables in a particular application using triggers within the database. The decision to use triggers (and not java) is the database has other entry points.

Due to the nature of the typical 3 tier j2ee app (where pooled connections are used), it is not possible to use the session user id when writing the user id (who made the changes). Oracle provides some work around for this, in that it is possible to set things in a session context, that can then be retrieved by a stored procedure.

So, my question is this. If I need to always make sure this is set via jdbc call before any data access code, where would be the best place to put it? Since the application already uses spring transaction management (tx:annotation stuff...) would it make sense to try to do it as a interceptor on the service classes that already have transaction interceptors?

How will you get the user identity? Unless this is to be hardcoded in configuration, or you have some other smart way of determining it, you will need to set this in your code. And there's no simple way to pass a parameter to an interceptor, unless you get into madness like "annotate the string argument that is the username with @ThisIsTheUsername"

My suggestion would be this:
You will need several co-operating classes.
A DoAsUserTemplate that puts the user into a ThreadLocal scoped bean.

The DoAsUserTemplate would be modelled after e.g. TransactionTemplate and be used like this:

It would first test whether a ThreadLocal bean already existed and throw an exception if it did and representeda different user. Then put the user into the threadLocal bean before calling doAsUser and, in a finally clause, remove it afterwards if it had been put in.

Then wrap your datasource inside a a UserSetupDataSource which extracts the user from the ThreadLocal class and does the Alter Session before passing on the DataSource. It should probably throw an exception, if no user has been set up.

Comment

Or use Spring AOP to weave the checking code around the DAOs instead of services, for two reasons - logically this validation is a concern of the DAO layer not the service layer; practically a service call doesn't always end up in a jdbc call, so there is no point to check prematurely.