3

I have a spring controller which is taking multiple BigDecimal RequestParams.

My application locale is en_US but just for this controller method I need to bind and convert these BigDecimal parameters in de_DE locale (ie. #.###,## > DOT for grouping and COMMA for decimal separator).

These BigDecimal values are coming from the UI text boxes and they are already in the de_DE format. Here is my controller code which is failing with the following error:

"Failed to convert value of type 'java.lang.String' to required type 'java.math.BigDecimal'; nested exception is java.lang.NumberFormatException"

@RequestMapping(value = "/create", method = RequestMethod.POST)
public ModelAndView create(@RequestParam("referenceNumber") String referenceNumber, @RequestParam("startDate") @DateTimeFormat(pattern="dd-MM-yyyy") Date startDate, @RequestParam("amount1") @NumberFormat(pattern = "#.###,##") BigDecimal amount1, @RequestParam("amount2") @NumberFormat(pattern = "#.###,##") BigDecimal amount2) {

    // Do something and return

}

Spring somehow ignores my numberformat pattern. Please note that DateTimeFormat annotation works as expected; parsing the startDate parameter in correct form.

Any help would be appreciated.

Thanks.

5
  • You can debug javascript part of your code. I guess you are sending string value. You can cast it to number in your javascript code Commented Feb 5, 2017 at 19:15
  • @user3087839 javascript is irrelevant here; of course i am sending a bunch of strings from view side. Submitting a form is a way of sending string key,value pairs from one side to another. I am asking how to convert these string parameter values in a custom way. Commented Feb 5, 2017 at 19:18
  • The annotation works because it gives error like NumberFormatException. It is weird to send string and try to format it later. Commented Feb 5, 2017 at 19:20
  • 1
    Please give us actual examples of input. Commented Feb 5, 2017 at 19:38
  • @SotiriosDelimanolis here is one example: referenceNumber:P17-0227 startDate:02-03-2017 amount1:1.000,44 amount2:4.020,31 Commented Feb 5, 2017 at 19:47

2 Answers 2

5

You can use PropertyEditorSupport to handle the form input as follows:

Create class extending PropertyEditorSupport to convert String received from client to BigDecimal, for example:

import java.beans.PropertyEditorSupport;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

public class BigDecimalEditor extends PropertyEditorSupport {

    public void setAsText(String text) {
        NumberFormat formatter = NumberFormat.getNumberInstance(Locale.GERMAN);
        try {
            Number number = formatter.parse(text);
            BigDecimal bigDecimal = BigDecimal.valueOf(number.doubleValue());
            setValue(bigDecimal);
        } catch (ParseException e) {
            // handle exception here
        }
    }
}

And bind it with the controller, as:

@RestController
@RequestMapping(value = "/employee")
public class EmployeeController {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(BigDecimal.class, new BigDecimalEditor());
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public ModelAndView create(
            @RequestParam("amount") @NumberFormat(pattern = "#.###,##") BigDecimal amount) {
        System.out.println(amount);
        return new ModelAndView();
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the answer. It is kind of a workaround though because with customEditors we don't need to use NumberFormat annotation. I really would like to know if it is possible to use NumberFormat annotation with a custom pattern just like the DateTimeFormat pattern.
+1 This is the best method to me, but you can register a global init binder so you don't have to register one for every controller (keenformatics.blogspot.it/2013/08/…). And don't need to use NumberFormat annotation in controller parameter, CustomEditor will convert the amount also without the annotation.
As you use spring anyway, you could shorten the content of setAsText by using spring's NumberUtils: setValue(NumberUtils.parseNumber(text, BigDecimal.class, NumberFormat.getInstance(java.util.Locale.GERMAN)));
But take care! The dot is in both variants accepted as a grouping char. So 123.45 would not be an error but 12345.
2

I solved my problem with: @RequestParam(value="amount1", required=false) @NumberFormat(pattern="#0,00") BigDecimal amount1

2 Comments

I applied a workaround with PropertyEditorSupport but i will give it a try and let you know. Thanks
actually what you suggested also works. I gave it a try yesterday and it works nicely.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.