Type mismatch when I enter string for Int in one of the form parameter when I submit form in spring 3

9.9k Views Asked by At

I have a jsp form as following :

<form:form method="POST" commandName="command" action="RouteGradesGoals.html" >
<tr>
   <td class="style4" colspan="2">
    Goal</td>
    <td colspan="2">
        <form:input path="goal" type="text" id="goal" style="width:200px;" />
     </td>
     <td colspan="2">
         <form:errors path="goal" cssClass="error" />
     </td>
 </tr>
 <input type="submit" name="action" value="Delete" id="Button3" 
                        class="submitButton" />
</form:form>

As you see there is only one parameter goal in the command object and it is of type int in the command object.

But when I submit the form I gets this error by passing string for int in the goal param:

{"detail":"An error has occured while processing the request: org.springframework.validation.BeanPropertyBindingResult: 1 errors\nField error in object 'command' on field 'goal': rejected value [sadfasd]; codes [typeMismatch.command.goal,typeMismatch.goal,typeMismatch.java.lang.Integer,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [command.goal,goal]; arguments []; default message [goal]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'goal'; nested exception is java.lang.NumberFormatException: For input string: \"sadfasd\"]"}

The controller has a simple method to process this form as given below:

@RequestMapping( value = "/RouteGradesGoals.html", method = RequestMethod.POST )
    public String addInventoryGoal(@ModelAttribute( "command" ) InventoryGoal goal, HttpServletRequest request,
            BindingResult result, SessionStatus status, ModelMap model, HttpSession session){
        inventoryGoalValidator.validate(goal, result);
        if (result.hasErrors()) {
            return "RouteGradesGoals";
        }

        // do processing of the command object 
        return "RouteGradesGoals";

    }

Command object is as follows :

public class InventoryGoal {

private Integer goal;

public Integer getGoal() {
        return goal;
    }

    public void setGoal(Integer goal) {
        this.goal = goal;
    }

}

This is how I have added the message resolver in the context xml file :

<bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

<bean id="localeChangeInterceptor"
    class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="lang" />
</bean>

<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="en"/>
</bean>

<bean id="handlerMapping"
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
        <ref bean="localeChangeInterceptor" />
    </property>
</bean>

I have added these properties in the messages.properties

typeMismatch.command.goal=invalid goal1
typeMismatch.goal=invalid goal2
typeMismatch.java.lang.Integer=invalid goal2
typeMismatch=invalid goal3

web.xml :

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

    <display-name>Forerunner Webservice</display-name>
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.ids.forerunner.web.configuration.WebConfig</param-value>
    </context-param>
    <context-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>mysql</param-value>
    </context-param>
    <servlet>
        <servlet-name>restService</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>webapp</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>webapp</servlet-name>
        <url-pattern>/webapp/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>restService</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <!-- The CORS filter with parameters -->
        <filter-name>CORS</filter-name>
        <filter-class>com.ids.cors.CORSFilter</filter-class>

        <!-- Note: All parameters are options, if ommitted CORS Filter
             will fall back to the respective default values.
          -->
        <init-param>
            <param-name>cors.allowGenericHttpRequests</param-name>
            <param-value>true</param-value>
        </init-param>

        <init-param>
            <param-name>cors.allowOrigin</param-name>
            <param-value>*</param-value>
        </init-param>

        <init-param>
            <param-name>cors.supportedMethods</param-name>
            <param-value>GET, HEAD, POST, OPTIONS</param-value>
        </init-param>

        <init-param>
            <param-name>cors.supportedHeaders</param-name>
            <param-value>Content-Type, X-Requested-With</param-value>
        </init-param>

        <init-param>
            <param-name>cors.exposedHeaders</param-name>
            <param-value>X-Test-1, X-Test-2</param-value>
        </init-param>

        <init-param>
            <param-name>cors.supportsCredentials</param-name>
            <param-value>true</param-value>
        </init-param>

        <init-param>
            <param-name>cors.maxAge</param-name>
            <param-value>3600</param-value>
        </init-param>

    </filter>


    <filter-mapping>
        <!-- CORS Filter mapping -->
        <filter-name>CORS</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>APIProtectionFilter</filter-name>
        <filter-class>com.ids.forerunner.filter.APIProtectionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>APIProtectionFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

in the WebConfig.java I am importing resources as given below:

@ImportResource({"classpath:/META-INF/spring/forerunner-service.xml","/WEB-INF/webapp-servlet.xml"})

