Getting a list of an objects changed properties that have not yet been saved

Does Coldbox have an equivalent to (or something resembling) cfWheels changedproperties() method?

http://cfwheels.org/docs/1-1/function/changedproperties

Thanks!

Not that I know of. The most ColdBox does with models is the ORM services and stuff like the bean populator. Other than that, it’s up to you to provide any functionality inside your models.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Are you talkin about orm? If so you can with the orm event handlers

If you wanted to be able to call this at arbitrary times apart from ORM event handlers, you could pretty easily roll your own version of what cfWheels does. Basically, they grab a snapshot of the entity’s properties on load, and then use that for making a comparison of the properties when calling changedproperties(), haschanged(), changedfrom(), etc.

ColdBox does, but it is done differently. These are all done for you by Hibernate in the pre and post events in ORM.

Just thinking out loud, but I wonder if there would be a way to build something like that into the ColdBox ORM Services as a feature you could turn on like entityDirtyPropertyTracking = true?

The trick is, your entities would probably need to extend a base class, or we would need to decorate the entities when they were created with this functionality.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Andrew, what events would you listen do? From what I can see, all the ORM events are at the object level. I don’t see anything on onProperySet or onPropertyChange. Or perhaps I’m thinking of this entirely differently.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

@Brad, I think it might be referring to preUpdate(), which includes a struct of “oldData”, the state of the persistent properties when the entity was loaded. We use this quite a bit for auditing changes to entities as they are updated.

Brad, I was talking about the preSave / preUpdate etc… I was thinking about how the before and after data is present there.

However as cfwheels uses or seems to someone correct me if I am wrong, doesn’t actually use hibernate for there ORM which means that the information or meta data of the beans are cached for every object or they re hit the database to do the comparison.

I haven’t used cfwheels since ColdBox became public, so I am going from memory here.

But Hibernate has isDirty options anyway, just never used them as the only time I have ever had the need to test this was with the ORM events for pre / post events.

I see. I think the issue with preSave/preUpdate is that those only fire when actually saving/updating. My understanding of CFWheels, is you can take any random model and say, “Hey what properties of yours are dirty?” without having to actually save it. Also after a bit of quick Googling, Hibernate has the “is session dirty” flag but from what I can tell, the Hibernate API doesn’t expose any property-level information about dirtiness.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Can you give us an example why you want or need this? ORM doesn’t work well with things like this and usually you just do a session is dirty if you don’t wish to persist when managing the state yourself, otherwise it is automatically persisted for you at the end of the request.

I ask for an example, because the longer I think about this the more I see no valid reason to have a requirement for this with ORM except with auditing of data when you may need to do what ever your business rules dictate you need to do.

Which is what Hibernate already does for us, in that example Brad you would check for the ORmSession.isDirty() to decide if you need to manage the session yourself. Otherwise why would you want or need to with ORM?

Oh and the API doesn’t need to because it is a cache or persistent data, hibernate managers all this for us and will allow us to do ORMSession.isDirty() or something like that if we are managing the flush at request end for us. If we are taking control of the flushing, then we need to check if the session isDirty and then do a flush if needed.

I still maintain that anyone who needs to check for properyt changes in a stateless environment needs to rethink their business logic, but hey that’s me.

Fair enough. I didn’t have any use case for that scenario-- I was just running with the idea of how we would implement it. I see what you are saying though that in theory you shouldn’t need to know what is dirty if you are letting Hibernate manage your persistence. Perhaps the original poster can clarify their need. Of course, the original poster may not even be using Hibernate so in that case they would need to manually track stuff.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Hi All, thanks for all the different angles. Lots of places for me to start playing with.

In relation to why I need this… It is a client requirement that any changes to a model (in this case, a Users Profile) be logged. Whenever a user makes a change to a profile, the administrators want to see what field was changed, and what it’s value was before and after the change (plus the ability to undo the change). We’ve implemented something similar to this in an App build with cfwheels, and the changedProperties() method was invaluable in setting this up… but this App is in Coldbox, so looking around on how best to do it in Coldbox. I’m actually interested in setting up a service that I can pass any model into just before it’s saved, and the service logs the Model, Property and before&after change values and timestamp…this could then allow a kind of change history to be setup on almost anything

It looks like I may have to roll my own, so will have a play around and post here what i come up with.

Thanks for all the pointers… any more you can add are much appreciated.

Jason

I would then say to them to move over to using ORM then, where you can then use ORM Events to audit the changes as it is called. It is the best place to do it, one location and one place to go wrong.

You might want to look at creating a custom interception point or looking into AOP to help tie your logging in everywhere you need it without duplicating too much code. You could even create an AOP aspect that you bound to any method whose name starts with “set” for instance.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

@Jason

As Andrew mentioned, if you use ORM, the ORM Events will get you exactly what you need. And as Brad mentioned, an interceptor will make this trivial to implement.

For example, at my work we have a large app where we need to track not only changes to a number of models, but even “reads” of particular ones (not to mention creates, deletes, etc). To do this all in one place, we created a custom interceptor. In this interceptor, we implemented methods for the various re-broadcasted ORM events that ColdBox provides (see here: http://wiki.coldbox.org/wiki/Interceptors.cfm#ORM_Events).

So in ORMPreUpdate() for example, we implemented some logic to compare the “oldDate” to the current properties of the entity, and log the differences. We even went so far as to create custom meta data for trackable entities that allow us to define which properties to track, what labels to use for the audit records in the db (e.g., “Some Property was changed from X to Y”). Obviously you don’t need this in order to do the auditing that you’re after, but it shows that the sky’s the limit for the type of functionality you can put into this.

The awesome thing about the interceptor approach, of course, is that besides the interceptor itself, you don’t have to do anything else. No need to pass the entity to another service before saving it. By leveraging the regular CF ORM events that ColdBox rebroadcasts as interception points, you can simply configure the interceptor, implement the appropriate interceptor methods, and sit back and watch the logs build.

After playing around with this, I am only left wondering where I can get my ‘I [heart] coldbox’ t-shirt. The OrmPreUpdate interceptor it is. Still got a bit of work, but have moved down this path, and coming together beautifully. Thanks for all for the great pointers and advice!