Grails Problem with custom error messages - grails

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

Related

Puzzling validation error after upgrading from Grails 2.2.5 to 4.0.11

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.

Hibernatate doesn't bind enums

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.

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

Custom error message in message.properties

I've got Form domain class and there is typeOfTransaction property. This property is required (blank: false). I want to write custom error message for this property, if the user does not set the value, the message must be appeared.
com.example.domain.form.typeOfTransaction.blank = Type of transaction required
Above is the message, but I don't get it when I'm trying to save form with empty typeOfTransaction field. Instead of this message I've got default message
"Please select an item in the list."
p.s. I don't know where this default message is defined.
If you use the absolute name of your class you need to use the exact name of the class, including capitalization - so I'm guessing you should put:
com.example.domain.Form.typeOfTransaction.blank = Type of transaction required
If you don't use the absolute name you don't capitalize the class name:
form.typeOfTransaction.blank = Type of transaction required
Well, for 1.3.7 it should be in grails-app/i18n/messages.properties (or one of the language specific variants if appropriate). I assume 2.0 would use the same location.

parameterized Grails validation messages

In the messages.properties file in a Grails application I've seen examples of validation messages such as:
User.password.size=Size of bar must be between {0} and {1}
which applies to
class User {
String password
static constraints = {
password(size:5..15)
}
}
This example assumes that {0} is bound to the minimum size and {1} is bound to the maximum size, but I cannot find any documentation of which parameters may be used by error messages for each built-in constraint. In other words, what I'd like to know is: for each built-in constraint what is the meaning of {0}....{n}
I did some experimentation and I discovered that for a constraint such as:
class User {
String password
static constraints = {
password(size:5..15)
}
}
The values of the placeholders are:
0. Name of the class (User)
1. Name of the property (password)
2. Value of the property
3. First constraint parameter (5)
4. Second constraint parameter (15)
5. etc.
You're right, I've never found any documentation of that either. Best bet? Change your messages to something like:
User.password.size=0:{0}, 1:{1}, 2:{2}, etc...
and see what you get for each one you're interested in. If you posted that info to the Nabble message board on Grails, I'm sure it would find it's way into the documentation.
Good luck.

Resources