Index: trunk/grails-app/conf/BootStrap.groovy
===================================================================
--- trunk/grails-app/conf/BootStrap.groovy	(revision 813)
+++ trunk/grails-app/conf/BootStrap.groovy	(revision 814)
@@ -1,7 +1,16 @@
 class BootStrap
 {
+
+    def sessionFactory // used by isDirty().
+    def grailsApplication // used by isDirty().
     def createDataService
 
     def init = { servletContext ->
+
+        /** Add isDirty() to domainClasses.
+        * @todo remove after upgrading to Grails-1.3 >.
+        * See: http://grails.1312388.n4.nabble.com/beforeUpdate-Compare-with-previous-set-value-isDirty-not-working-in-Events-td1695661.html
+        */
+        addDirtyCheckMethods()
 
         /** Environment specific settings.
@@ -37,3 +46,76 @@
     }
 
+   private void addDirtyCheckMethods() {
+      for (dc in grailsApplication.domainClasses) {
+         addDirtyCheckMethods dc.clazz.metaClass
+      }
+   }
+
+    private void addDirtyCheckMethods(metaClass) {
+      metaClass.isDirty = { ->
+         def session = sessionFactory.currentSession
+         def entry = findEntityEntry(delegate, session)
+         if (!entry) {
+            return false
+         }
+
+         Object[] values = entry.persister.getPropertyValues(delegate, session.entityMode)
+         def dirtyProperties = entry.persister.findDirty(values, entry.loadedState, delegate, session)
+         return dirtyProperties != null
+      }
+
+      metaClass.isDirty = { String fieldName ->
+         def session = sessionFactory.currentSession
+         def entry = findEntityEntry(delegate, session)
+         if (!entry) {
+            return false
+         }
+
+         Object[] values = entry.persister.getPropertyValues(delegate, session.entityMode)
+         int[] dirtyProperties = entry.persister.findDirty(values, entry.loadedState, delegate, session)
+         int fieldIndex = entry.persister.propertyNames.findIndexOf { fieldName == it }
+         return fieldIndex in dirtyProperties
+      }
+
+      metaClass.getDirtyPropertyNames = { ->
+         def session = sessionFactory.currentSession
+         def entry = findEntityEntry(delegate, session)
+         if (!entry) {
+            return []
+         }
+
+         Object[] values = entry.persister.getPropertyValues(delegate, session.entityMode)
+         int[] dirtyProperties = entry.persister.findDirty(values, entry.loadedState, delegate, session)
+         def names = []
+         for (index in dirtyProperties) {
+            names << entry.persister.propertyNames[index]
+         }
+         names
+      }
+
+      metaClass.getPersistentValue = { String fieldName ->
+         def session = sessionFactory.currentSession
+         def entry = findEntityEntry(delegate, session, false)
+         if (!entry) {
+            return null
+         }
+
+         int fieldIndex = entry.persister.propertyNames.findIndexOf { fieldName == it }
+         return fieldIndex == -1 ? null : entry.loadedState[fieldIndex]
+      }
+   }
+
+   private findEntityEntry(instance, session, boolean forDirtyCheck = true) {
+      def entry = session.persistenceContext.getEntry(instance)
+      if (!entry) {
+         return null
+      }
+
+      if (forDirtyCheck && !entry.requiresDirtyCheck(instance) && entry.loadedState) {
+         return null
+      }
+
+      entry
+   }
+
 } // end class
