Spring Form Validation Error: java.lang.IllegalArgumentException: 'items' must not be null

29,928

In you get part, you populate you model, not only with studentForm but also with genderList, gradeList and extraSubjects. And you use all in your jsp.

In the post part, you have a studentForm initialized by the parameters in the request. But your never initialize the lists. So in the JSP, ${gradeList}, ${genderList} and ${extraSubjects} and all null, so the error.

You have to initialize the three lists in addStudent before forwarding to the view if validation fails. You can do that either as proposed by Neil McGuigan, ie by having spring to automatically populate the model, or by populating it yourself. For example, you could have :

void initLists(Model model) {
    LinkedHashMap<Integer, String> gradeList = new LinkedHashMap<Integer, String>();
    gradeList.put(1, "Class 1");
    gradeList.put(2, "Class 2");
    gradeList.put(3, "Class 3");
    gradeList.put(4, "Class 4");
    gradeList.put(5, "Class 5");
    model.addAttribute("gradeList", gradeList);

    List<String> genderList = new ArrayList<String>();
    genderList.add("Male");
    genderList.add("Female");
    model.addAttribute("genderList", genderList);

    List<String> extraSubjects = new ArrayList<String>();
    extraSubjects.add("Math II");
    extraSubjects.add("Population");
    extraSubjects.add("Computer");
    model.addAttribute("extraSubjects", extraSubjects);
}

and call initLists both in addStudentForm and in addStudent. Example code for last :

@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addStudent(
        @Valid @ModelAttribute("studentForm") Student student,
        BindingResult result, Model model) {

    if (result.hasErrors()) {
        logger.info("Returning add page with errors");
        initLists(model);
        return "addstudent";
    }
        //Stuffs to save in database 
    return "redirect:add";
}

Of course, all list initialization should be removed from addStudentForm once you call initLists from there ...

Share:
29,928
Chandra Prakash
Author by

Chandra Prakash

Updated on July 01, 2020

