Pregunta

Estoy escribiendo un plugin de Grails y tengo que enganchar en el dominio método save () para hacer un poco de lógica tras el salvamento. Necesito hacer esto a través de múltiples clases de dominio. Estoy tratando de evitar eventos de hibernación en los casos en los que un usuario plugin no está usando Hibernate con GORM.

He intentado muchas cosas pero por debajo es lo que creo que debería haber tenido la mejor oportunidad de trabajo. En todos los casos grailsSave es nula . ¿Cómo puedo hacer esto?

def doWithDynamicMethods = { ctx ->
    application.domainClasses.each { dc ->
        def grailsSave = dc.metaClass.pickMethod('save', [Map] as Class[])

        domainClass.metaClass.save = { Map params ->
        grailsSave.invoke(delegate, [params] as Object[])
        println "Saved object, now do my thing"
        //...
        }
    }
}

Tengo el siguiente puesto en mi * Clase Plugin.groovy:

def dependsOn = [domainClass: '1.1 > *', hibernate: '1.1 > *']
def loadAfter = ['hibernate']
¿Fue útil?

Solución

he podido conseguir con éxito una referencia a los métodos Save () durante la inicialización Plugin / app; No sé por qué. En su lugar, he decidido crear un oyente para los eventos de hibernación después de la inserción, actualización y eliminaciones. Este posterior por Sean Hartsock en relación con el registro de auditoría plug-in era una cartilla perfecto para hacerlo.

Esta es la esencia del Oyente:

class MyListener implements PostInsertEventListener, PostUpdateEventListener, PostDeleteEventListener, Initializable {

        public void onPostInsert(final PostInsertEvent event) {
            // logic after insert
            return
        }

        public void onPostUpdate(final PostUpdateEvent event) {
            // logic after update
            return
        }

        public void onPostDelete(final PostDeleteEvent event) {
            // logic after delete
            return
        }


        public void initialize(final Configuration config) {
            return
        }   
    }

A continuación, en el GrailsPlugin.groovy *:

def doWithApplicationContext = { applicationContext ->

    // add the event listeners for reindexing on change
    def listeners = applicationContext.sessionFactory.eventListeners
    def listener = new MyListener()

    ['postInsert', 'postUpdate', 'postDelete'].each({
       addEventTypeListener(listeners, listener, it)
    })

}


// copied from http://hartsock.blogspot.com/2008/04/inside-hibernate-events-and-audit.html
private addEventTypeListener(listeners, listener, type) {
    def typeProperty = "${type}EventListeners"
    def typeListeners = listeners."${typeProperty}"

    def expandedTypeListeners = new Object[typeListeners.length + 1]
    System.arraycopy(typeListeners, 0, expandedTypeListeners, 0, typeListeners.length)
    expandedTypeListeners[-1] = listener

    listeners."${typeProperty}" = expandedTypeListeners
}

bastante simple al final del día ...

Otros consejos

Hay tres versiones diferentes de ahorro añadido a la metaclase,

save(Map)
save(Boolean)
save()

¿Cuál usted está llamando en su prueba? Tendrá que añadir que el código para cada uno.

Otra cosa a comprobar es si su plugin se ejecuta después de que el plug-in de hibernación que se suma a los tres métodos para la MetaClass

aplausos

Lee

Tenga una mirada en el plug-in Falcone Util . Este plugin le permite conectar en eventos de Hibernate (ver la documentación en la parte inferior de la página). No sé si esto es exactamente lo que quiere, pero es posible obtener algunas pistas.

Sal! No creo que el plugin funciona con Grails 1.2 todavía.

Este es un problema de optimización prematura:. Versiones anteriores de Groovy penaliza seriamente MetaClass mangling, y así GORM no añade toda su magia hasta que se detecta la necesidad de

La solución más fácil es tener su complemento dependOn GORM Labs (Yo trabajo alrededor de ella allí). La solución alternativa es poner en funcionamiento methodMissing manualmente (que sería duplicar el trabajo que hice). Consulte la documentación GORM laboratorios para obtener más información sobre cómo he logrado eso.

¿No esta mejor se añadirá a la clase de servicio que posee la unidad de trabajo? Ahí es donde la primavera de costumbre / Grails lenguaje tendría tal lógica. No es necesario que modifique el salve a todos.

métodos GORM adicional se inicializan perezoso en primera llamada a cualquiera de ellos. Para inicializar en doWithDynamicMethods simplemente llamar a uno de los métodos estáticos de la clase dominio (s):

def doWithDynamicMethods = { ctx ->

    application.domainClasses.each { dc -> 

        // call any static method to initialize dynamic gorm methods
        dc.clazz.count()

        def grailsSave = dc.metaClass.pickMethod('save', [Map] as Class[])
        //...
    }
}

Su método Save () estará disponible ahora. Como esto se llama en el arranque de un solo cargo no debe ser un gran problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top