Fix for Railo not persisting data

When ormSettings in Application.cfc has:

flushAtRequestEnd = true,
autoManageSession = true

Then when making any changes in the admin on Railo (update, new post, change layout, etc) it won’t persist the changes, they are lost after submit.

Changing both of these values to false fixes that issue, but is dangerous because of the custom transaction handling.

I decided to simply do the following:

1.) Create an ORMEventHandler.cfc in my model folder that extends the default orm even thandler
2.) Add a postSave() method to the event handler that runs ormFlush()

3.) Set the eventhandler = “model.ORMEventHandler” in my Application.cfc

Now, this almost works, except… the BaseORMService.cfc does this statically:

// Create the service ORM Event Handler composition
ORMEventHandler = new coldbox.system.orm.hibernate.EventHandler();

So, all of our services, like SettingService use a generic EventHandler, not the one we set up in Application.cfc for eventhandler.

The options are… to make each service’s constructor do:
ORMEventHandler = createObject(“model.ORMEventHandler”);

Which will override the generic one from the extended BaseORMService. This works, but you have to do it in the constructor for every model…

I think that what needs to be done is that the BaseORMService.cfc needs to check to see if an eventhandler has been set for ormsettings, and then set that as the ORMEventHandler instead of the generic one.

Does this sound right? Does anyone know how to access the properties from ormsettings in Application.cfc from the BaseORMService?

Well the dangerous ones is when you have auto flush and auto manage session. That's why I have them typically off and then do transactions o demarcate. So I would suggest have them off and not on

+infinity

You do not really want either of those set to true. There are a ton of threads out there as to why, but I would recommend checking Mark Mandel’s, Brian Kotek’s, and Bob Silverberg’s blogs as well as the CF-ORM-Developer’s list (Google Groups) for a plethora of reading on the topic.

Yes, that’s why I turned them off and created the postSave() event and a custom event handler. The real question is, in BaseORMService.cfc how can I get access to the ormsettings.eventhandler from Application.cfc to determine if it have a value or not?

It should be something like…

if (isDefined(“application.ormsettings.eventhandler”) and application.ormsettings.eventhandler is not ‘’) {
ORMEventHandler = createObject(“model.ORMEventHandler”);
} else{
ORMEventHandler = new coldbox.system.orm.hibernate.EventHandler();
}

But application.ormsettings does not exist. Are these settings below stored anywhere else? They don’t seem to be accessible to me…

// FILL OUT: THE DATASOURCE FOR BLOGBOX
this.datasource = “blogbox”;
// FILL OUT: THE LOCATION OF THE BLOG BOX MODULE
this.mappings["/blogbox"] = COLDBOX_APP_ROOT_PATH & “modules/blogbox”;

// ORM SETTINGS
this.ormEnabled = true;
this.ormSettings = {
// FILL OUT: ADD MORE LOCATIONS AS YOU SEE FIT
cfclocation=[“model”,“modules”],
// FILL OUT: THE DIALECT OF YOUR DATABASE OR LET HIBERNATE FIGURE IT OUT
dialect = “MySQLwithInnoDB”,
// FILL OUT: Change to dropcreate if you are running this for the first time, then change it back to update for continuos repo updates, or remove for production
dbcreate = “update”,
sqlscript = “modules/blogbox/install/sql/blogbox_data.sql”,
logSQL = true,
flushAtRequestEnd = true,
autoManageSession = true,
eventHandling = true
};

I should add, I have the setting:

eventHandler = “model.ORMEventHandler”

I just forgot to add it to my example.

Jim i guess I am confused on the issue. I am setting up my Railo environment now to test this. Do you have any guidelines on a tomcat+apache+virtual hosts?

I made a huge mistake in understanding here and didn’t realize that the coldbox.system.orm.hibernate.EventHandler would announce an ORMPostSave() interception and that all I needed was an interceptor listening on ORMPostSave() that ran ormFlush().

So, the solution to the original problem of no actions saving (update a post, change layout, etc) is very simple: Create an interceptor that listens to ORMPostSave() and run ormFlush() inside of that method, that’s it.

This was my mistake.

I thought that the event handler for all services was using a vanilla instance of that EventHandler.cfc from coldbox.system.orm.hibernate, instead of a custom event handler with a postSave() method. So, I thought that I needed to override it using something like:

SettingService function init(){
// init it
super.init(entityName=“bbSetting”);
// settings cache key
setSettingsCacheKey(“bb-settings”);

// load my custom event handler from model.ORMEventHandler to this Service
ORMEventHandler = createObject(“model.ORMEventHandler”);
return this;
}

Then I simply created: model.ORMEventHandler as:

component extends=“coldbox.system.orm.hibernate.EventHandler”{
function postSave() {
ormFlush();
};
}

I didn’t realize that I just needed an interceptor listening for the ORMPostSave event.

My confusion came in trying to find a way to get all of my services to use my custom event handler instead of the default one, but this was not needed, since the default announces an interception point, which is where the ormFlush() should happen. I didn’t need a custom postSave() event in a custom event handler, so my other questions are irrelevant.

Just so you know, the value I was looking for was getEventHandling()

Ok, so adding the postSave() causes my updates, layout changes, etc to work, but I can’t delete any posts.

I noticed that the $delete() method in BaseORMService doesn’t have:

// Event Handling? If enabled, call the postSave() interception
if( eventHandling ){
ORMEventHandler.postSave( arguments.entity );
}

(or any other ORMEventHandler call) like the $save() method has.

If I add this in, I start getting errors like:

Application Execution Exception
Error Type: org.hibernate.StaleStateException : 0
Error Messages: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

I see in entries.cfc:

announceInterception(“bbadmin_postEntryRemove”,{entryID=entryID});

So, there’s a different set of interceptors for bb_admin with different names? There’s no universal pre and post orm events that can flush after all orm events? Do I need to listen for postSave, postDelete, postUpdate, and also bbadmin_postEntryRemove, etc in my interceptor?

Well here is the thing. In acf doing a native hibernate commit flushes too. So flushes should not be done manually.

According to the hibernate docs issuing a tx.commit() flushes automatically. So if Railo is not doing it then the questions is why?