webapp-servlet.xml :

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

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix">
            <value>/WEB-INF/jsp/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>
    <context:component-scan base-package="com.ids.forerunner.webapp.controllers" />

    <mvc:resources mapping="/css/**" location="/css/" />
    <mvc:resources mapping="/images/**" location="/images/" />
    <mvc:resources mapping="/js/**" location="/js/" />
    <mvc:resources mapping="/forerunner_style.css" location="/forerunner_style.css" />

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="com.ids.forerunner.webapp.interceptor.ForerunnerRequestInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>

    <bean id="messageSource" class=" org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:message-webapp-error" />
</bean>

<!--    <util:properties id="tophireProperties" location="classpath:tophire.properties" /> --> 

</beans>

forerunner-service.xml:

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

    <!-- Enables automatic mapping of fund objects to and from JSON -->
    <mvc:annotation-driven />

    <import resource="classpath:/META-INF/spring/applicationContext.xml" />
    <import resource="classpath:/META-INF/spring/applicationContext-jpa.xml" />

    <bean id="contactFormValidator" class="com.ids.forerunner.webapp.validator.ContactFormValidator" />
    <bean id="inventoryGoalValidator" class="com.ids.forerunner.webapp.validator.InventoryGoalValidator" />
    <bean id="anchorAreaValidator" class="com.ids.forerunner.webapp.validator.AnchorAreaValidator" />

    <bean class="com.ids.forerunner.util.ForerunnerInitializer"/>
    <bean class="org.dozer.spring.DozerBeanMapperFactoryBean">
        <property name="mappingFiles" value="classpath*:/dozer-bean-mappings.xml" />
    </bean>

    <!-- Setup spring to pull in @Controller, @RequestMapping, etc. Configuration 
        scans specified packages for classes configured as Spring managed beans and 
        automatically sets up objects annotated with @Controller, @Service etc. -->
    <context:component-scan base-package="com.ids.forerunner.web" />

    <bean
        class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>

    <!-- Configures view for returning JSON to the client -->
    <bean
        class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"
        p:contentType="text/plain"></bean>

    <!-- maps handler methods based on HTTP paths -->
    <bean
        class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <util:list id="beanList">
                <ref bean="jsonMessageConverter" />
            </util:list>
        </property>
    </bean>
    <!-- Converts JSON to POJO and vice versa -->
    <bean id="jsonMessageConverter"
        class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/pages/" p:suffix=".jsp">
    </bean>

    <bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

<bean id="localeChangeInterceptor"
    class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="lang" />
</bean>

<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="en"/>
</bean>

<bean id="handlerMapping"
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
        <ref bean="localeChangeInterceptor" />
    </property>
</bean>

<bean id="taskList" class="com.forerunner.cronjobs.TaskList">
        <property name="taskList">
            <list>
                <bean name="sessionTask" class="com.forerunner.cronjobs.SessionCronTask"></bean>
            </list>
        </property>
    </bean>
    <bean name="jobDetail" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" value="com.forerunner.cronjobs.ForerunnerCronJob" />
        <property name="jobDataAsMap">
            <map>
                <entry key="taskList" value-ref="taskList" />
            </map>
        </property>
    </bean>

    <bean id="cronTrigger" class="com.forerunner.cronjobs.ForerunnerTrigger">
        <property name="jobDetail" ref="jobDetail" />
    </bean>
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobDetails">
            <list>
                <ref bean="jobDetail" />
            </list>
        </property>

        <property name="triggers">
            <list>
                <ref bean="cronTrigger" />
            </list>
        </property>
    </bean>
</beans>

In the message-webapp-error.properties I have properties as follows :

typeMismatch.command.goal=invalid goal1
typeMismatch.goal=invalid goal2
typeMismatch.java.lang.Integer=invalid goal2
typeMismatch=invalid goal3

Form is posted to this url http:///forerunner/webapp/RouteGradesGoals.html

Can someone please tell me how can I prevent such error and in such scenerios return a valid error message.

1

There are 1 best solutions below

5
On

Configure a MessageSource and provide a message for one of the shown error codes

  • typeMismatch.command.goal
  • typeMismatch.goal
  • typeMismatch.java.lang.Integer
  • typeMismatch

Which provides messages from most specific to least specific.

<bean id="messageSource" class=" org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
</bean>

This MessageSource will load a messages.properties (or locale specific one) from the root of the classpath. Add it and fill it accordingly

typeMismatch.command.goal=The goal needs to be a valid number.
typeMismatch.java.lang.Integer=The given input is not a valid number.

Now with this content for your case the first message will be shown, for other typeMismatch errors on Integer fields the second one will be shown.

For more information on a MessageSource see the reference guide and javadoc. More information on error code generation here.