Migrating from ColdFusion to Railo Part 6: More ORM issues
Continuing my series of notes on the nitty gritty of migrating from ColdFusion 9 to Railo 4.2.
← Migrating from ColdFusion to Railo Part 5: Scope names and local variables
Multiple ORM datasources
Issue
In CF9.0.1 you can define more than one datasource for your ORM entities and they needn't be on the same database server. I have a particular app that runs on MariaDB for the most part, but authenticates admin users against a SQL Server.
This won't work on Railo. You can only have one ORM datasource.
Fix
There's no universally applicable workaround as far as I'm aware, but in my case the solution was straightfoward: I just made the SQL Server admin entity non-persistent, and loaded it manually the old fashioned way using a query.
Update: Lucee supports multiple ORM datasources.
Flushing transactions
Issue
When I first started using ORM it took me a while to grasp that, by default, changes to entity data aren't immedately saved to the database. Instead they're managed by the "ORM session" which queues up changes and executes them at the end of the request.
The general consensus seemed to be that giving up control of when data was persisted in this way was a bad thing. Instead, best practice was to prevent the automatic ORM flushing to the DB from taking place using ormSettings.flushAtRequestEnd=false
and then using CFML transactions around saves/deletes to force them to be persisted immediately.
transaction{
EntitySave( myEntity );
}
This all seemed to work fine in Railo until I updated to the latest 4.2.2.003 patch. Changes at first appeared to be saved - they showed up fine in the UI. But then I discovered the data was not actually being persisted to the database.
Clearly the ORM session was not being flushed despite the use of transactions as normal.
Fix
Transactions aren't the only way to force ORM to persist changes immediately: OrmFlush()
serves that purpose too. Adding an explicit OrmFlush()
at the end of my transactions did the trick.
Fortunately, I generally abstract my ORM CRUD operations into a base service so as workarounds go this was fairly painless.
Bug tracker
However, ORM operations within transactions should be flushed anyway without the need for an explicit command so this would appear to be a regression. Hansjoerg has logged it as Issue 3279.
9 February 2015 In Lucee (formerly Railo) this issue appears to be present still, but is not quite as bad. If you call EntitySave( myEntity )
within the transaction, then the data is saved, but if you simply set a property within the transaction without explicitly calling EntitySave()
or OrmFlush()
the change is not persisted (as it should). See Lucee Issue #78.
4 July 2015 This issue is fixed in Lucee 4.5.1.022
Datasource timeouts
Issue
Another problem which may or may not be related, but which also appeared after applying the latest patch, concerns datasource connection timeouts. I started getting exceptions thrown when ORM tried to load an entity after the datasource in question had been idle for while. The first included the following message:
could not execute query [The last packet successfully received from the server was 71,904,864 milliseconds ago. The last packet sent successfully to the server was 71,904,864 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.]
When I tried re-running the operation, the message was simply:
could not execute query [No operations allowed after connection closed.]
Fix
Issuing an OrmReload()
brought things back to normality, but for a more permanent, preventative solution I followed one of the suggestions in the first error message and set the (MariaDB/MySQL) datasource's "Validate" setting to true in the Railo admin. Having since dealt with the issue again in another ORM app, this does seem to be an effective fix.
I can't be sure that this is connected with the patch release, but given the timing and that ORM sessions are again involved it seems likely.
If anyone on 4.2.2.xxx can confirm sightings of this as a new issue I'd be happy to raise a ticket.
19 December 2014 The validate setting has failed to solve the problem completely, and we subsequently experienced some serious datasource connection issues following a change to an ORM database table. For now we've rolled back the patch.
9 February 2015 Again, there is still an issue in Lucee, but I've yet to see the exact same results. The problem I have identified is that calling OrmReload()
in Lucee seems to cause existing ORM datasource connections to become "detached": they fail to time out until forcibly closed by the database server (which may be hours later). See Lucee issue #119.