Model object validates (TryValidateModel) but does not update (TryUpdateModel) - asp.net-mvc

The Model object refuses to update on production server but has no issues on development machine. For the purposes of testing, I retrieve the model object and then immediately check its validation and update states, for example:
Timesheet timesheet = _timesheetRepository.GetTimesheet(timesheetId);
Helpers.ErrorHandler check = new Helpers.ErrorHandler();
check.write("can I validate immediately? :- ", TryValidateModel(timesheet).ToString());
check.write("can I save immediately? :- ", TryUpdateModel(timesheet).ToString());
TryValidateModel - returns true
TryUpdateModel - returns false
Any recommendations?

Validation and binding are different. Invalid data can often be bound (this is a feature; it makes re-displaying a page in the case of an error much easier), and "valid" (per your validation rules, if any) data sometimes can't be bound, due to typing conflicts.

Related

In GORM, Object is not modified in database when the object property is modified at Controller

In my Grails App, I have bootstrapped an object of a domain class as:
def user1 = new Users(userID: 1, name: "John Doe")
user1.save()
In my dashboard controller i have retrieved the object and modified its property name as:
Users userObj = Users.get((Long) 1)
println(userObj as JSON); // This gives me: {"class":"com.prabin.domains.Users","id":1,"name":"John Doe"}
userObj.name = "anonymous"
Now i create a new Users object to retrieve the changed object with same ID 1 as
Users otherUserObj = Users.get((Long) 1) // **Line 2** Is this retrieving from database or from GORM session?
print(otherUserObj as JSON)// This gives me: {"class":"com.prabin.domains.Users","id":1,"name":"anonymous"}
But the value of object in database is not changed. And even when i retrieve the Users object of same id 1 in another controller it gives me the initial object rather than the modified as:
Users userObjAtDifferentController = Users.get(1);
print(userObjAtDifferentController) //This gives me: {"class":"com.prabin.domains.Users","id":1,"name":"John Doe"}
My question is, if the value is not changed in the database, why it gives me the modified object at Line 2 though i have retrieved the object using GORM query (which i guess should retrieve from the database)?
I have also tried using save() after the modification but the result is same.
userObj.save() //doesn't show the changes in database.
My guess is that the object is not being saved to the database because some constraint(s) are invalid. You can determine whether this is the case by replacing your calls to save() with save(failOnError: true). If my guess is correct, an exception will be thrown if saving to the database fails.
When you call the save() method on a domain object, it may not persist in the database immediately. In order to persist the changed value to the database, you would need to do the following.
userObj.save(flush: true)
By using flush, you are telling GORM to persist immediately in the database.
In some cases when validation fails, the data will still not persist in the database. The save() method will fail silently. To catch validation errors as well as save to the database immediately, you would want to do the following
userObj.save(flush:true, failOnError:true)
If validation errors exist, then the GROM will throw ValidationException (http://docs.grails.org/latest/api/grails/validation/ValidationException.html)
You need to consider two things:
If you do save(), it only retains in hibernate session, until you flush it the changes does not persist in database. So, better do save(flush:true, failOnError: true) and put in try/catch block and print exception.
And another important things is, your method in controller needs to be with #Transactional annotation, without it your changes does not persist in database, you will encounter Connection is read-only. Queries leading to data modification are not allowed. exception.
Hope this helps, let me know if your issue is fixed. Happy coding . :)

Why don't unflushed domain objects revert to their "saved" state after discard? Can I get the "clean" version?

Confused here about domain objects in intermediate states.
So here's a class:
class Foo {
Double price
String name
Date creationDate = new Date()
static constraints = {
price min: 50D
creationDate nullable: false
}
}
And this test case:
#TestFor(Foo)
class FooSpec extends Specification {
void "test creation and constraints"() {
when: "I create a Foo within constraints"
Foo f= new Foo(price: 60D, name: "FooBar")
then: "It validates and saves"
f.validate()
f.save()
when: "I make that foo invalid"
f.price=49D
then: "It no longer validates"
!f.validate()
when: "I discard the changes since the last save"
f.discard()
then: "it validates again"
f.validate() //TEST FAILS HERE
}
}
So this test fails on the last validate, because f.discard() doesn't seem to revert f to its "saved" state. Notes on the grails docs appear to indcate this is intended (alothough very confusing to me at least) behavior. That all "discard" does is mark it as not to be persisted (which it wouldn't be anyway if it fails the constraints, so in a case like this, I guess it does nothing right? ) I thought refresh might get me the saved state, or even Foo.get([id]) but none of that works. Foo.get gets the corrupted version and f.refresh throws an nullPointer apparently because creationDate is null and it shouldn't be.
So all that is confusing, and seems like there's no way to get back to saved state of the object if it hasn't been flushed. Is that really true? Which sort of raises the question "In what respect is the object "saved?"
That would seem to mean I would want to be making sure the I'm definitely reading from the db not the cache if I want to be sure I'm getting a valid persisted state of the object, \not some possibly corrupted intermediate state.
A related question -- Not sure the scope of the local cache either -- is it restricted to the session? So if I start another session and retrive that id, I'll get a null because it was never saved, not the corrupt version with the invalid price?
Would appreciate someone explaining the underlying design principal here.
Thanks.
Hibernate doesn't have a process for reverting state, although it seems like it could since it keeps a clean copy of the data for dirty checking. Calling the GORM discard() method calls a few layer methods along the way but the real work is done in Hibernate's SessionImpl.evict(Object) method, and that just removes state from the session caches and disassociates the instance from the session, but it does nothing to the persistent properties in the instance. If you want to undo changes you should evict the instance with discard() and reload it, e.g. f = Foo.get(f.id)

