If I create a Domain Object with a nullable LocalDate, the scaffolding editor throws a validation error if the date is empty: Cant populate a class org.joda.time.LocalDate without a year
This seems to come from within the Joda DateTimeStructuredBindingEditor.getPropertyValue
Does anyone know how to prevent this validation problem?
I'm not positive, but if the issue is coming from the scaffolding, it's possible that it is sending a blank date, not a null one.
I would try to:
1 - Check if the localDate is actually null before you save it.
2 - Add "blank: true" as a constraint. You shouldn't need this, as it's not a string, but it may work.
http://grails.org/doc/latest/ref/Constraints/nullable.html
Related
A method which was working for a long time in Grails 2.2.5 has broken after moving to 4.0.11 with a validation error on saving, and the error is a puzzle to me. I have a domain class 'Decline' which has one of its properties 'user', which is of domain class user. As part of the save process I assign the currently logged in user to this property:
Decline decline = new Decline()
decline.policy = policy
decline.declineTime = new Date()
decline.field = field
decline.cause = reason
decline.user = User.getUser()
decline.save(flush:true)
This was working fine in 2.2.5 but now I get the following validation error:
Field error in object 'myapp.pei.Decline' on field 'user.userType': rejected value [DIRECT_CLIENT]; codes [myapp.User.userType.nullable.error.myapp.pei.Decline.user.userType,myapp.User.userType.nullable.error.user.userType,myapp.User.userType.nullable.error.userType,myapp.User.userType.nullable.error.myapp.UserType,myapp.User.userType.nullable.error,user.userType.nullable.error.myapp.pei.Decline.user.userType,user.userType.nullable.error.user.userType,user.userType.nullable.error.userType,user.userType.nullable.error.myapp.UserType,user.userType.nullable.error,myapp.User.userType.nullable.myapp.pei.Decline.user.userType,myapp.User.userType.nullable.user.userType,myapp.User.userType.nullable.userType,myapp.User.userType.nullable.myapp.UserType,myapp.User.userType.nullable,user.userType.nullable.myapp.pei.Decline.user.userType,user.userType.nullable.user.userType,user.userType.nullable.userType,user.userType.nullable.myapp.UserType,user.userType.nullable,nullable.myapp.pei.Decline.user.userType,nullable.user.userType,nullable.userType,nullable.myapp.UserType,nullable]; arguments [userType,class myapp.User]; default message [Property [{0}] of class [{1}] cannot be null]
There are two things which are puzzling about this. Firstly, and more importantly, this appears to be an error saving the User object. But why is it even trying to save the User object? I have assigned an existing User object which it should be using. Secondly, the specific error is 'rejected value [DIRECT_CLIENT]' for field 'user.userType', but the error message is that this field cannot be null. So it's rejecting a value but telling me it cannot be null! The value, incidentally, is of a UserType enum defined thus:
public enum UserType {
ADMIN_USER,ADMIN_OWNER_USER,SUPER_USER,BROKER,DIRECT_CLIENT
}
I wonder what change from version 2.2.5 to 4 (or maybe 3) could have caused this?
It seems there was some change in behaviour of deepValidate between Grails 2.x and 4.x which is causing this, although I don't see why validation of the associated User object should be failing when it can actually be saved OK separately. But what got me past this issue was to set the following in the mapping block for Decline:
user cascadeValidate: 'none'
This ensures that when the Decline object is saved it does not attempt to validate the User as well.
Context:
app using CoreData
some lightweight migration successfully performed in the past (reached the 4th iteration of the model version)
client wants a new feature
created a 5th model version
added one single lousy new property, a non-optional boolean called new_one, to the TestModel entity
The outcome:
CoreData: error: NSUnderlyingError = "Error Domain=NSCocoaErrorDomain Code=134110 \"An error occurred during persistent store migration.\"
UserInfo={
entity= TestModel,
attribute=new_one,
reason=Validation error missing attribute values on mandatory destination attribute}";
}
Solution:
I don't completely grasp why this happens (I'm too tired and eager to leave this problem behind), but the "mandatory destination attribute" thing pointed me in the direction of setting the property as an optional. Whether it's the right thing to do or just an ordinary hack...I don't know...but it solved my problem, I can now move on to the next
You've pretty much hit the nail on the head but it sounds like maybe you don't know why. It's because:
The attribute was required
Which means it must have a value when changes are saved
Migration saves changes, but
You didn't provide any value for this attribute.
That leads directly to the error that you received.
You can fix this using any one of the following:
Make the attribute optional, as you did. After migration, no migrated objects have a value, but that's OK.
Keep it non-optional but provide a default value in the model editor. After migration, all migrated objects have the default value.
Set up a non-lightweight migration and provide values when migration occurs. After migration, each migrated object has whatever value you provide during migration.
I think providing a default value is better than superfluous optionality.
Better to use optional only when a value is indeed optional.
I'm running into a situation where a record is returning null for getPersistentValue(name) even when I can verify that the value was NOT null.
Test:
//get it
def team =Team.get(params.id)
if(team){
log.debug(team.dateCreated);//logs date correctly
team.properties=params;
log.debug(team.getPersistentValue('dateCreated');//logs NULL???
}
It does not do this for all records. The only obvious difference I can find is the "version" column kept by grails, but manually messing with this didn't alter the behavior. What situations would cause this method to return null when the record exists and the value was set on it?
I'm trying to give some DateTime fields default values from the model browser.
Whatever I type into the Default Value field, I get an error telling me The value must be in the form 'yyyy-MM-dd HH:mm:ss.fffZ'. I am assuming that format string uses the scheme documented here.
The value I punched in is 2014-05-23 00:00:00.0000, which I believe is of that form. I'm not sure whether 0 is a valid value for the Z component, but I don't know what the right value would be.
What could be wrong with the string I gave?
I figured it out. The Z component was indeed the issue. I just needed to use 2014-05-23 00:00:00.000Z instead.
Wondering if its possible to concatenate keyPaths to one attribute in mapping objects. Looking for something like
mapKeyPaths #"firstname", #"lastname", nil toAttribute:#"name"
Where name would then be "Bob Johnson"
** The API I am dealing with passes over a date and a startTime attribute, as 2012/02/28 and 16:12 respectively, as Strings.
It would be easier to just use startTime as "2012/02/28 16:12".
I figured I can get around this issue by leaving the date and startTime as NSDate fields, so I have tried setting up a dateFormatter per Restkits instructions. When I tried that idea, just using "HH:MM", for the startTime dateFormatter, it shoves "1970/01/01 16:12" into the startTime field.
Anyone have any suggestions, besides going through each record manually after mapping to Core Data and putting the fields in programatically?
I don't think you can do these kind of programmatic mappings yet.
Two alternative solutions come to mind:
1) In willMapData (or something like that) you can manually modify the incoming serialization before object mapping occurs. There you can specify a format you like.
2) Save both these properties in your Core Data entity and create a third transient attribute which is calculated at runtime, and when required, by passing these two values through a NSDateFormatter.