Spring Form Validation Error: java.lang.IllegalArgumentException: 'items' must not be null
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 ...
Chandra Prakash
Updated on July 01, 2020Comments
-
Chandra Prakash almost 4 years
I am trying to
Validate Spring
form which includes:- Normal input fields
- Radio buttons whose options are set in controller (later may come from database)
- Check box whose options are also set in controller
- 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 theradio buttons, select fields, and checkboxes are loaded
and selected as well. If Isubmit my form with no validation errors it works fine
but when I send my formwith 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 forspecifying genders, gradeList, extraSubjects
are appear to beNULL 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?