Spring Form hidden value is lost on submit - spring-mvc

On my 'update user' page I have a hidden field to hold the ID of the current user being edited. I've checked the HTML source and the value populates correctly. However when I submit the form, the userID value ALWAYS comes through as 0 while every other field comes through correctly.
-I've tried setting the type as form:input and submitting it, still 0 on the controller side.
-There are no bindingresult errors.
-Page URL: /admin/update-user.html?uid=3 (I've tried changing the URL variable from uid to userID, no difference.)
So what the heck is going on?! Am I missing something obvious??
JSTL
<form:form commandName="user" method="POST">
<form:hidden path="userID"/>
<table width="400" cellpadding="3" cellspacing="0" border="0" class="datatable">
<tr>
<td>User ID #</td>
<td>${user.userID}</td>
</tr>
<tr>
<td valign="top">Password</td>
<td>****<br />Change Password</td>
</tr>
<tr>
<td>First Name</td>
<td><form:input path="firstName" /></td>
</tr>
<tr>
<td>Last Name</td>
<td><form:input path="lastName" /></td>
</tr>
<tr>
<td>Gender: </td>
<td>
<form:select path="gender">
<form:option value="Male" label="Male" />
<form:option value="Female" label="Female" />
</form:select>
</td>
</tr>
<tr>
<td>Birthday: </td>
<td><form:input path="birthday" id="datepickerpast" readonly="true" /></td>
</tr>
<tr>
<td>Email</td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Update" /> <input type="reset"></td>
</tr>
</table>
</form:form>
Controller
#RequestMapping(value = "admin/update-user", method = RequestMethod.POST)
public String processUpdateUser(ModelMap model, #ModelAttribute("user") User user, BindingResult result) throws SQLException {
if (result.hasErrors()) {
model.addAttribute("user", user);
model.addAttribute("pagetitle", "Admin - Update User Details");
return "admin/users/update-user";
} else {
userDao.updateUser(user);
return "redirect:/admin/user-management.html";
}
}
Object Properties with appropriate getters/setters
private int userID;
private String firstName;
private String lastName;
private String username;
private String email;
private Date birthday;
private String gender;

Realized my getter was type Integer but my setter and property was type int. Made all of them Integer and it worked. If someone can explain why there was no error on compile or why it didn't work the way it was, that'd be greatly appreciated.
Sigh, there goes 3 hours of my life.

You got a compiler error because of autoboxing, which allows for the automatic conversion of primitives to their wrapper class alternatives. As to why it didn't work when the getter was using Integer, I can't help you there.

Related

spring MVC form:radiobutton typical usage not working

here is the addVariable.jsp
<h3>Add Process Variable</h3>
<br>
<form:form action="/cpms/vrms/add" commandName="processVariable">
<table>
<tr>
<td>Variable Name </td>
<td><form:input path="variableName" /></td>
</tr>
<tr>
<td>Symbol </td>
<td><form:input path="symbol" /></td>
</tr>
<tr>
<td>Description </td>
<td><form:textarea path="variableDescription" rows="3" cols="20" /></td>
</tr>
<tr>
<td>Unit</td>
<td><form:input path="unit" /></td>
</tr>
<tr>
<td>Type</td>
<td>
<form:radiobuttons path="dataType" items="${dataTypes}"/>
</td>
</tr>
<tr>
<td>Source</td>
<td><form:radiobuttons path="source" items="${sourceList}"/></td>
</tr>
<tr>
<td>Is Input?</td>
<td>
<form:radiobuttons path="input" value="true" />
<form:radiobuttons path="input" value="false" />
</td>
</tr>
<tr>
<td>Is Constant?</td>
<td>
<form:radiobuttons path="constant" value="true"/> Yes
<form:radiobuttons path="constant" value="false"/> No
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add Variable" />
</td>
</tr>
</table>
The VariableManagementController
public class VariableManagementController {
#Autowired
private IVariableManagementService variableManagementService;
private static final String ADD_FORM_PATH="cpms/vrms/addVariable";
#RequestMapping(value="/cpms/vrms/add/form",method=RequestMethod.GET)
String addProcessVariable(Model model){
DATA_TYPE[] dataTypes = DATA_TYPE.values();
SOURCE[] sourceList = SOURCE.values();
model.addAttribute("dataTypes",dataTypes);
model.addAttribute("sourceList",sourceList);
model.addAttribute("processVariable", new ProcessVariable());
return ADD_FORM_PATH;
}
The ProcessVariable bean
public class ProcessVariable {
private String variableId;
private String variableName;
private String variableDescription;
private String symbol;
private String unit;
private DATA_TYPE dataType;
private SOURCE source;
private boolean constant; //if isConstant=true then isOutput must be false
private boolean input;
//getters and setters
When i hit a link with target http://localhost:9090/wcc/cpms/vrms/add/form i get following exception.
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/jsp/cpms/vrms/addVariable.jsp at line 46
43: <tr>
44: <td>Is Input?</td>
45: <td>
46: <form:radiobuttons path="input" value="true" />
47: <form:radiobuttons path="input" value="false" />
48: </td>
49: </tr>
.
.
.
root cause
java.lang.IllegalArgumentException: Attribute 'items' is required and must be a Collection, an Array or a Map
I dont want to add an attribute in my model from within the controller for boolean values. It should have worked like this. I am using spring mvc 3.1.2
I dont think so using items=${inputTypes} is mandatory. i can simply use hardcoded values for my boolean values
If you are not using a list use
<form:radiobutton />
eg.
<form:radiobutton path="sex" value="M"/>Male
<form:radiobutton path="sex" value="F"/>Female
Here is a post explaning something similar:
http://www.mkyong.com/spring-mvc/spring-mvc-radiobutton-and-radiobuttons-example/

Neither BindingResult Nor Plain Target Object For Bean Name ‘Xxx’ Available As Request Attribute

I am getting this error, while trying to configure the spring controllers. I am sure that I have the name correctly matching and it still gives me this error. Here is my controller class. Also the input and output page are same. please help me
"Neither BindingResult nor plain target object for bean name 'userForm' available as request attribute"
#Controller
#SessionAttributes
public class UserController {
protected Log logger = LogFactory.getLog(getClass());
#Autowired
UserService userService;
#RequestMapping(value="/userList")
public ModelAndView getUserList(){
List<User> userList = userService.getUserList();
return new ModelAndView("userList", "userList", userList);
}
#RequestMapping(value="/findUser")
public ModelAndView findUser(#ModelAttribute("user") User user,
BindingResult result){
List<User> userResultsList = null;
//model.addAttribute("user", new User());
userResultsList = userService.findUser(user.getUsername(), user.getFirstname(),
user.getLastname());
return new ModelAndView("userList", "user", userResultsList);
}
}
And my JSP is here
<body>
<form:form modelAttribute="user" method="post" action="/findUser.html">
<table>
<tr>
<td><form:label path="username">User ID:</form:label></td>
<td><form:input path="username" /></td>
</tr>
<tr>
<td><form:label path="firstname">First Name</form:label></td>
<td><form:input path="firstname" /></td>
</tr>
<tr>
<td><form:label path="lastname">Last Name:</form:label></td>
<td><form:input path="lastname" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="findUser" /></td>
</tr>
</table>
</form:form>
<table>
<tr>
<td>User Id</td>
<td>First Name</td>
<td>Last Name</td>
<td>Email Address</td>
<td>Last Update Date</td>
<td>Last Update By</td>
</tr>
<c:forEach var="list" items="${userList}">
<tr>
<td>${list.userId}</td>
<td>${list.username}</td>
<td>${list.firstname}</td>
<td>${list.lastname}</td>
<td>${list.email}</td>
<td>${list.lastUpdatedBy}</td>
<td>${list.lastUpdatedDate}</td>
<td>assignVendor</td>
</tr>
</c:forEach>
</table>
Try to add following line to your public ModelAndView getUserList() method:
modelAndView.addObject("user", new User());
In your JSP you are using two model attributes, named "user" and "userList", which are basically properties of the MODEL object.
When you first come to the page, Spring will try to find the property values with names "user" and "userList" from the Model object (the M in MVC). So you need to set the property values for "user" and "userList" before showing the page to the user (typically from within the method that takes the user to the JSP page), and in your case you can do that by changing the "getUSerList" method as follows:
#RequestMapping(value="/userList")
public ModelAndView getUserList(){
ModelAndView model = new ModelAndView("userList");
User user=new User();
List<User> userList = userService.getUserList();
model.addObject("user",user);
model.addObject("userList",userList);
return model;
}
Now this method will take you to the "userList" JSP, with your MODEL populated with "user" and "userList" attribute values.

Spring 3.2 MVC -- validation errors not appearing

I am trying to run a validator class for my Spring form, but my errors are not showing up on my page. I'm a newbie when it comes to Spring validation, so there are undoubtedly some errors here. Here is my form. (Incidentally, Eclipse is posting warnings on the form:error lines that say, "List is a raw type. References to generic type List should be parameterized.")
<form:form commandName="bulletin" method="post" action="processBulletin">
<table>
<tr>
<td>Name:</td>
<td><form:errors path="name" /></td>
<td><form:input path="name" maxlength="30" /></td>
</tr>
<tr>
<td>Subject:</td>
<td><form:errors path="subject" /></td>
<td><form:input path="subject" maxlength="50" /></td>
</tr>
<tr>
<td valign="top">Message:</td>
<td><form:errors path="note" /></td>
<td><form:textarea path="note" cols="70" rows="20" /></td>
</tr>
<tr>
<td><input type="submit" /></td>
<td> </td>
</tr>
</table>
</form:form>
Here is my controller class. I'm calling the validation class from here, and I'm not sure if that's the right thing to do, so feel free to say so if it's not.
#RequestMapping(value = "/processBulletin", method = RequestMethod.POST)
public String processBulletin(
#ModelAttribute("bulletin") Bulletin bulletin, BindingResult result) {
final BindException errors = new BindException(bulletin, "bulletin");
bulletinValidator.validate(bulletin, errors);
if (errors.hasErrors()) {
return "redirect:/approvedBulletins";
} else {
// rest of method
}
return "redirect:/approvedBulletins";
}
Here is my validation class.
#Override
public boolean supports(Class<?> cls) {
return Bulletin.class.isAssignableFrom(cls);
}
#Override
public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "subject", "Subject is required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "Name is required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "note", "Message is required");
}
}
Try to return view name instead of redirect return "redirect:/approvedBulletins"; when you have errors.

