Hooking into GORM events | Hooking into GORM custom event listener from plugin in Grails | Grails Custom Gorm Event Listener
At first configure your datasource.groovy to connect with your desired database as below:
dataSource { pooled = true jmxExport = true driverClassName = "org.h2.Driver" username = "sa" password = "" } hibernate { cache.use_second_level_cache = true cache.use_query_cache = true cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider' format_sql = false use_sql_comments = false } // environment specific settings environments { development { dataSource { pooled = true url = "jdbc:mysql://localhost/my_db?useUnicode=yes&characterEncoding=UTF-8" driverClassName = "com.mysql.jdbc.Driver" username = "root" password = "" dialect = "org.hibernate.dialect.MySQL5InnoDBDialect" dbCreate = "update" properties { jmxEnabled = true initialSize = 5 maxActive = 50 minIdle = 5 maxIdle = 25 maxWait = 10000 maxAge = 10 * 60000 timeBetweenEvictionRunsMillis = 5000 minEvictableIdleTimeMillis = 60000 validationQuery = "SELECT 1" validationQueryTimeout = 3 validationInterval = 15000 testOnBorrow = true testWhileIdle = true testOnReturn = false jdbcInterceptors = "ConnectionState" defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED } logSql = true loggingSql = true } } test { dataSource { } } production { dataSource { } } }
Now add "runtime 'mysql:mysql-connector-java:5.1.29'" to your BiuldConfig.groovy file under "dependencies" section if you used MySQL.
Now create controller like below:
package com.custom_gorm_event_listener class HomeController { def index() { println("Tracking-post-load-function") println(Home.list()) println("") println("") println("Tracking-post-update-function") Home.last().departmentName = "Department-${System.currentTimeMillis()}".toString() render "" } }
And as well as a Domain class as below:
package com.custom_gorm_event_listener class Home { Long id String name String roll String departmentName static constraints = { departmentName nullable: true } }
This is the most important step, need to create and gorm event listener class as below:
package com.custom_gorm_event_listener import grails.util.Holders import org.codehaus.groovy.grails.orm.hibernate.EventTriggeringInterceptor import org.codehaus.groovy.grails.orm.hibernate.HibernateDatastore import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent import org.grails.datastore.mapping.engine.event.ValidationEvent import org.hibernate.HibernateException import org.hibernate.event.spi.AbstractPreDatabaseOperationEvent import org.hibernate.event.spi.PostDeleteEvent import org.hibernate.event.spi.PostInsertEvent import org.hibernate.event.spi.PostLoadEvent import org.hibernate.event.spi.PostUpdateEvent import org.hibernate.event.spi.PreDeleteEvent import org.hibernate.event.spi.PreInsertEvent import org.hibernate.event.spi.PreLoadEvent import org.hibernate.event.spi.PreUpdateEvent import org.hibernate.event.spi.SaveOrUpdateEvent /** * Created by pritom on 18/10/2017. */ class GormEventListener extends EventTriggeringInterceptor { GormEventListener() { this((HibernateDatastore) Holders.applicationContext.getBean(Datastore), new ConfigObject()) } GormEventListener(HibernateDatastore datastore, ConfigObject co) { super(datastore, co) } protected void onPersistenceEvent(AbstractPersistenceEvent event) { super.onPersistenceEvent(event) } private void updateState(AbstractPreDatabaseOperationEvent event) { Object[] newState = event.persister.getPropertyValuesToInsert(event.entity, null, event.session) Object[] oldState = event.state newState.eachWithIndex { m, i -> oldState[i] = m } } boolean onPreInsert(PreInsertEvent event) { updateState(event) return false } void onPostInsert(PostInsertEvent event) { println("onPostInsert::${event.entity}") } boolean onPreUpdate(PreUpdateEvent event) { updateState(event) return false } void onPostUpdate(PostUpdateEvent event) { println("onPostUpdate::${event.entity}") } boolean onPreDelete(PreDeleteEvent event) { return false } void onPostDelete(PostDeleteEvent event) { println("onPostDelete::${event.entity}") } void onPreLoad(PreLoadEvent event) { } void onPostLoad(PostLoadEvent event) { println("onPostLoad::${event.entity}") } void onSaveOrUpdate(SaveOrUpdateEvent event) throws HibernateException { println("onSaveOrUpdate::${event.entity}") } void onValidate(ValidationEvent event) { } }
And finally need to hook our custom gorm event listener to gorm event, to do so we have to add some functionalities to BootStrap.groovy as below:
import com.custom_gorm_event_listener.GormEventListener import org.codehaus.groovy.grails.commons.GrailsApplication import org.springframework.context.event.AbstractApplicationEventMulticaster import org.springframework.context.support.AbstractApplicationContext class BootStrap { GrailsApplication grailsApplication def init = { servletContext -> addGormListener() } def destroy = { } void addGormListener() { AbstractApplicationContext context = grailsApplication.mainContext AbstractApplicationEventMulticaster multicaster = context.applicationEventMulticaster List listeners = multicaster.applicationListeners multicaster.removeAllListeners() /* Placing our listener at first */ multicaster.addApplicationListener(new GormEventListener()) listeners.each { multicaster.addApplicationListener(it) } } }
We are finished, if we run our project we can track when an instance create, update or read through our listener:
Tracking-post-load-function Hibernate: select this_.id as id1_0_0_, this_.version as version2_0_0_, this_.department_name as departme3_0_0_, this_.name as name4_0_0_, this_.roll as roll5_0_0_ from home this_ onPostLoad::com.custom_gorm_event_listener.Home : 53 onPostLoad::com.custom_gorm_event_listener.Home : 54 onPostLoad::com.custom_gorm_event_listener.Home : 55 [com.custom_gorm_event_listener.Home : 53, com.custom_gorm_event_listener.Home : 54, com.custom_gorm_event_listener.Home : 55] Tracking-post-update-function Hibernate: select this_.id as id1_0_0_, this_.version as version2_0_0_, this_.department_name as departme3_0_0_, this_.name as name4_0_0_, this_.roll as roll5_0_0_ from home this_ order by this_.id desc limit ? Hibernate: update home set version=?, department_name=?, name=?, roll=? where id=? and version=? onPostUpdate::com.custom_gorm_event_listener.Home : 55