Home » General

Filling audit columns automatically with ADF Business Components

Written By: Pascal Alma on January 3, 2007 No Comment

In a previous post I blogged about the use of sequences for the ID column as primary key. This post goes a bit further and describes how you could have audit columns of a table fill automatically. With audit columns I mean the columns in which information is stored about who changed a row and when (or created one).

Of course it is possible to get this functionality by setting the attribute in the entity object to 'history column' and choose the corresponding type. But with this example it is done automatically by matching the column name, which can be handy when you have a lot of tables with auditing columns, which otherwise you have to configure by hand, one by one.
For this purpose I created a specific base class called 'AuditTrailEntityImpl'. In my example the audit columns are named 'CREATED_BY', 'CREATED_DATE', 'MODIFIED_BY' and 'MODIFIED_DATE'. This is my code:

JAVA:
  1. /**
  2. * Extends the base ADF EntityImpl to add support for dynamic filling of audit columns.
  3. * The CREATED_BY and CREATED_DATE attributes are filled in the create()-method,
  4. * the MODIFIED_BY and MODIFIED_DATE attributes are filled in the prepareForDML() method
  5. * (only if incoming operation equals DML_UPDATE).
  6. *
  7. * If you wish to use this functionality, edit your Entity Object and extend from
  8. * base<code>.adf.model.businessobjects.AuditTrailEntityImpl</code>.
  9. *
  10. * @author Pascal Alma
  11. *
  12. * $Log: AuditTrailEntityImpl.java,v $
  13. */
  14. public class AuditTrailEntityImpl extends BaseEntityImpl
  15. {
  16. private static final String CREATED_BY = "CreatedBy";
  17. private static final String CREATED_DATE = "CreatedDate";
  18. private static final String MODIFIED_BY = "ModifiedBy";
  19. private static final String MODIFIED_DATE = "ModifiedDate";
  20.  
  21. private final Log _log = LogFactory.getLog(this.getClass());
  22.  
  23. /**
  24. * Overridden method.
  25. *
  26. * Adds support for filling CREATED-attributes.
  27. * @param nameValuePair
  28. */
  29. protected void create(AttributeList nameValuePair)
  30. {
  31.   final String method = "create(...)";
  32.   _log.debug(method);</samp>
  33.  
  34.   _log.debug("Create instance for '" + getEntityDef().getName() + "'");
  35.   super.create(nameValuePair);
  36.  
  37.   // set 'create' history attributes
  38.   setAttribute(CREATED_BY, getCurrentUser());
  39.   setAttribute(CREATED_DATE, new oracle.jbo.domain.Date(new Timestamp(System.currentTimeMillis())));
  40. }
  41.  
  42. /**
  43. * Overridden method.
  44. *
  45. * Adds support for filling MODIFIED-attributes.
  46. * @param e
  47. * @param operation
  48. */
  49. protected void prepareForDML(int operation, TransactionEvent e)
  50. {
  51.   final String method = "prepareForDML(int operation, TransactionEvent e)";
  52.   _log.debug(method);</samp>
  53.  
  54.   super.prepareForDML(operation, e);
  55.  
  56.   // only if current operation == UPDATE, do update related history columns.
  57.   if (operation == DML_UPDATE)
  58.   {
  59.     setAttribute(MODIFIED_BY, getCurrentUser());
  60.     setAttribute(MODIFIED_DATE, new oracle.jbo.domain.Date(new Timestamp(System.currentTimeMillis())));
  61.   }
  62. }
  63.  
  64. /**
  65. * Get current user from application module.
  66. * Uses getUserPrincipalName to derive current user. If getUserPrincipalName
  67. * returns null, the default username is used.
  68. * @return Name of current user
  69. */
  70. protected String getCurrentUser()
  71. {
  72.   _log.debug("getCurrentUser");
  73.   String username = ((ApplicationModuleImpl)getDBTransaction().getRootApplicationModule()).getUserPrincipalName();
  74.   if (username == null)
  75.   {
  76.     username = "unknown";
  77.   }
  78.   return username;
  79. }
  80.  
  81. }

Now for every table with audit columns just use this Entity Object as base class
and your audit information is stored.

One condition which much be met is that you have to use some kind of JAAS login functionality to have the username filled in the Application Module context.

Tags:

Digg this!Add to del.icio.us!Stumble this!Add to Techorati!Share on Facebook!Seed Newsvine!Reddit!Add to Yahoo!

Comments are closed.

Copyright © 2009 Pascal’s Blog, All rights reserved.| Powered by WordPress