Comments

  • Chandra Prakash
    Chandra Prakash almost 4 years

    I am trying to Validate Spring form which includes:

    1. Normal input fields
    2. Radio buttons whose options are set in controller (later may come from database)
    3. Check box whose options are also set in controller
    4. Select field which is also set in controller

    Method 1 approach is followed.

    Model:

    public class Student {
        private Long id;
    
        @NotEmpty
        private String name;
    
        @NotEmpty
        private String address;
    
        @NotEmpty
        private String contactNumber;
    
        @NotEmpty
        private String grade;
    
        @NotEmpty
        private String gender;
    
        @NotEmpty
        @Email
        private String email;
    
        @NotEmpty
        private List<String> extraSubjects = new ArrayList<String>();
    
        /****  Corresponding getter setters ****/
    
    }
    

    Controller:-

    @Controller
    @RequestMapping("/student")
    public class StudentController {
        private Logger logger = Logger.getLogger(StudentController.class);
    
        @RequestMapping("/home")
        public String getHomePage() {
            return "home";
        }
    
        @RequestMapping(value = "/add", method = RequestMethod.GET)
        public String addStudentForm(Model model) {
            Student student = new Student();
            model.addAttribute("studentForm", student);
    
            LinkedHashMap<Integer, String> gradeList = new LinkedHashMap<Integer, String>();
            gradeList.put(1, "Class 1");
            gradeList.put(2, "Class 2");
            gradeList.put(3, "Class 3");
            gradeList.put(4, "Class 4");
            gradeList.put(5, "Class 5");
            model.addAttribute("gradeList", gradeList);
    
            List<String> genderList = new ArrayList<String>();
            genderList.add("Male");
            genderList.add("Female");
            model.addAttribute("genderList", genderList);
            student.setGender("Male");
    
            List<String> extraSubjects = new ArrayList<String>();
            extraSubjects.add("Math II");
            extraSubjects.add("Population");
    
            List<String> extraSubjectsStd = new ArrayList<String>();
            extraSubjectsStd.add("Math II");
            extraSubjectsStd.add("Population");
            student.setExtraSubjects(extraSubjectsStd);
    
            extraSubjects.add("Computer");
            model.addAttribute("extraSubjects", extraSubjects);
            return "addstudent";
        }
    
        @RequestMapping(value = "/add", method = RequestMethod.POST)
        public String addStudent(
                @Valid @ModelAttribute("studentForm") Student student,
                BindingResult result) {
    
            if (result.hasErrors()) {
                logger.info("Returning add page with errors");
                return "addstudent";
            }
                //Stuffs to save in database 
            return "redirect:add";
        }
    }
    

    JSP Page:-

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
    <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Insert title here</title>
    <style>
    .error {
        color: #ff0000;
    }
    
    .errorblock {
        color: #000;
        background-color: #ffEEEE;
        border: 3px solid #ff0000;
        padding: 8px;
        margin: 16px;
    }
    </style>
    </head>
    <body>
        <form:form action="add" method="post" commandName="studentForm">
            <form:errors path="*" cssClass="errorblock" element="div" />
            <table border="0">
                <tr>
                    <td colspan="3" align="center"><h3>Add Student</h3></td>
                </tr>
                <tr>
                    <td><form:label path="name">
                            <spring:message code="label.studentname" />
                        </form:label></td>
                    <td><form:input path="name" /></td>
                    <td><form:errors path="name" cssClass="error" /></td>
                </tr>
                <tr>
                    <td><form:label path="address">
                            <spring:message code="label.address" />
                        </form:label></td>
                    <td><form:input path="address" /></td>
                    <td><form:errors path="address" cssClass="error" />
                </tr>
                <tr>
                    <td>Contact Number:</td>
                    <td><form:input path="contactNumber" /></td>
                    <td><form:errors path="contactNumber" cssClass="error" />
                </tr>
                <tr>
                    <td><form:label path="grade">
                            <spring:message code="label.grade" />
                        </form:label></td>
                    <td><form:select path="grade">
                            <form:option value="" label="--- Select ---" />
                            <form:options items="${gradeList}" />
                        </form:select></td>
                    <td><form:errors path="grade" cssClass="error" />
                </tr>
                <tr>
                    <td>Gender:</td>
                    <td><form:radiobuttons path="gender" items="${genderList}" />
                    </td>
                    <td><form:errors path="gender" cssClass="error" />
                </tr>
                <tr>
                    <td>Extra Subjects:</td>
                    <td><form:checkboxes items="${extraSubjects}"
                            path="extraSubjects" /></td>
                    <td><form:errors path="extraSubjects" cssClass="error" />
                </tr>
                <tr>
                    <td>Email Address:</td>
                    <td><form:input items="${email}" path="email" /></td>
                    <td><form:errors path="email" cssClass="error" />
                </tr>
                <tr>
                    <td></td>
                    <td align="center"><input type="submit" value="Save" /></td>
                    <td></td>
                </tr>
            </table>
        </form:form>
    </body>
    </html>
    

    Now, When I run my application, the forms get loaded while I perform get operation. The value in the radio buttons, select fields, and checkboxes are loaded and selected as well. If I submit my form with no validation errors it works fine but when I send my form with validation errors, I get following errors:

    StackTrace:-

    Jun 26, 2014 4:32:00 PM org.apache.catalina.core.ApplicationDispatcher invoke
    SEVERE: Servlet.service() for servlet jsp threw exception
    java.lang.IllegalArgumentException: 'items' must not be null
        at org.springframework.util.Assert.notNull(Assert.java:112)
        at org.springframework.web.servlet.tags.form.AbstractMultiCheckedElementTag.setItems(AbstractMultiCheckedElementTag.java:85)
        at org.apache.jsp.WEB_002dINF.pages.addstudent_jsp._jspx_meth_form_005fradiobuttons_005f0(addstudent_jsp.java:810)
        at org.apache.jsp.WEB_002dINF.pages.addstudent_jsp._jspService(addstudent_jsp.java:360)
        at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
        at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
        at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
        at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
        at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
        at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
        at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209)
        at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:266)
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1225)
        at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1012)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
    
    DEBUG org.springframework.web.servlet.DispatcherServlet- Error rendering view [org.springframework.web.servlet.view.JstlView: name 'addstudent'; URL [/WEB-INF/pages/addstudent.jsp]] in DispatcherServlet with name 'mvc-dispatcher'
    org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/pages/addstudent.jsp at line 62
    
    59:             </tr>
    60:             <tr>
    61:                 <td>Gender:</td>
    62:                 <td><form:radiobuttons path="gender" items="${genderList}" />
    63:                 </td>
    64:                 <td><form:errors path="gender" cssClass="error" />
    65:             </tr>    
    
    Stacktrace:
            at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568)
            at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470)
            at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
            at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
            at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
            at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
            at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
            at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209)
            at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:266)
            at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1225)
            at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1012)
            at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
            at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
            at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
            at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
            at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
            at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
            at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
            at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
            at java.lang.Thread.run(Unknown Source)
        Caused by: java.lang.IllegalArgumentException: 'items' must not be null
            at org.springframework.util.Assert.notNull(Assert.java:112)
            at org.springframework.web.servlet.tags.form.AbstractMultiCheckedElementTag.setItems(AbstractMultiCheckedElementTag.java:85)
            at org.apache.jsp.WEB_002dINF.pages.addstudent_jsp._jspx_meth_form_005fradiobuttons_005f0(addstudent_jsp.java:810)
            at org.apache.jsp.WEB_002dINF.pages.addstudent_jsp._jspService(addstudent_jsp.java:360)
            at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
            ... 42 more
        Jun 26, 2014 4:32:00 PM org.apache.catalina.core.StandardWrapperValve invoke
        SEVERE: Servlet.service() for servlet [mvc-dispatcher] in context with path [/sms] threw exception [An exception occurred processing JSP page /WEB-INF/pages/addstudent.jsp at line 62
    
        59:             </tr>
        60:             <tr>
        61:                 <td>Gender:</td>
        62:                 <td><form:radiobuttons path="gender" items="${genderList}" />
        63:                 </td>
        64:                 <td><form:errors path="gender" cssClass="error" />
        65:             </tr>
    
    
        Stacktrace:] with root cause
        java.lang.IllegalArgumentException: 'items' must not be null
            at org.springframework.util.Assert.notNull(Assert.java:112)
            at org.springframework.web.servlet.tags.form.AbstractMultiCheckedElementTag.setItems(AbstractMultiCheckedElementTag.java:85)
            at org.apache.jsp.WEB_002dINF.pages.addstudent_jsp._jspx_meth_form_005fradiobuttons_005f0(addstudent_jsp.java:810)
            at org.apache.jsp.WEB_002dINF.pages.addstudent_jsp._jspService(addstudent_jsp.java:360)
            at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
            at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
            at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
            at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:486)
            at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
            at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
            at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:209)
            at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:266)
            at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1225)
            at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1012)
            at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
            at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
            at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:931)
            at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:833)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
            at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:807)
            at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
            at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
            at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
            at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
            at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
            at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
            at java.lang.Thread.run(Unknown Source)
    

    I am able to figure out that the List that I have used for specifying genders, gradeList, extraSubjects are appear to be NULL after post request.

    • How can I render those values again in form after post if validation fails?
    • Should I have to set the value in lists on POST method too as in GET method?