Hibernatate doesn't bind enums - grails

After update to Grails 2.3.7 from Grails 2.2.4 enums binding in my domains stop working.
I can't figure out what happened, someone could give me a hint?

There may be some specific aspect that is broken and if you can identify that please report a JIRA and we can look at it, but in general enum binding does work in Grails 2.3.7. The simple way to make that work is to have request parameters whose name matches the name of the enum property you are binding to and the value is the String representation of the enum instance. For example, if you have the following...
// grails-app/domain/com/demo/Company.groovy
class Company {
Status companyStatus
// ...
}
// src/groovy/com/demo/Status.groovy
enum Status {
ACTIVE, INACTIVE
}
Then if you bind companyStatus='INACTIVE' or companyStatus='ACTIVE' to a Company object, that should work.
I just created a sample app at https://github.com/jeffbrown/enumbinding which demonstrates that working in Grails 2.3.7. Run the app and submit the form on the default index page to see it in action.
I hope that helps.

Related

Grails 2.4.4 upgrade data binding issue

A pattern we use here for large dynamic forms is to allow the client to edit pretty much the entire graph including children and removal and addition of children is handled in javascript. Failing use case is when user deletes a property of one of the children and for this example we'll say the email address of the second child is removed and the parm is sent empty.
Example Class Structure
Domain X
Long id
String name
SortedSet<Child> children
Domain Child
Long id
Integer position // used to sort
String name (required)
String email (required)
Parms are named in this manner:
x.id = 1
x.name = 'blah'
x.children[0].id = 1
x.children[0].position = 0
x.children[0].name = 'childa0'
x.children[0].email = 'child0#any.com'
x.children[1].id = 2
x.children[1].position = 1
x.children[1].name = 'child1'
x.children[1].email = ''
Current stored values:
x.id = 1
x.name = 'blah'
x.children[0].id = 1
x.children[0].position = 0
x.children[0].name = 'childa0'
x.children[0].email = 'child0#any.com'
x.children[1].id = 2
x.children[1].position = 1
x.children[1].name = 'child1'
x.children[1].email = 'child1#any.com'
The pattern to update has been:
Browser
user edits all and submits changes
parms are sent as shown above and in this use case user accidentally deleted email address that is required (yes submit could be prevented in this simple case but there are more extensive validation rules and this is just a simple example to illustrate issue)
Server
retrieve current parent domain class using id parm
check current stored version against edited version and ensure it has not changed
apply all parms to current domain object in this manner: x.properties = parms.x
This is where it breaks down. With Grails 2.2.2 the email property of child[1] is updated to an empty string and running validation catches the error. Grails 2.4.4 does NOT update the child value. I know the data binding changed and perhaps there are valid reasons for this change but I can't fathom it. This has worked from 1.3.6 to 2.2.2.
One thing to note is that if I do not retrieve the domain class and instead create a new instance with the parms passed in all of the child parms are set correctly.
X x = new X(params.x)
This seems to indicate some Grails issue as the user guide talks about both methods as equal - one to use for new instances and the other for updates but the examples clearly demonstrate that both methods should handle indexed child properties.
Any help or thoughts are appreciated!
I ran into this problem my self upgrading an application from 2.2.4 to 2.4.4.
Setting grails.databinding.useSpringBinder = true for config.groovy
and adding grails-web-databinding-spring to the pom worked flawlessy for me.
Obviously doing this was a lot less hassle than rewriting all the binding code :-)
Looking into this further Grails 2.4.4 documentation states that it will bind sets positionally if they are indexed (ie. [0]).
http://grails.org/doc/latest/guide/single.html#dataBinding
The section titled "Data Binding and Many-ended Associations" states that these parms will be bound and that new instances of the set will be created if their index is greater than the current set. This was true for me in Grails 2.2.2 but NOT in 2.4.4.
HOWEVER, earlier in the documentation in the section "Binding To Collections And Maps" it states clearly: "When updating existing elements in a Set the Map being assigned to the Set must have id elements in it which represent the element in the Set".
If you are upgrading to Grails 2.4.4 and have any complex form data binding I suggest you look there first to decide whether to upgrade. Due to these changes in data binding this has become the most complex upgrade we've encountered yet with Grails.
The other disappointment with 2.4.4 is that it states you can override the new binding and fall back to the old spring binding but you cannot past 2.4 - at least from what I can gather from others' posts and my attempts. Setting the config property as documented and adding the dependency required resulted in startup runtime errors.
Apparently older versions of grails prior to 2.4.4 would match the child instances to params positionally, i.e. using the indexes ([0],[1], etc.) to match the children not caring if the IDs of the instances matched. The new binder does want the IDs of the instances to match before binding. I had never realised I was not placing the ID in a hidden field as it always worked perfectly.
I had a similar problem after migrating to Grails 2.4.4 (from 2.2.2). After a lot of reading and seaching (you must to definitly read http://docs.grails.org/2.4.4/guide/single.html#dataBinding mencioned in user2863513 post) I've resolved it in a very simple way
In my application I had nested domains relationships. Example:
class A {
String name
static hasMany = [b:B]
}
class B {
String name
static hasMany = [c:C]
}
class C {
String name
}
Due to the form complexity, class C object were not binding correcly. I've resolved this defining the C atribute on class B as a List (remember, has many relationships are implemented as Sets by default). So, my class B changed to:
class B {
String name
static hasMany = [c:C]
List c
}
And voila! Everything works perfectly again.

Grails adding version to command object causes id and version from params not to be bound

I apologize if I'm missing something really obvious here but I've been pulling my hair out with this issue.
I have a command object:
class MyCommand {
Long id
String value
}
I bind to this in my controller:
public update(MyCommand myCmd) {
}
Everything is fine in this scenario. Now I'm trying to add the version field, which is passed in the request parameters to the command object:
class MyCommand {
Long id
Long version
String value
}
Now however when the binding happens the id and version are always null, even though they are present in the params object.
I suspected that there may be some special handling for id / version attributes related to how grails handles optimistic locking (as this is ultimately why I'm doing this) but the issue is present at the command object independent of any domain object.
I'm baffled why this is not working. Is there some special case when version is present on a command object?
Seems this is by design per Jeff Brown jira
The data binding explicitly avoids binding id or version [if] they both
exist and does this by design. This is a shield against potential
security problems relevant to data binding as it relates to domain
classes. A simple work around for command objects would be to name the
properties with something like "idValue" and "versionValue" or
anything other than "id" and "version".

Grails domain custom error messages

I am working in a grails application, I have many domains in the applications, more than 50! The error message generated are default, I have the following in my message.properties file
default.blank.message=Field "{0}" cannot be blank.
An example of my one of the domain class is as follows:
class Person {
String firstName;
String lastName;
String middleName;
Date dob;
String gender;
String religion;
String nationality;
String maritalStatus;
Zone permAddZone;
District permAddDistrict;
String permAddVDC;
}
And so on, so when I leave a field, for example 'maritalStatus' the following error message shows up, 'Field "maritialStatus" cannot be blank.'. I also added the following to my message.properties file
person.maritialStatus=Maritial Status
But still I am getting the 'Field "maritialStatus" cannot be blank.' message. I also tried using I18n Templates Plugin, but as I have a lot of domain classes, modifying error message for all of them would be time consuming. So, what choices do I have or what am I doing wrong. Any help is appreciated.
The appropriate message key to override is specified on the reference page for each constraint type. In the case of blank it's
com.example.Person.maritalStatus.blank=Marital status must not be blank
However this will be very time consuming and repetitive if you have many domains and many properties.
What you are asking for is instead a way to process the domain class property names in some way before they are inserted into the default messages. This isn't something Grails supports out of the box but I like a challenge... and I've found a surprisingly elegant way to implement it. My approach is the grails plugin available at https://github.com/ianroberts/recursive-messages and it works by extending the format string syntax to support placeholders of the form
default.blank.message=Field "{0,message,field.name.}" cannot be blank.
A placeholder {N,message,prefix} is resolved by prepending the given prefix to the usual placeholder replacement value and then treating the resulting string (field.name.maritalStatus in this example) as a no-argument message key, and looking that up in the usual way. Thus you could have different representations for different languages.
It has to be a plugin because it relies on a trick that works in a plugin's doWithSpring but doesn't work in an application's resources.groovy, to modify the definition of the default messageSource Spring bean.
Disclaimer: this was a quick fix, it hasn't been fully tested and could probably be implemented more efficiently.
In order to override the field label you need to override the key:
<package>.<domainclass>.<fieldname>.label
So in your case, try:
<package>.Person.martialStatus.label=Label

grails removeFrom removes only one at a time

I have a grails application where I have contacts which belongs to another domain contactGroup. It all seems to be working fine except for removeFromContacts method. I am using following code. The code works correctly but removes only one contact from the group at a time. I even did some debugging and the foreach loop runs as many times as the contacts provided. There is no error message. Any idea what could be going wrong -
ContactGroup group = ContactGroup.findByIdAndOwner(params.groupId, user)
def contactIds = request.JSON.data.contact
contactIds.each {
Contact contact = Contact.findByContactIdAndOwner(it.contactId, user)
if(contact) {
group.removeFromContacts(contact)
}
}
I've read a few things about the findAll methods loading proxies if the associations are lazy-loaded rather than the "real" instance.
Try this:
group.removeFromContacts(Contact.get(contact.id))
The 'get' should bypass the proxies and use the "real" instance. There is a JIRA that talks about this (Grails-5804). An overall fix according to the JIRA (from Burt Beckwith) is to implement the equals and hashCode method in your Contact class.
Thanks for all your support. I realized that I have not defined the relationship at the domain level correctly and that was messing up with the whole thing. When I corrected that it was working correctly.
saurabh

Grails Problem with custom error messages

I am currently trying to specify custom error messages in grails for the default constraints but so far all I get back is the default error message.
I know that I have to edit the grails-app/i18n/messages.properties file
If I change the following default error codes message, it will correctly display the new error message
default.blank.message=Property [{0}] of class [{1}] cannot be blank
However, this is not what I am trying to do. I need more granular error reporting and have more than one field that can be blank etc. What I would like to be able to do would be, display custom messages for each field in a class
package com.mycompany.myapp
class Test{
String name
def constraints = {
name(nullable:false, blank:false)
}
}
(following codes appended to end of messages.properties)
test.name.blank=Name cannot be blank
test.name.nullable=Name cannot be nullable
According to the grails documentation this should work correctly, either with or without the package name - className.propertyName.blank
grails.org/doc/latest/ (constraints section) & (section 7.4 - validation & internationalization)
I have tried all comnbinations that I can think of, but it always displays the custom message
I have also tried installing the grails i18n templates plugin
http://www.grails.org/I18n+Templates+Plugin
which generated the error codes automatically for me. I appended the new error codes to the end of the existing messages.properties file but I still get the default error messages.
However, there was something different with the error codes that were generated by the plugin.
instead of the format specified in the grails doc - test.name.null=......, it automatically generated test.name.null.error=Custom Message
I have also tried deleting the default error messages completely, but they are still displayed
If anyone has experienced this issue before, I would appreciate any help that anyone can give me
Thanks in advance
put def messageSource (in controller or service)
item.errors?.allErrors?.each{
println messageSource.getMessage(it, null)
};
I also found a good link which explains this better
http://johnrellis.blogspot.com/2010/02/retrieve-grails-domain-errors-from.html
Well, the documentation shows you an example of how to override the messages for one of the default Validation Constraints (blank, nullable, min, max, size, range, etc.). But it fails to tell you to look in the documentation for each Constraint and at the bottom it shows you what propery key to use:
Error Code: className.propertyName.size.toosmall or className.propertyName.size.toobig
for Constraint size http://grails.org/doc/latest/ref/Constraints/size.html
So, for
package com.example
class User {
String username
static constraints = {
username size:5..15
}
}
use:
com.example.User.username.size.toosmall=Yo there! too small: [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
com.example.User.username.size.toobig=Yo there! too big: [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}]
It might be that your constraints aren't static - it should be specified as "static constraints = { ..."
Also note that nullable defaults to false so you don't need to specify that.
I use fully qualified class names in my messages.properties
com.shareyourlove.User.password.blank=Some custom message
This worked for me
com.model.Customer.name.nullable.error = Custom message
instead of
com.model.Customer.name.blank = Custom message

Resources