[Coldbox 3.7] ORMPreUpdate Event via custom Interceptor

Hi,

I’m looking for any thoughts on how to properly use an interceptor to use ORMPreUpdate announced event. I have a modified column on every table. Whenever an update happens I would like to update this timestamp. We have created an interceptor called ORMEvents.cfc and added this to the interceptor.

`

/**

  • Custom ORM Events Interceptor
    */
    component extends=“coldbox.system.interceptor” {

void function configure(){

}

void function ORMPreUpdate(event,struct interceptData, buffer){
interceptData.entity.setModified(dateConvert(‘local2UTC’, now()));
}

}

`

  1. It seems that this event is also getting fired before my update actually happens. It’s getting fired during my getByID() action which is just fetching the record. Is this the right event for what what I want to do?

FROM JOHN WHISH’s ORM book

`

preUpdate() – This event occurs before the corresponding database record is
updated in the database.

`

and from ColdBox Docs:

ORMPreUpdate {entity,oldData} Called via the preUpdate() event
  1. The code above throws the following error:

`

Application Execution ExceptionError Type: Application : [N/A]

**Error Messages:**coldfusion.runtime.CustomException: Invalid method call: setModified
Root cause :org.hibernate.HibernateException: coldfusion.runtime.CustomException: Invalid method call: setModified

`

I’ve event done things like:

`
if (structKeyExists(interceptData.entity,“setModified”)) interceptData.entity.setModified(dateConvert(‘local2UTC’, now()));

`

Any thoughts on where I’m going wrong would be much appreciated. I see the power of interceptors, but I couldn’t find a concrete example (http://wiki.coldbox.org/wiki/Extras:ORMEventHandler.cfm) of how to properly use these custom announced events that are announced from my:

ORMEventHandler.cfc

`

component extends=“coldbox.system.orm.hibernate.EventHandler” { }

`

Thanks!
Tim

Interesting. We do exactly the same thing (UpdatedDate instead of “modified”, but same principle), and it works as expected…our interceptor is even named the same :).

The only difference I see is that we check the meta of the entity before calling the setter to make sure that this won’t bomb, since this method will fire for every update to every entity (and not all our tables have that column).

I would try adding the generic preUpdate() CF event handler in a single entity and see if you can get that to work.

Hmm…we have tried that, but it’s not firing. We tried adding the method directly to the entity CFC and to the ORMEventHandler.cfc, but neither were able to find the method…

As you mentioned and some interesting comments on this post suggest I guess I’ll have to inspect the metaData as the structKeyExists() approach appears to produce spotty results when detecting the methods on a particular entity (http://www.cfgears.com/index.cfm/2011/1/21/How-to-see-if-a-function-exists-in-a-CFC). Since the intercept data is receiving an instance of an object the

structKeyExists(interceptData.entity,'setModified')
should work though.

Here are my ORM settings.

`

this.ormsettings={
datasource=this.datasource
,logsql=“true”
,cfclocation=“model”
,dialect=“MicrosoftSQLServer”
,dbcreate=“none”
,eventHandling=“true”
// Set the event handler to use, which will be inside our application.
,eventhandler = “model.ORMEventHandler”
};

`

Are there any other settings needed to turn on the ORM event handling?

As I mentioned before when putting in a dump etc, it appears that this preUpdate event is getting invoked during the fetch of the entity based on when the error is getting thrown. It is getting thrown on a getByID() function call on my concrete service object. Is this event getting fired because the fetch request is over and the ORM is closing that orm session?

My full understanding of ORM session handling is lacking, but didn’t know if that was what might be causing this event to be fired following an entity fetch vs the entity save logic.

Any further thoughts would be appreciated…

Thanks,
Tim

I’m running up against my understanding of ORM as well, but have you tried adding flushAtRequestEnd = false to ormsettings in Application.cfc? I seem to remember having issues with this as this setting set to true will flush everything at request end. So perhaps there are a other entities that are open and getting flushed besides the one you’re trying to update explicitly, and maybe they don’t have the property you’re trying to update?

The error is occurring as Joel has indicated.

What is happening is that you are in a global event handler, and not every entity will have that method. Here is a trick that will help you out.

void function ORMPreUpdate(event,struct interceptData, buffer){
interceptData.entity.setModified(dateConvert(‘local2UTC’, now()));
}

Becomes

void function ORMPreUpdate(event,struct interceptData, buffer){
try {
interceptData.entity.setModified(dateConvert(‘local2UTC’, now()));
interceptData.entity.setModified(dateConvert(‘local2UTC’, now()));
} catch (type any) {
writeDump(interceptData.entity); abort;

}

}

What you will find is that you need to either do a check for that Entity at the global level, or apply the event at the entity level only. If you are expecting something like this to work on the global level than you are mistaken.