4

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

Eel Lee
  • 3,513
  • 2
  • 31
  • 49
  • I don't have time to check today (not working), but this similar question has an answer worth investigating (in case you haven't seen it): http://stackoverflow.com/questions/24274274/binding-real-number-values-to-grails-domain-attributes-values-sent-by-dojo-widg?lq=1 – wwwclaes Sep 21 '15 at 14:46

1 Answers1

5

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.

wwwclaes
  • 1,152
  • 8
  • 12
  • Hi! Have you had time to test this solution and did you get it to work for you as well? – wwwclaes Sep 24 '15 at 11:45
  • Yes, and it worked! So the only problem left for me was wiring it with a right name. And that was `defaultGrailsBigDecimalConverter`. Thank you *very*, very much! And congratulations, bounty hunter, you won the prize! :-) – Eel Lee Sep 27 '15 at 13:21
  • Great to hear! It's funny, but the bounty actually made a difference. It made me prioritize my tasks differently and "just go for this now for the bonus" :-) Good to know when I get stuck! – wwwclaes Sep 27 '15 at 16:57