I have been doing a ton of work lately with the ORM features in ColdFusion 9. Last night I was reading through my grails book and I came across a feature that I really like. In grails you can automatically have the date created (on insert) and last updated (on update) time stamp added to each table during their respected events. This way you always know when records were created and updated. We can replicate this feature on the entity itself or on all entities in our system and today I will show you how to do both.

First off you need to setup some settings in our application. You need to first setup your normal ORM settings like orm enabled and the data source. In the ORM settings we are going to be working with event handling and event handler. Event handling is false by default and therefor will not broadcast these events that we want to listen for. Also the db create setting must be set to update unless we already have these fields added to our table. Next we are going to create a very basic persistent entity in our model folder called User. As you can see this is no different from most of the entity's you have been building. The only difference is we are going to add 2 fields to our domain model. The date created and last updated should both be set to time stamps.

Now that we have event handling turned on and our entity ready we can work on adding the functionality I talked about at th e beginning of this article. As I said before we can listen for events on a per entity basis or application wide. First let us take a look at how we would do it on our user entity. Below is a list from the docs of the different methods we can listen for in our entity.

  • preLoad(): This method is called before the load operation or before the data is loaded from the database.
  • postLoad(): This method is called after the load operation is complete.
  • preInsert(): This method is called just before the object is inserted.
  • postInsert(): This method is called after the insert operation is complete.
  • preUpdate(Struct oldData): This method is called just before the object is updated. A struct of old data is passed to this method to know the original state of the entity being updated.
  • postUpdate(): This method is called afterthe update operation is complete.
  • preDelete(): This method is called before the object is deleted.
  • postDelete(): This method is called after the delete operation is complete.
Taking a look at that list I can tell that to accomplish my goal I am going to work with the preInsert() & preUpdate() methods. This just means before I save / update what do you want do. In my case I want to set those fields to now(). In the case of the insert I will set the date created to now as well as the last updated field. In the update event we will just set the last updated field.

This to me is awesome because its one less thing I have to manually worry about. I know that every time a record is inserted or updated we will have time stamps on them. This is great for the example I gave above but you will quickly find yourself asking the following. I have x number of objects in my system and I would really rather not have to do this to each of my entities. Your in luck because you don't have to and I am going to show you how!

You can define an application wide event handler for your app. First we are going to use all of the settings we did before but we are going to add one to the mix, eventhandler. Event handler is the path to your application wide event handler component (without the .cfc on the end, it knows that already). Next we need to create our event handler component. The only requirements of this component is that it implements the CFIDE.orm.IEventHandler interface. When you implement an interface you must define each and every method in the interface. I find it much easier if you use the component wizard in builder and allow it to create all of the methods for you.

Now that we have our event handler in place and ready to go we need to write the code for our methods. When an application wide event is broadcasted the entity is passed along as an argument so we know which entity we are working with. That is all we need to add this functionality to every event.

As you can see this is a a pretty awesome use case for event handling but why stop there. You could record information about the user who made the changes to the database, copy versions to a version history table and even use the updates as some sort of restore point for your application. I am loving the cool things I can add to my app with very little coding and I hope you are starting to see the value in them as well.