Grails 2.2.5 - domain object not being saved, but no errors - grails

I have run into a baffling situation in a Grails 2 2.5 application where my domain object is not being persisted to the MySQL database and yet no errors are being returned. I've worked with Grails for a number of years so I think I've avoided the more obvious pitfalls, and I've never seen this one before. Here's the code:
if (sale.save(flush:true,failOnError: true)) {
println "nettTotal = "+sale.nettTotal
map.response = "OK"
map.sale = sale
} else {
map.error = "Unable to save sale"
sale.errors.allErrors.each {
println it
}
}
When I run this, I see the message 'nettTotal = 290.36', showing that the domain object has in fact been saved as far as Grails is concerned (and I don't see any errors which I would do if it had failed). Yet when I do a select in the MySQL database, I see that the row in question remains unchanged ('nett_total' remains NULL, other columns are also unchanged).
The code runs in a controller, without any explicit transaction which might have failed to commit. I'm not sure where else to look. It has to be something simple, but I'm stuck.
(I'm not sure this is relevant, but this application has been proving curiously problematic with spurious errors over the last couple of weeks suggesting some kind of sporadic corruption. For example, previously working findBy* dynamic methods have suddenly started throwing errors, which have been cleared up by a 'deep clean' of the application, i.e., grails clean and the deletion of the project directory in .grails/2.2.5/projects. Yesterday I had a wholly mystifying JSON error from unchanged code which had previously worked, which was once again cleared up by a deep clean. I'm not sure why this is happening, but it worries me and I'd like to prevent it).

The problem turned out to be with a def beforeUpdate() in the Sale object. There's nothing I can see that's wrong with it, but once I'd commented it out, the update to the database was OK again.

Related

Getting Stale object error. Optimistic Locking: How does it work?

I think I've eliminated everything, but I'm not sure I understand OL perfectly enough to be sure. In general, let's say you and I are on a team to keep a foo up to date. I'm in one room and decide to save time I'll update the foo myself. So I start updating it. A minute later you have the same idea and log onto the edit page to update it as well. What happens if I finish first? What happens if you finish first? In a configuration where it fails how does it distinguish between someone editing and someone reading. If I catch and reload to update the lock I lose all my changes, how is this solved? Here, it's simple to redo the update, but potentially it's part of a more complicated form object.
My specific problem came when (best I can make out) loaded one copy in my browser, later forgot about it and then one in my console (also lock: 0?) couldn't update the one in my console with stale object error. Noticed the browser thing. Closed my console. Tried to reload my browser and got stale object error as well. Here's the code that's failing:
=> 7: self.update_attributes({
8: failed_view_attempts: self.failed_view_attempts += 1,
9: failed_view_at: Time.now
10: })
11: end
(byebug) self
#<Product id: 12... lock_version: 0>
#=> ActiveRecord::StaleObjectError (Attempted to update a stale object: Product.)
Things I've tried:
To see if another instance was being loaded I added puts "CALLED !!!!" in an after_initializecallback, but it only printed once.
And checking self.changed after rescuing from the error and get back ["updated_at", "failed_view_attempts", "failed_view_at"]
Need to set lock_version column default to zero (0).
Optimistic locking is based on an object version number.
Reading and object should not affect the version number at all.
If you try to update some object, this version number is compared (in sql actually update statement is used for example "update ... where version = 1 and ..." ) and increased on update.
If the comparison fails when trying to update, you get the stale object error. This means that the object was modified by somebody else while you was doing your changes.
To resolve this error you need to load the object again to get the actual version and maybe merge the changes manually (presenting the user some info about it, and let user decide for example).

ActiveRecord changing position on memory

I have a rather odd situation here.
My OrdersController has an edit method and at some point I have the following statement:
order_item.item = item
As you can guess, order_item.item expects a reference to an Item object, which is exactly what item is. Here comes the mistery. The first time I send a request to orders/{some_order_id}/edit, I receive the expected response. But if I send a new request (even if I just press F5) the application crashes and I receive the following error message:
ActiveRecord::AssociationTypeMismatch in OrdersController#edit
Item(#177601092) expected, got Item(#67520280)
What have I discovered so far? I have put an puts "#{Item.object_id}" just before the order_item.item = item and found out that Item.object_id changes from a request to another, which means that the Item ActiveRecord is changing its position on memory. (For instance, in the above example, during the first request Item.object_id is 67520280, while in the second it changes to 177601092.)
My question is: What can be causing the Item ActiveRecord to change its position on memory?
Useful info: I'm using rails 3.0.20
Update:
I found out that this change of ID is pretty common. But I still can't figure out why the expectation doesn't change as the Item.object_id does.
Despite the fact that I am not using Factory Girl, this answer and this discussion helped me a lot.
tl;dr
The problem was solved when I set cached_classes to true in my environment.

'save' does not work, tried flush and failOnError:true but no error was given

I'm trying to update a DB with flush:true for save() operations. The debugger showed that the status was updated, but when I use this sql
Select * from domain_name where id = 123
I'm still getting the old status.
I am using the Quartz plugin for running a scheduled cron job that reads from the same table:
DomainName.withTransaction{ status ->
try
{
DomainName name = DomainName.get(123)
name.status = "newstatus"
name.save(flush:true,failOnError:true)
}
catch(Exception rte)
{
log.error "Update failed with error ${rte.message}"
status.setRollbackOnly()
}
}
Has anyone encountered similar issues? There are no error on turning on hibernate log in config.groovy
debug 'org.hibernate.SQL'
'org.hibernate.transaction'
I experienced this issue. Turns out that the instance to update was being obtained via a dynamic finder. Once I used get(id) to obtain the instance the values were save to the database table.
During troubleshooting I turned on the sql logging. When the row was supposed to be updated no update statement was written to the console when the instance was obtained via the finder. Using get(id) the update statement was written to the console.
I think the problem resides before your given code block.
Did you pull that object with dirty checking (e.g. Domain.get()) before this transaction, which is still alive? My suggestion is to check your code carefully, detach from all dirty check (e.g. use Domain.discard()) and try again. That should solve your problem.
I was facing a similar problem. I was getting the object via a dynamic method. Then passing a property to another method. In the other method I was again getting the object by a dynamic finder.
I saved the domain object but it was not getting saved. I tried failOnError as well as flush but did not work.
I passed the domain object instead of using dynamic finder and it worked.

If I update a column that is part of a composite id in a Grails domain, will model.save() work?

The domain has 4 columns part of a composite id:
id composite: ['exemptionTermCode', 'exemptionCode', 'exemptionClassification', 'exemptionPayType']
In the controller, a ugly parody of a REST service, I have this code:
else if (request.method == "PUT" && params.rowid) {
def a = WaiverExemption.find("from WaiverExemption as e where e.exemptionRowId = ?", [params.rowid])
if (params.exemptionPay) a.exemptionPayType = params.exemptionPay
if (params.exemptionClassification) a.exemptionClassification = params.exemptionClassification
if (params.exemptionCode) a.exemptionCode = params.exemptionCode
if (params.exemptionPriority) a.exemptionPriority = parseLong(params.exemptionPriority)
if (params.exemptionTempFlag) a.exemptionTempFlag = params.exemptionTempFlag
a.exemptionUserId = session.licensePlate
a.save(flush: true, failOnError: true)
I don't get any errors on the console. I can step through, and see the model object in the watch window, and I see the correct property updated. After the save() finishes, I see in the model.errors the following:
grails.validation.ValidationErrors: 0 errors
No exceptions. No crashing the debugger. Nada. Subsequent commands are all executed. However, on the Oracle side of things, the record that was updated definitely remains un-updated. It's taken me awhile (didn't know about .errors until yesterday) to get this far, and I can do inserts and deletes with the gorm methods. I can't understand why save() is failing, I'm not getting validation issues like I have in the past. I'm not updating fields in such a way that I'd have a non-unique pk, and I'd expect that to throw an error if I did.
Is there something I'm missing here?
I am using the rowid to search for the record because by the time I've updated this, I've lost part of the pk with which to look it up. Rowid is set to updateable false.
[edit]
I've also tried doing a.refresh() after the save. This fails, it's unable to find a record with that key (which you'd expect, since it didn't actually run the update query.
I'm afraid you will have to remove the old instance and create a new one if you change a field that is part of the composite id. That's how I've solved the problem earlier.

Rails 2.3.X weird problem with Created On

Hey everyone... I've been out of the game for awhile so you're going to have to excuse the fact that it's Rails2.3
Currently the app is running 2.3.3, I just updated it to 2.3.11
An object is edited, and saved using the .save command and the SQL generated in the logs is as follows:
UPDATE `calc_sheets` SET `is_us_connection` = 0, `holding_date_end` = '0001-02-11', `updated_on` = '2011-03-16 13:14:00', `extra_chars` = '' WHERE `id` = 657
however for some reason the created_on field is getting updated, and obviously shouldn't be. Is there some bug that I'm not aware of. I did some searching, looking and reading and nothing jumped out at me.
This is the only SQL call made during the action, so it's not as if something else is being updated or saved.
Any advice?
I realize this is out dated code, the app is fairly old, and the clients aren't ready to updated it... this "bug" however is causing all kinds of havoc.
Thanks in advance for any advice.
My guess is that the created_on table column is set to on "on update CURRENT_TIMESTAMP" (assuming mySQL) or something equivalent.

Resources