BigDecimal and Locale in Grails

I was recently puzzled by strange behaviour of Grails application with web service interface. It resulted with rounding currency amount values when I sent request from my browser but it worked perfectly if another client application sent same…

I was recently puzzled by strange behaviour of Grails application with web service interface. It resulted with rounding currency amount values when I sent request from my browser but it worked perfectly if another client application sent same request. After investigation it turned out that the HTTP requests were not exactly identical. The browser request contained header entry with Polish locale pl-PL for which coma is a decimal separator.

Request
http://localhost:8080/helloworld/amount/displayAmount?amount=12.22

Header
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4

In order to reproduce this behaviour I created a simple Grails 2.1 HelloWorld app.

AccountController.groovy

package helloworld

class AmountController {

    def displayAmount(PaymentData paymentData) {
        render "Hello, this is your amount: " + paymentData.amount.toString()
    }
}

PaymentData.groovy:

    package helloworld

import grails.validation.Validateable

@Validateable
class PaymentData {
    BigDecimal amount

    static constraints = {
        amount(nullable: false, min: BigDecimal.ZERO, scale: 2)
    }
}

 

Starting this app we can observe rounding of cents in amount to 00 when sending request with dot in amount (http://localhost:8080/helloworld/amount/displayAmount?amount=12.22)


Whereas for amount with coma it gives a result with valid cent part (http://localhost:8080/helloworld/amount/displayAmount?amount=12,22)


Same behaviour might be expected in case of other locales that use coma as decimal separator, e.g. de_DE. Very not an obvious feature.

You May Also Like

Grails render as JSON catch

One of a reasons your controller doesn't render a proper response in JSON format might be wrong package name that you use. It is easy to overlook. Import are on top of a file, you look at your code and everything seems to be fine. Except response is still not in JSON format.

Consider this simple controller:

class RestJsonCatchController {
def grailsJson() {
render([first: 'foo', second: 5] as grails.converters.JSON)
}

def netSfJson() {
render([first: 'foo', second: 5] as net.sf.json.JSON)
}
}

And now, with finger crossed... We have a winner!

$ curl localhost:8080/example/restJsonCatch/grailsJson
{"first":"foo","second":5}
$ curl localhost:8080/example/restJsonCatch/netSfJson
{first=foo, second=5}

As you can see only grails.converters.JSON converts your response to JSON format. There is no such converter for net.sf.json.JSON, so Grails has no converter to apply and it renders Map normally.

Conclusion: always carefully look at your imports if you're working with JSON in Grails!

Edit: Burt suggested that this is a bug. I've submitted JIRA issue here: GRAILS-9622 render as class that is not a codec should throw exception

Me on Hadoop on Parleys

Finally I've managed to import my WarJUG presentation to parleys.com. See for yourself :) If you've got problems with opening the parleys' version try the ones uploaded to youtube. Here is part 1: And here is part 2: Finally I've managed to import my WarJUG presentation to parleys.com. See for yourself :) If you've got problems with opening the parleys' version try the ones uploaded to youtube. Here is part 1: And here is part 2: