Reputation: 3543
What is the problem:
In my application, numbers on the front-end are always presented with a ,
as a decimal separator. The problem with wrong binding occurs when an user changes his locale and edits the entity with ?lang=en_EN
parameter. What happens is that with en_EN
locale, the decimal separator is .
which makes value on the input 11,00
, 1100
in the database, instead of 11.00
- critical problem when it comes to money.
Software used:
Grails 2.3.8
Groovy 2.2.1
What I want to do:
In my case the default "locale aware" approach in converters is very problematic, and I want them to be binded always the same way, which should be locale-independent.
What I have already tried:
I found that what makes the job by default is LocaleAwareNumberConverter
and more specifically LocaleAwareBigDecimalConverter
, so I wrote a simple implementation which simply uses one locale (in this case GERMAN
, as it uses ,
as a decimal separator)
@CompileStatic
class MyBigDecimalConverter extends LocaleAwareNumberConverter {
@Override
protected NumberFormat getNumberFormatter() {
NumberFormat.getInstance(Locale.GERMAN)
}
}
included it in the resources.groovy
:
myBigDecimalConverter com.company.converters.MyBigDecimalConverter
But it just doesn't work. Values are still converted with LocaleAwareBigDecimalConverter
.
EDIT:
I've changed my converter to directly implement ValueConverter
:
@CompileStatic
class MyBigDecimalConverter implements ValueConverter {
@Override
boolean canConvert(Object value) {
value instanceof String
}
@Override
Object convert(Object value) {
def numberFormatter = NumberFormat.getInstance(Locale.GERMAN)
numberFormatter.parse((String)value).asType(getTargetType())
}
@Override
Class<?> getTargetType() {
BigDecimal
}
}
And this converter also doesn't get called. I made no changes to the resources.groovy
Upvotes: 4
Views: 919
Reputation: 1152
Ok, I think I got it working now. It is based on my code, but should work for you as well.
To register your own ValueConverter
for BigDecimal
, you should add defaultGrailsBigDecimalConverter(YourBigDecimalValueConverter)
to resources.groovy. I derived that conclusion from DataBindingGrailsPlugin.groovy for Grails 2.3.11.
If you have grails.databinding.useSpringBinder = true
in Config.groovy, you need to remove that to enable the new data binding for Grails 2.3.
My ValueConverter
is similar to your your second sample that implements it directly, so use that one first to minimize other problems that might occur.
That's all there is to it. I have implemented a ValueConverter
that accepts both dot and comma as separator and then presents it according to the user's locale. It is working, the tricky part was figuring out the correct name for resources.groovy and at the same time have the Spring binder disabled.
Upvotes: 5