I am trying to Validate Spring
form which includes:
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
.
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 ...