How to debug NumberFormatException somewhere in Ba

2019-08-17 06:43发布

问题:

A am new to SpringFramework. I have created a controller which extends SimpleFormController. I have also created a command class which have a few String fields and two List<String> fields.

The form is located on a PHP generated page and was previously procesed by PHP. I am trying to move that processing to Java, as this part of application is generating large spreadsheets, which PHP just can't handle any more.

Anyway, The form does not contain any numeric fields. Still, when I submit the form I get the NumberFormatException:

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NumberFormatException: For input string: ""
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
root cause

java.lang.NumberFormatException: For input string: ""
    java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    java.lang.Integer.parseInt(Integer.java:504)
    java.lang.Integer.parseInt(Integer.java:527)
    org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:991)
    org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:924)
    org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
    org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:692)
    org.springframework.validation.DataBinder.doBind(DataBinder.java:588)
    org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:191)
    org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:112)
    org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:394)
    org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:266)
    org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)

The stack trace does not contain any of my classes and I have no idea how to debug it.

Here is my command class:

public class ExportCommand {
    private String ifs_login;
    private String exp_sales_price_group_id_sp_ip_pl;
    private List<String> exp_catalog_group;
    private List<String> exp_vendor_no_pps;
    private String exp_price_list_no_pl;
    private String exp_contract;
    private String exp_language_code_spl;
    private String exp_active_ind_sp = ""; //those are checkboxes with "Y" as checked value, so I initialize them to empty strings if they are unchecked. 
    private String exp_desc = "";
    private String exp_customs = "";
    private String exp_ordered = "";

//here goes default getters and setters
}

Here is my form as it is seen in Chrome Developer Tools:

ifs_test:MAGE
exp_sales_price_group_id_sp_ip_pl:MOLEX
exp_catalog_group[]:
exp_price_list_no_pl:MOLEX
exp_contract:VER
exp_language_code_spl:

... along with it's source form:

ifs_test=MAGE&exp_sales_price_group_id_sp_ip_pl=MOLEX&exp_catalog_group%5B%5D=&exp_price_list_no_pl=MOLEX&exp_contract=VER&exp_language_code_spl=

EDIT:

My controller looks like this:

public class ExportController extends org.springframework.web.servlet.mvc.SimpleFormController {

    @Override
    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
         //....
    }
}

What am I doing wrong?

回答1:

I have found an answer. The problem was that I have tried to directly use the PHP form without any modifications. PHP handles arrays of data in forms only if they have [] suffix in the name of the input or select box. They of course can have indices in the square bracket like field[1] or field[some_text_index], but usually the brackets are left blank and that was my case.

It seems that Spring tried to map 'exp_catalog_group[]' field name to name of the List<String> exp_catalog_group field, and was trying to extract the index from the sqare brackets. This index should be Integer for List, but it was empty string.

I had to change the <select> name on the PHP part of the system to just exp_catalog_group and it is working now.

Stupid beginners mistake :)



回答2:

You're getting a NumberFormatException trying to turn the empty string "" into an Integer. Set a breakpoint on throwing the exception and walk up the stack trace to see what's being attempted to be set. In particular, the stack variables for BeanWrapperImpl will probably tell you what target property is being processed when the exception occurs.

Most likely, you're having Spring attempt to automatically adapt some data format that includes a String onto something whose corresponding field is of type Integer, and it's missing, either as a bug or as an optional value. What's the signature of the controller method that you're trying to access when this error occurs?