Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails databinding with decimal delimiter

Tags:

grails

I have a problem when I use grail automatic databinding "ex: Test t = new Test(params)" with decimal delimiter on Double form field. After few search, I've found that it is relative to the browser Locale.

Example : If I enter number with decimals separated by a dot '3.45' it does not work (The decimal part of the number is ignored). It store 3.0 in my database

If I do the same test but using a comma '3,45' for decimal separator, everything works fine. Grails store 3.45 in the database.

The problem is that nobody enter number with comma delimiter. (even the numpad enter a dot '.' when set to fr_CA)

I've already found some solutions like register custom number editor (bit painful when you have many apps) or set the global localeResolver to en_US (that last one doesn't do the job because I loose all the internationalization functionality of my app).

So, does someone have an easy solution to fix that problem?

using: Grails : 2.2.0 Browser : Google Chrome (locale fr_CA)

Thanks a lot!

like image 653
rattek Avatar asked Feb 14 '13 14:02

rattek


2 Answers

I've been searching and trying for 2 days. I've finally chosen to define a custom PropertyEditorRegistar. This way, I can fix the Locale only for the Double field format. However, I don't think that it's the best solution because it will be applied to all my Double fields. But in the mean time it does the job pretty well. So if someone have a better solution, I will be glad to test it and update my code.

So this is how I set this up :

1 - Create a new groovy class that implements PropertyEditorRegistrar (if you already have one, just add the part of code contained by the method in the existing one)

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomNumberEditor;

public class CustomDoubleRegistrar implements PropertyEditorRegistrar {

    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
            //define new Double format with hardcoded Locale.ENGLISH
        registry.registerCustomEditor(Double.class, 
                 new CustomNumberEditor(Double.class, 
                           DecimalFormat.getInstance(Locale.ENGLISH),true))
    }

}

2- Define the custom registrar into the conf/spring/resources.goovy (if it's not already there of course)

beans = {
    customPropertyEditorRegistrar(CustomDoubleRegistrar)
}

3- That's it, the Grails auto data binding will work fine

Test t = new Test(params); 
//params contains many Double fields with dot '.' as decimal delimiter

Don't hesitate to post better solutions... Thanks

EDIT 1

Since Grails 2.3 this solution is no longer working. If you still want to use this solution, you have to add this configuration to the Config.groovy file

grails.databinding.useSpringBinder = true

Or implement one of the new DataBinding. I've tried few of them but nothing seems to solve the decimal delimiter issue. Thank you to post answer if you know how...

EDIT 2

Since Grails 2.4+ you can define your own ValueConverter to bypass the basic Locale validation. Note that you must remove the changes made in the initial post and in the EDIT 1. Here's how to implement the custom ValueConverter:

conf/spring/resources.groovy

// Place your Spring DSL code here
beans = {
    "defaultGrailsjava.lang.DoubleConverter"(DoubleValueConverter)
}

class DoubleValueConverter implements ValueConverter {

    public LongValueConverter() {
    }

    boolean canConvert(value) {
        value instanceof Double
    }

    def convert(value) {
        //In my case returning the same value did the trick but you can define 
        //custom code that takes care about comma and point delimiter...
        return value
    }

    Class<?> getTargetType() {
        return Double.class
    }
}
like image 124
rattek Avatar answered Oct 16 '22 00:10

rattek


For Grails 2.3+ you can properly override the default binder/converter, although it is not trivial or intuitive.

See my answer here: Binding real number values to Grails domain attributes (values sent by Dojo widgets)

like image 43
sola Avatar answered Oct 16 '22 00:10

sola