Using Spring 3.1. I’ve got a form that populates a POJO stored in a DB. However, this POJO also has an instance of another POJO in it:
class Job {
private id;
private Filter filter;
//getters and setters
}
and the Filter class:
class Filter {
private id;
private name;
//getters and setters
}
So on the form that populates the Job object I’m trying to display the Filter objects in a select object. All of that part seems to work properly. The problem comes in when I try to edit a Job object that already has a Filter. The select object is not automatically setting itself to the corresponding Filter object associated with the job. Wondering if someone can let me know what I’m screwing up. Here is the JSP:
<%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s"%>
<div align="center">
<s:url value="/job" var="jobPost_url"/>
<s:url value="/job/provData" var="provData_url"/>
<sf:form method="POST" modelAttribute="job" dojoType="dijit.form.Form" action="${jobPost_url}">
<script type="dojo/method" event="onSubmit">
if (!this.validate()) {
return false;
}
return true;
</script>
<sf:hidden path="id" />
<table>
<tr><td align="right">Customer:</td><td>
<sf:input path="customer" dojoType="dijit.form.ValidationTextBox" trim="true" required="true"/><br/>
<sf:errors path="customer" cssClass="error"/>
</td></tr>
<tr><td align="right">Project:</td><td>
<sf:input path="project" dojoType="dijit.form.ValidationTextBox" trim="true" required="true"/><br/>
<sf:errors path="project" cssClass="error"/>
</td></tr>
<tr><td align="right">Date:</td><td>
<sf:input path="date" dojoType="dijit.form.DateTextBox" required="true"
constraints="{datePattern:'MMM d, y'}" /><br/>
<sf:errors path="date" cssClass="error"/>
</td></tr>
<tr><td align="right">Filter:</td><td><sf:select id="filter" path="filter" items="${filters}" itemValue="id"
itemLabel="programName"/></td>
</tr>
<tr><td colspan="2" align="right">
<button dojoType="dijit.form.Button" type="submit">Submit</button>
<button dojoType="dijit.form.Button" id="testButton">Test</button>
</td></tr>
</table>
</sf:form>
</div>
And here is the Controller (or at least the relevant parts):
@Controller
public class JobController {
@Autowired
private JobService jobService;
@Autowired
private ProvisionService provisionService;
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new DatePropertyEditor());
binder.registerCustomEditor(Provision.class, new ProvisionEditor(provisionService));
}
@ModelAttribute("filters")
@RequestMapping(value="/job", method=RequestMethod.GET)
public List<Provision> showJobForm(Model model) {
model.addAttribute(new Job());
return provisionService.getAll();
}
@RequestMapping(value="/job", method=RequestMethod.POST)
public String submitJobForm(@Valid Job job, BindingResult bindingResult) {
if(bindingResult.hasErrors())
return "job";
job.setStatus("Running");
JobManager.AddJob(job);
jobService.save(job);
return "redirect:/";
}
@RequestMapping(value="/job/edit", method=RequestMethod.POST)
public String editJob(@RequestParam("jobHiddenList") String list, Model model) {
log.info("Edit List: " + list);
Job job = jobService.getById(Long.valueOf(list.trim()));
model.addAttribute("job", job);
model.addAttribute("filters", provisionService.getAll());
return "job";
}
}
And the ProvisionEditor needed for converting the Provision from the select’s ID to a Provision:
public class ProvisionEditor extends PropertyEditorSupport {
private ProvisionService provisionService;
public ProvisionEditor(ProvisionService provisionService) {
this.provisionService = provisionService;
}
public void setAsText(String value) {
long provisionId = Long.parseLong(value);
Provision p = provisionService.getById(provisionId);
setValue(p);
}
}
So, as I said, things work fine when creating a new Job. The list of Provisions get loaded into the select, everything gets assigned correctly and stored correctly in the DB. However, when a user selects a provison later and edits it, it brings them to the same form and all the data loads in correctly except for the Provision select. It loads the list of provisions in, but it doesn’t select the correct one. Any ideas how I can fix this? Thanks.
Turns out the problem was that I did not override Equals and Hashcode for the objects. After solving another proble I came across the issue, fixed it, and everything started working as it should. It’s made especially easy because I use Eclipse and it has automatic generation of overriding both of those methods.