Grails 2.3.7 Optimistic Locking version is updated every time a Command Object is submitted

I have the following
def save(ACommand command){
...
}
#Validateable
class ACommand implements Serializable
{
ADomainObject bundleDef
}
but every time save is called the version is incremented. So if I open up two browsers and submit a different value in succession, instead of getting an error the second time as I would expect, the value is updated.
I also tried using two different sessions with no difference
Update
If I use breakpoints and submit before the other one is completed it works fine. However, If I let the first complete then submit the second without a refresh the version is updated to the newer one (which I don't want) and the change goes through.
Update 2
When you perform updates Hibernate will automatically check the version property against the version column in the database and if they differ will throw a StaleObjectException. This will roll back the transaction if one is active.
per Grails this should work seems to me.
AFAIK, you need to check the version and handle failures yourself - it doesn't happen automatically. You can do this with code like this:
/**
* Returns a boolean indicating whether the object is stale
*/
protected boolean isStale(persistedObj, versionParam = params.version) {
if (versionParam) {
def version = versionParam.toLong()
if (persistedObj.version > version) {
return true
}
} else {
log.warn "No version param found for ${persistedObj.getClass()}"
}
false
}
you can call isStale from an action like this
def update() {
Competition competition = Competition.get(params.id)
if (isStale(competition)) {
// handle stale object
return
}
// object is not stale, so update it
}
I am not sure what you expect to happen but what you describe sounds correct to me unless you have code in your save() action that is relevant.
You can't expect Hibernate to do anything special here. When your save() action is invoked the instance is retrieved using Hibernate, mutated and then saved. That is all fine as far as Hibernate is concerned.
One way to deal with this is when the form for editing the entity is rendered, render the version of the entity that is being edited to a hidden form field which will be submitted when the entity is saved. In the save action after retrieving the entity from the database compare its version to the version retrieved from the hidden form field and if they don't match you know that the entity was modified between those 2 steps and you can react however is appropriate for your app. Note that since your example is using a command object, data binding is being imposed on the entity before your code ever executes. If that isn't what you want, don't use a command object.
I hope that helps.

Why is GORM not saving my object?

If I execute this code in the Grails console:
def p = new Post(title: "T");
p.save(flush: true); // or p.save();
Post.count();
GORM is not throwing any exceptions, but the data is not saved in my DB. What am I doing wrong?
It's likely you have a constraint violation. Add failOnError: true to your save method parameters. Then you'll get an exception when your save fails. (Alternatively you can check the return value from save, and if it's false print out p.errors.allErrors().)
Validation and saving are done together. If you are validating user-submitted data that's been bound to some domain object, then in order to check for the save failing due to invalid input the idiomatic thing to do is check the return value of save; failing on account of invalid input is not exceptional behavior. If you just want to save the contents of the object and want an exception thrown if there's a problem, use failOnError.
For more on the rationale on why they designed GORM so that you need to do this see this article.
Likely some constraint on Post is being violated and thus the object is not being saved. Note that the default behavior of GORM is not to throw on a failed save. You need to either call it like
p.save(flush: true, failOnError: true);
Or change the behavior globally by adding
grails.gorm.failOnError=true
to your Config.groovy

troubleshooting a NullPointerException in grails

preface note: I'm just starting to learn Grails, so I'm sure there are many other problems and room for optimization.
I've got two domains, a parent (Collection) and child (Event), in a one-to-many mapping. I'm trying to code an integration test for the deletion of children. Prior to the code in question, I've successfully created a parent and three children. The point where I'm having problems is getting a single child in preparation to delete it. The first line of my sample code is only there because of my rudimentary attempt to troubleshoot.
// lines 95-100 of my EventIntegrationTests.groovy file
// delete a single event
assertEquals("2nd Event", event2.title) // passes
def foundEvent = Event.get(event2.id) // no apparent problems
assertEquals("2nd Event", foundEvent.title) // FAILS (line #98)
foundEvent.delete()
assertFalse Event.exists(foundEvent.id)
The error message I'm getting is:
Cannot get property 'title' on null object
java.lang.NullPointerException: Cannot get property 'title' on null object
at edu.learninggrails.EventIntegrationTests.testEventsDelete(EventIntegrationTests.groovy:98)
What should my next troubleshooting steps be? (Since the first assertEquals passes, event2 is clearly not null, so at this point I have no idea how to troubleshoot the failure of the second assertEquals.)
This is not evident from the code: did you persist event2 by calling save()? Get will try to retrieve it from the persistent storage (the in-memory database for example) and if the event wasn't saved, the retrieved instance will be null.
If you did save it, did the save go through OK? Calling event.save() will return false if there was something wrong while saving the item (like a validation error). Lastly, you might try calling event.save(flush:true) in case the Hibernate session doesn't handle this case as you might expect (I'm not entirely sure about this one, but it can't hurt to try).
Try to print or inspect the event2.id on line 97 and check if you actually have an id, if so check if you actually get an Event object on line 97.
I dont think you saved the parent and its children successfully. after you save, you should make sure that every object that was persisted has a non null id, in your test.
What you are seeing is you created the event2 with a title, but didnt save it. It passes the first assertion because you created it. When you do the get, null is returned because your save failed.
in general for DAO integration tests i do the following
Setup -- create all objects Ill use in the test.
Save -- assert that all ids on saved objects are NOT null.
Clear the hibernate session -- this is important because if you don't do it, objects can be in the session from the previous operations. In your real world scenario, you are probably going to start with a find, i.e. an empty session. In other words, you are not going to start with anything in the session. If you are you need to adjust this rule so that the session in the test, when you start the actual testing part, is the same as the session of the code in the wild
Load the objects on which you want to operate and do what you need to do.

Resources