Adding audit information to entities in the Seam framework.

2 min 392 words
Peter Tillemans Profile picture

Categories: programming

Tags: jvm

Since we write a lot of stuff for use in the production side of the business we need to comply with rules which allow effective control that the processes and procedures have been followed. In the automotive industry people take these measures seriously.

One of these requirements we often get is that all configuration data elements must contain information on who created this information and when, and similarly for the last update.

Since the advent of EJB3 and JPA we now have nice POJO entities which clearly show the structure of the data and the last thing we want is to add a bunch of boilerplate code which multiplies the number of code lines with redundant stuff.

This blogpost of Daniel Pfeifer shows how to do this using an entity listener. However, it does not work using Seam since we cannot get the user information through the EJBContext, at least not on JBoss 4.2.3.

After wasting the better part of an afternoon barking up the wrong tree, the answer came to me next morning during breakfast. I have the unhealthy habit of reading PDF-files between bites, in this case chapter 15 of the Seam manual. The security section. (Yes, I know, I hould have done this sooner, you know : "if all else fails, read the manual.")

Seam provides a nice utility class aptly named org.jboss.seam.security.Identity which provides all we need to get the name of the person logged in the current session. So replacing the implementation of getCallerIdentity() with the following, we now have nice audit trails.

/**
* Get the name of the currently logged in user.
*
* This part contains the framework specific code to get the active username.
* In this case we use the Seam provided Identity.instance() to get at this
* information.
*
* @param t
* @return
*/
private String getCallerIdentity(Traceable t) {
   try {
     // get the identity principal to get information about the current active user
     Principal principal = Identity.instance().getPrincipal();
     if (log.isDebugEnabled())
       log.debug("AuditLogger.getCallerIdentity returned " + principal.getName());

     return principal.getName();

   } catch (Exception e) {
     log.error("Exception received : " + e.getClass().getName() + ":" + e.getMessage());
     return "unknown";
   }
}

I provided both the interface and mapped superclass implementations for convenience. All what is now remaining is to extend our configuration POJO's from the TraceableEntity class (and create an update script, and modify the UI to get at the audit info, ...) to make our stuff auditable.