Grails has a bug with regards to databinding in that it throws a cast exception when you're dealing with bad numerical input. JIRA: http://jira.grails.org/browse/GRAILS-6766
To fix this I've written the following code to manually handle the numerical input on the POGO class Foo
located in src/groovy
void setPrice(String priceStr)
{
this.priceString = priceStr
// Remove $ and ,
priceStr = priceStr.trim().replaceAll(java.util.regex.Matcher.quoteReplacement('$'),'').replaceAll(',','')
if (!priceStr.isDouble()) {
errors.reject(
'trade.price.invalidformat',
[priceString] as Object[],
'Price:[{0}] is an invalid price.')
errors.rejectValue(
'price',
'trade.price.invalidformat')
} else {
this.price = priceStr.toDouble();
}
}
The following throws a null reference exception on the errors.reject()
line.
foo.price = "asdf" // throws null reference on errors.reject()
foo.validate()
However, I can say:
foo.validate()
foo.price = "asdf" // no Null exception
foo.hasErrors() // false
foo.validate()
foo.hasErrors() // true
Where does errors come from when validate()
is called?
Is there a way to add the errors
property without calling validate()
first?
I can't exactly tell you why, but you need to call getErrors()
explicitly instead of accessing it as errors
like a property. For some reason, Groovy isn't calling the method for it. So change the reject
lines in setPrice()
to
getErrors().reject(
'trade.price.invalidformat',
[priceString] as Object[],
'Price:[{0}] is an invalid price.')
getErrors().rejectValue(
'price',
'trade.price.invalidformat')
That is the easiest way to make sure the Errors
object exists in your method. You can check out the code that adds the validation related methods to your domain class.
The AST transformation handling @Validateable
augments the class with, among other things
errors
getErrors
, setErrors
, clearErrors
and hasErrors
The getErrors
method lazily sets the errors
field if it hasn't yet been set. So it looks like what's happening is that accesses to errors
within the same class are treated as field accesses rather than Java Bean property accesses, and bypassing the lazy initialization.
So the fix appears to be to use getErrors()
instead of just errors
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With