Grails - 创建自定义PersistenceEventListener

时间:2015-11-06 16:42:09

标签: grails

我正在使用Grails 2.3.8。我想在一些域中添加两个审计字段(createdBy和lastUpdatedBy)。因此,从audit plugin开始,我创建了一个自定义侦听器。

package com.nimbus.listener

import groovy.util.logging.Log4j
import org.grails.datastore.mapping.core.Datastore
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEvent
import org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
import org.grails.datastore.mapping.engine.event.PreInsertEvent
import org.grails.datastore.mapping.engine.event.PreUpdateEvent
import org.springframework.context.ApplicationEvent

@Log4j
class NimbusStampListener extends AbstractPersistenceEventListener {

    public NimbusStampListener(final Datastore datastore) {
        super(datastore)
    }

    @Override
    protected void onPersistenceEvent(final AbstractPersistenceEvent event) {
        if (event.source != this.datastore) {
            log.trace("Event received for other datastore. Ignoring event")
            return
        }

        if (event instanceof PreInsertEvent) {
            beforeInsert(event.getEntity(), event.getEntityAccess())
        } else if (event instanceof PreUpdateEvent) {
            beforeUpdate(event.getEntity(), event.getEntityAccess())
        }
    }

    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return PreInsertEvent.class.isAssignableFrom(eventType) ||
                PreUpdateEvent.class.isAssignableFrom(eventType)
    }

    .
    .
    .
}

并在插件中注册:

def doWithApplicationContext = { applicationContext ->
    application.mainContext.eventTriggeringInterceptor.datastores.each { key, datastore ->
            com.nimbus.NimbusStampListener listener = new com.nimbus.NimbusStampListener(datastore, application)
            applicationContext.addApplicationListener(listener)
        }
}

侦听器已成功注册,并且还会侦听持久性事件。问题是,当我尝试在entity对象上获取entityAccessevent字段时,它们为空。

但是我可以获取event.entityObject字段,我可以使用它。但有时在创建新的可审计对象时,createdBy和lastUpdatedBy的值不会在插入时设置,而是触发新的更新事件,该事件会修改在项目的其他部分中导致StaleObjectStateException的对象版本。

AbstractPersistenceEvent类有两个构造函数。

protected AbstractPersistenceEvent(final Datastore source, final PersistentEntity entity,
        final EntityAccess entityAccess) {
    super(source);
    this.entity = entity;
    this.entityAccess = entityAccess;
    this.entityObject = entityAccess.getEntity();
}

protected AbstractPersistenceEvent(final Datastore source, final Object entity) {
    super(source);
    entityObject = entity;
    this.entity = null;
    this.entityAccess = null;
}

很明显,我的侦听器接收到从第二个构造函数创建的事件对象。 Grails还有一些内置的监听器,例如AutoTimestampEventListener,它会自动更新域中的时间戳字段(dateCreated & lastUpdated)。此侦听器使用entity和entityAccess对象,这意味着它们在那里不为空。

当我尝试使用applicationContext.applicationEventMulticaster.applicationListeners打印通过applicationContext注册的所有侦听器时,它不包含AutoTimestampEventListener

如果有人可以帮助我如何在我的自定义监听器中提供实体和entityAccess,或者在哪里可以找到AutoTimestampEventListener的注册方式,那将会很棒。我无法在发布的随附的grails源代码中找到它。

1 个答案:

答案 0 :(得分:0)

我找到了一些方法来实现我的要求,并考虑与他人分享。我创建了两个博客,描述了对我有用的选项。在这里发布整篇博客是没有意义的,所以我只想对选项提出一点看法。

  1. 选项1 :挂钩到var chart = new google.visualization.ColumnChart(document.getElementById('columnchart_material'));并覆盖其方法,并实现您的逻辑以更新域字段。
  2. 选项2 :不直接在Persistence Listener中使用Grails事件,而是从中获取本机Hibernate事件,以便更新事件的当前状态。
  3. 博客链接有更详细的解释:

    Using Hibernate Events with PersistenceEventListener

    Hooking into the Instance methods of the GORM API

相关问题