How to handle value type conversion in Spring

Viewed 40

I'm new in Spring and I am faced with a value type conversion issue. When typing String to Free Pass field which is required Integer, I'm expecting to get custom error message "Invalid number" from the properties file, but I'm getting:

Failed to convert property value of type java.lang.String to required type java.lang.Integer for property freePasses; nested exception is java.lang.NumberFormatException: For input string: "sdf"

Am I doing something wrong or missing some java libs?

Controller:

import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;

@Controller
@RequestMapping("/customer")
public class CustomerController {

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {
        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }

    @RequestMapping("/showForm")
    public String showForm(Model theModel) {
        theModel.addAttribute("customer", new Customer());
        return "customer-form";
    }

    @RequestMapping("/processForm")
    public String processForm(
            @Valid @ModelAttribute("customer") Customer theCustomer,
            BindingResult theBindingResult
    ) {
        if (theBindingResult.hasErrors()) {
            return "customer-form";
        } else {
            return "customer-confirmation";
        }
    }
}

Class:

import javax.validation.constraints.*;

public class Customer {

    @NotNull(message="is required")
    @Min(value = 0, message = "cannot be less than 0")
    @Max(value = 10, message = "cannot be more than 10")
    private Integer freePasses;
    
    public Integer getFreePasses() {
        return freePasses;
    }

    public void setFreePasses(Integer freePasses) {
        this.freePasses = freePasses;
    }
}

Config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/util
            http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- Step 3: Add support for component scanning -->
    <context:component-scan base-package="com.autosdet.autosdetmvc" />

    <util:properties  id="countryOptions" location="classpath:countries.properties" />

    <!-- Step 4: Add support for conversion, formatting and validation support -->
    <mvc:annotation-driven/>

    <!-- Step 5: Define Spring MVC view resolver -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames" value="messages" />
    </bean>
</beans>

Form:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Custome Form</title>
    <style>
        .error {color: red}
    </style>
</head>
<body>
    Fill out the form.Asterisk (*) required.
    <form:form action="processForm" modelAttribute="customer">
        Free Passes (*): <form:input path="freePasses" />
        <form:errors path="freePasses" cssClass="error" />
        <br><br>
        <input type="submit" value="Submit" />
    </form:form>
    <br><br>
    <a href="/autosdet_mvc_war_exploded">Main Menu</a>
</body>
</html>

Properties:

type.Mismatch.customer.freePasses=Invalid number
1 Answers

java.lang.NumberFormatException: For input string: "sdf"

String-to-Integer conversion in Spring is executed with Integer.parseInt() or Integer.valueOf(). Apparently your input "sdf" cannot be converted into a numeric value unlike e.g. "12345".

I'd check the value you actually pass into your form, namely freePasses parameter. It looks like you are feeding their some text, not numbers:

<form:form action="processForm" modelAttribute="customer">
        Free Passes (*): <form:input path="freePasses" />
        <form:errors path="freePasses" cssClass="error" />
        <br><br>
        <input type="submit" value="Submit" />
    </form:form>
Related