I have a Spring Boot 1.3 app that uses Thymeleaf on the HTML. I have page of users and when I edit them, I would like the user institution selected from a list. I have the window showing everything properly, but when I select the institution, the controller does not show the selected value.
Here is my HTML:
<div class="form-group">
<label class="col-md-3 control-label">Institution</label>
<div class="col-md-5">
<div th:if="${institutionList != null and not #lists.isEmpty(institutionList)}">
<select>
<option th:each="dropDownItem : ${institutionList}"
th:value="${dropDownItem.name}"
th:text="${dropDownItem.name}" />
</select>
</div>
<div th:if="${institutionList == null or lists.isEmpty(institutionList)}">
<div>"No Institutions were found, please create some first"</div>
</div>
</div>
</div>
And here is my controller
@Controller
@PreAuthorize("hasRole('Admin')")
@RequestMapping("/admin")
public class AdminController {
@Transactional
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping(value = "/addUser", method = RequestMethod.POST)
public String checkPersonInfo(@ModelAttribute User user, Model model, Authentication authentication) {
// user does not have the selected institution set
customUserDetailsService.createNewUser(user);
updateModelWithAllUsers(model);
return "admin";
}
private void updateModelWithAllUsers(Model model) {
model.addAttribute(USERLIST, customUserDetailsService.findAllUsers());
model.addAttribute(INSTITUTION_LIST, institutionService.findAll());
model.addAttribute("user", new User());
}
...
}
Here is my User:
@Entity
@Table(name = "Users")
public class User implements UserDetails {
@Id
private String username;
@Column(nullable = false)
private String password;
private boolean enabled;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
private String companyName;
private String email;
@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name="Authorities", joinColumns=@JoinColumn(name="username"))
@Column(name="authority")
private Set<String> roles = new HashSet<String>();
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "institutionId", nullable = false)
private Institution institution;
... getters & setters
}
And my Institution:
@Entity
@Table(name = "Institution")
public class Institution {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long institutionId;
private String name;
@OneToMany(mappedBy = "institution", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
List<User> users = new ArrayList<User>();
... getters & setters
}
When the "/addUser" gets the User object from the UI, the institution is null.
EDIT
I used Sergios suggestion to use select th:field="${user.institution}" as well as select th:field="*{institution}"
but that gives me an error:
org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'user' on field 'institution': rejected value [com.security.Institution@3e3945d2]; codes [typeMismatch.user.institution,typeMismatch.institution,typeMismatch.com. .security.Institution,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.institution,institution]; arguments []; default message [institution]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.security.Institution' for property 'institution'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.lang.Long for value 'com.security.Institution@3e3945d2'; nested exception is java.lang.NumberFormatException: For input string: "com. .security.Institution@3e3945d2"]
Not sure if I am reading this correctly, but does that mean Thymeleaf is trying to pass the Institution.name to the user.institution field?
Can anyone offer any advice on how to do this?