A "teacher" can have several assigned "subjects" to teach:
public class Teacher {
private int id;
private String firstName;
private String lastName;
...
private List<Subject> subjects;
}
In HTML view user can select one ore more subjects for the teacher and send POST request:
<select class="form-control" id="subjects" name="subjects" size="5" multiple required>
<option th:each="subject: ${allSubjects}"
th:value="${subject.id}"
th:text="${subject.name}"
th:selected="${teacher.subjects.contains(subject)}">
</option>
</select>
Controller to process this request:
@PostMapping("/update")
public String update(@ModelAttribute("teacher") Teacher teacher) {
logger.debug("Received update data: {}", teacher);
teacherService.update(teacher);
return "redirect:/teachers";
}
Here is the POST request that is being passed:
I expect Spring to take subject.id`s and inject them into teacher as list of subjects. But I get exception:
BindException
org.springframework.validation.BeanPropertyBindingResult:
1 errors Field error in object 'teacher' on field 'subjects': rejected value [2,4]; codes [typeMismatch.teacher.subjects,typeMismatch.subjects,typeMismatch.java.util.List,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [teacher.subjects,subjects];
arguments []; default message [subjects]]; default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'subjects'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'ua.com.foxminded.university.model.Subject' for property 'subjects[0]': no matching editors or conversion strategy found]
I carefully read first 50 google results for my question, code should work, but it doesn't. I must be missing something.
First of all wrong annotation - u dont use @ModelAttribute
inside of the post but rather @RequestBody
which is implicit in spring controllers for post.
Other than that what you are sending is not a teacher entity but rather teacherDTO which wont have all the fields (collections) that teacher entity that you showed has. That means you should be receiving a different class (TeacherDTO) and then convert it correctly to teacher entity which you then update in the database
i suppose this is an update form, so it take an object teacher as an input. try this
<form th:object="${teacher}" method="post">
<select class="form-control" th:field="*{subjects}" id="subjects" name="subjects" size="5" multiple required>
<option th:each="subject: ${allSubjects}"
th:value="${subject.id}"
th:text="${subject.name}"
th:selected="*{subjects.contains(subject)}">
</option>
</select>
</form>
Finally I found the solution while working on another part of my project. I tried to pass Lecture object to controller, Lecture contains List of student groups. Each group has 2 fields: id and name. First we implement a formatter
public class GroupFormatter implements Formatter<Group> {
@Override
public Group parse(String text, Locale locale) throws ParseException {
Group group=new Group();
if (text != null) {
String[] parts = text.split(",");
group.setId(Integer.parseInt(parts[0]));
if(parts.length>1) {
group.setName(parts[1]);
}
}
return group;
}
@Override
public String print(Group group, Locale locale) {
return group.toString();
}
}
Register formatter in MVCConfig
@Override
public void addFormatters(FormatterRegistry registry) {
GroupFormatter groupFormatter=new GroupFormatter();
registry.addFormatter(groupFormatter);
}
And we get the correct format from POST request:
groups=[4:VM-08, 5:QWE-123]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.