0
votes

In my Grails 2.3.7 app, I have the following command object

class UpdateThresholdsCommand {
    Double threshold_1
    Double threshold_2
}

The parameters I'm trying to bind to these properties are formatted currency values, e.g. threshold_1=$2,459.04&threshold_2=$1,459.04

I've defined the following implementation of ValueConverter to perform this binding

class CurrencyStringToDoubleConverter implements ValueConverter {

    FormatService formatService

    @Override
    boolean canConvert(Object value) {
        value instanceof String
    }

    @Override
    Object convert(Object value) {
        formatService.parseCurrency((String) value)
    }

    @Override
    Class<?> getTargetType() {
        Double
    }
}

and registered it in resources.groovy

currencyStringToDoubleConverter(CurrencyStringToDoubleConverter) {
    formatService = ref('formatService')
}

But when a request with params such as those shown above is sent to the action, CurrencyStringToDoubleConverter is never invoked, so the threshold_1 and threshold_2 properties of the command object are null. Why isn't CurrencyStringToDoubleConverter being invoked?

2
You haven't set grails.databinding.useSpringBinder to true have you? The Spring binder does not use ValueConverter beans. - Jeff Scott Brown
@JeffScottBrown no I'm using the new grails binder - Dónal
Mysterious indeed. My first guess was that your converter or service was probably throwing an exception but on second read of your description, "CurrencyStringToDoubleConverter is never invoked" tells me that isn't the case. - Jeff Scott Brown

2 Answers

2
votes

The approach you describe does work. See the app at https://github.com/jeffbrown/donalconverter. Run that app and click the link on the main index page. The FormatService is hardcoded to return 21.12 (see https://github.com/jeffbrown/donalconverter/blob/7a01031deceeea0d857af23f58686b4f1f824e1d/grails-app/services/demo/FormatService.groovy#L7) but the app demonstrates that the converter is being invoked and that the converter is delegating to the service.

You have not shown what your FormatService is doing. It may be that there is something wrong in that code and that is throwing an exception, in which case your command object should have a corresponding binding error associated with it.

It is difficult to say what is going wrong without seeing your code or seeing any relevant errors, but the linked app should demonstrate that the converter is being invoked, at least in that app.

The relevant files in the app:

I hope that helps.

0
votes

If anyone finds their way here, you may have to put this annotation on your converter to give it a higher precedence than the built in Grails converters:

import org.springframework.core.annotation.Order
import org.springframework.core.Ordered

@Order(value=Ordered.HIGHEST_PRECEDENCE)
class DateTimeValueConverter implements ValueConverter  {
    // blah blah
}