How to do the Hibernate validation on the nested list objects?

I need to validate the objects which are stored in the list on my form bean object.
Below is my form bean object.
public class Role implements java.io.Serializable {
// Fields
private int roleId;
#NotBlank
private String roleName;
private boolean active;
#Valid
private List<Module> modules;
// getters anfd setters
}
and below is my object which is present in the list of my main form bean object
public class Module implements Serializable {
private int id;
#NotBlank
private String moduleName;
// other properties and getters and setters
}
Below is my properties file
# -- Role form --
NotBlank.role.roleName=Role Name can not be blank.
NotBlank.module.moduleName=Module Name can not be blank.
Below is My JSP page, the form consists of a role name and modules which can be added to the role.
<table border="0" class="section_tbl2">
<tr>
<td width="150px" valign="top">
<spring:message code="dmx.role.form.label.name"/>
</td>
<td width="10px">:</td>
<td>
<form:input class="txtinput" id="roleName" path="roleName" maxlength="50"/> <form:errors path="roleName" cssClass="error"/>
</td>
</tr>
<tr><td colspan="3" height="8px"></td></tr>
<tr>
<td width="150px" vAlign="top">
Modules
</td>
<td width="10px" vAlign="top">:</td>
<td>
<table>
<tr>
<td>
<input type="button" value="<spring:message code="dmx.role.form.button.addModule.label"/>" onclick="return addModuleRow();"></input>
</td>
</tr>
<tr><td> </td></tr>
</table>
<table cellpadding="0" cellspacing="0" border="0" class="tblstyle1" id="moduleTable">
<thead>
<tr>
<th class="fst" width="200px">
<spring:message code="dmx.role.form.label.moduleName"/>
</th>
<th width="50px"><spring:message code="dmx.role.form.label.create"/></th>
<th width="50px"><spring:message code="dmx.role.form.label.update"/></th>
<th width="50px"><spring:message code="dmx.role.form.label.delete"/></th>
<th width="30px"></th>
</tr>
</thead>
<tbody id="moduleTBody">
<c:forEach items="${role.modules}" var="module" varStatus="status" >
<c:set var="moduleCounter" value="${status.index}"/>
<tr id="moduleRowId_${moduleCounter}">
<td class="fst txt-center">
<form:select onchange="checkIfThisModuleAlreadySelected(this);" class="seloption" id="selectedModule_${moduleCounter}" path="modules[${moduleCounter}].id">
<form:option value="" label="-- Select Module --"/>
<form:options items="${moduleList}" itemLabel="moduleName" itemValue="id" />
</form:select>
</td>
<td class="txt-center">
<form:checkbox id="create_${moduleCounter}" path="modules[${moduleCounter}].create"/>
</td>
<td class="txt-center">
<form:checkbox id="update_${moduleCounter}" path="modules[${moduleCounter}].update"/>
</td>
<td class="txt-center">
<form:checkbox id="delete_${moduleCounter}" path="modules[${moduleCounter}].delete"/>
<td class="txt-center">
<input class="delbtn" id="moduleDelBtn_${moduleCounter}" name="moduleDelBtn[${moduleCounter}]" type="button" onclick="delModuleRow(${moduleCounter});">
</td>
</tr>
</c:forEach>
</tbody>
</table>
</td>
</tr>
<tr><td colspan="3" height="3px"></td></tr>
</table>
I can successfully validate the role name i.e. when role name is blank I get an error message but when module is not selected i do not get any error message.
Please help
Adding #NotNull and #Size constraints to your module list should help:
#Valid
#NotNull
#Size(min = 1)
private List<Module> modules;
The #Valid annotation causes the elements of the annotated collection to be validated but it doesn't validate wether that collection is not null or contains any elements.

How to pass the entire object from jsp to spring controller

I am new to Spring MVC and hope someone can help me figure out this issue. I have jsp like this:
<table border="1">
<tr>
<td width="50">Id</td>
<td width="150">First Name</td>
<td width="150">Last Name</td>
<td width="50">Money</td>
<td width="50"></td>
</tr>
<c:forEach items="${persons}" var="person">
<tr>
<td><c:out value="${person.id}" /></td>
<td><c:out value="${person.firstName}" /></td>
<td><c:out value="${person.lastName}" /></td>
<td><c:out value="${person.money}" /></td>
<td colspan="2"> Delete</td>
</tr>
</c:forEach>
</table>
When user clicks on the Delete link, I want to pass the entire object (person) to the controller. Can someone please help how would I do that? I will appreciate any help.
This is my controller:
#RequestMapping(value = "/removeContact", method = RequestMethod.GET)
public String removeContact(#ModelAttribute("contact")Person person, BindingResult result) {
System.out.println("============ > "+person.getId());
return "index.jsp";
}
Thanks
First, don't use permit delete operation on GET requests. Use DELETE instead, it's more appropriate. If you use jquery, use the ajax function to submit your data to the controller.

Resources