I'm trying to add a custom GORM event listener class in Bootstrap.groovy
, as described in the Grails documentation but its not working for me. Here is the code straight from the docs:
def init = {
application.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore ->
applicationContext.addApplicationListener new MyPersistenceListener(datastore)
}
}
When I run it, the compiler complains that application and applicationContext are null. I've tried adding them as class level members but they don't get magically wired up service-style. The closest I've got so far is:
def grailsApplication
def init = { servletContext ->
def applicationContext = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
grailsApplication.mainContext.eventTriggeringInterceptor.datastores.each { k, datastore ->
applicationContext.addApplicationListener new GormEventListener(datastore)
}
}
But I still get errors: java.lang.NullPointerException: Cannot get property 'datastores' on null object
.
Thanks for reading...
EDIT: version 2.2.1
If you do:
ctx.getBeansOfType(Datastore).values().each { Datastore d ->
ctx.addApplicationListener new MyPersistenceListener(d)
}
This should work without needing the Hibernate plugin installed
That looks like it should work, although I'd do it a bit differently. BootStrap.groovy does support dependency injection, so you can inject the grailsApplication
bean, but you can also inject eventTriggeringInterceptor
directly:
class BootStrap {
def grailsApplication
def eventTriggeringInterceptor
def init = { servletContext ->
def ctx = grailsApplication.mainContext
eventTriggeringInterceptor.datastores.values().each { datastore ->
ctx.addApplicationListener new MyPersistenceListener(datastore)
}
}
}
Here I still inject grailsApplication
but only because I need access to the ApplicationContext
to register listeners. Here's my listener (simpler than what the docs claim the simplest implementation would be btw ;)
import org.grails.datastore.mapping.core.Datastore
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
class MyPersistenceListener extends AbstractPersistenceEventListener {
MyPersistenceListener(Datastore datastore) {
super(datastore)
}
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
println "Event $event.eventType $event.entityObject"
}
boolean supportsEventType(Class eventType) { true }
}
Finally stumbled onto a working Bootstrap.groovy
, thanks to this post but I don't think its the best way to do it, rather its a work around.
def init = { servletContext ->
def applicationContext = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
applicationContext.addApplicationListener new GormEventListener(applicationContext.mongoDatastore)
}
So basically I'm hard-coding the MongoDB datastore directly as opposed to iterating over the available ones, as the docs suggest.
To save you reading the comments to the first answer, the adapted version I provided in the Question (as well as Burt's answer) only works if the Hibernate plugin is installed but in my case I was using the MongoDB plugin so had no need for the Hibernate plugin (it in fact broke my app in other ways).