I have downloaded a working demo which working perfectly fine while I ran it. But when I have just made my way and I am using same page and functionality with registration page and then I submitting the form I am getting error:
[Field error in object 'user' on field 'userProfiles': rejected value [3]; codes [typeMismatch.user.userProfiles,typeMismatch.userProfiles,typeMismatch.java.util.Set,typeMismatch]; arguments
[org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.userProfiles,userProfiles]; arguments []; default message [userProfiles]]; default message
[Failed to convert property value of type 'java.lang.String' to required type 'java.util.Set' for property 'userProfiles'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type
[com.idev.tpt.model.UserProfile] for property 'userProfiles[0]': no matching editors or conversion strategy found]]
JSP File:
<form:form id="userForm" action="newuser" modelAttribute="user">
<form:input type="hidden" path="id" id="id" />
<div class="form-group">
<form:input type="text" path="firstName" id="firstName" placeholder="First Name" class="form-control input-sm" />
</div>
<div class="form-group">
<form:input type="text" path="lastName" id="lastName" placeholder="Last Name" class="form-control input-sm" />
</div>
<div class="form-group">
<c:choose>
<c:when test="${edit}">
<form:input type="text" path="ssoId" id="ssoId" placeholder="SSO ID" class="form-control input-sm" disabled="true" />
</c:when>
<c:otherwise>
<form:input type="text" path="ssoId" id="ssoId" placeholder="SSO ID" class="form-control input-sm" />
<div class="has-error">
<form:errors path="ssoId" class="help-inline" />
</div>
</c:otherwise>
</c:choose>
</div>
<div class="form-group">
<form:input type="password" path="password" id="password" placeholder="password" class="form-control input-sm" />
<div class="has-error">
<form:errors path="password" class="help-inline" />
</div>
</div>
<div class="form-group">
<form:input type="text" path="email" id="email" placeholder="email" class="form-control input-sm" />
<div class="has-error">
<form:errors path="email" class="help-inline" />
</div>
</div>
<div class="form-group">
<form:select path="userProfiles" items="${roles}" multiple="true" itemValue="id" itemLabel="type" class="form-control input-sm" />
</div>
<!-- <div class="form-group">
<textarea class="form-control" id="prop_note" name="note" placeholder="Note" ></textarea>
</div> -->
<p class="demo-button btn-toolbar">
<span id="warningLbl" class="label label-warning" style="display: none;"></span>
<button id="propAddBtn" type="submit" class="btn btn-primary pull-right">Save</button>
<button id="propUpdateBtn" type="submit" class="btn btn-primary pull-right" style="display: none;">Update</button>
<button id="propClearBtn" type="button" class="btn btn-primary pull-right" style="display: none;">Clear</button>
</p>
<br>
</form:form>
controller:
@RequestMapping(value = { "/newuser" }, method = RequestMethod.GET)
public String newUser(ModelMap model) {
User user = new User();
model.addAttribute("user", user);
model.addAttribute("edit", false);
model.addAttribute("roles", userProfileService.findAll());
model.addAttribute("loggedinuser", getPrincipal());
return "registration";
}
/**
* This method will be called on form submission, handling POST request for
* saving user in database. It also validates the user input
*/
@RequestMapping(value = { "/newuser" }, method = RequestMethod.POST)
public String saveUser(@Valid User user, BindingResult result,
ModelMap model) {
if (result.hasErrors()) {
return "registration";
}
if(!userService.isUserSSOUnique(user.getId(), user.getSsoId())){
FieldError ssoError =new FieldError("user","ssoId",messageSource.getMessage("non.unique.ssoId", new String[]{user.getSsoId()}, Locale.getDefault()));
result.addError(ssoError);
return "registration";
}
userService.saveUser(user);
model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " registered successfully");
model.addAttribute("loggedinuser", getPrincipal());
//return "success";
return "registrationsuccess";
}
Model :
package com.websystique.springmvc.model;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.validator.constraints.NotEmpty;
@SuppressWarnings("serial")
@Entity
@Table(name="APP_USER")
public class User implements Serializable{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@NotEmpty
@Column(name="SSO_ID", unique=true, nullable=false)
private String ssoId;
@NotEmpty
@Column(name="PASSWORD", nullable=false)
private String password;
@NotEmpty
@Column(name="FIRST_NAME", nullable=false)
private String firstName;
@NotEmpty
@Column(name="LAST_NAME", nullable=false)
private String lastName;
@NotEmpty
@Column(name="EMAIL", nullable=false)
private String email;
@NotEmpty
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "APP_USER_USER_PROFILE",
joinColumns = { @JoinColumn(name = "USER_ID") },
inverseJoinColumns = { @JoinColumn(name = "USER_PROFILE_ID") })
private Set<UserProfile> userProfiles = new HashSet<UserProfile>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSsoId() {
return ssoId;
}
public void setSsoId(String ssoId) {
this.ssoId = ssoId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Set<UserProfile> getUserProfiles() {
return userProfiles;
}
public void setUserProfiles(Set<UserProfile> userProfiles) {
this.userProfiles = userProfiles;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((ssoId == null) ? 0 : ssoId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof User))
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (ssoId == null) {
if (other.ssoId != null)
return false;
} else if (!ssoId.equals(other.ssoId))
return false;
return true;
}
/*
* DO-NOT-INCLUDE passwords in toString function.
* It is done here just for convenience purpose.
*/
@Override
public String toString() {
return "User [id=" + id + ", ssoId=" + ssoId + ", password=" + password
+ ", firstName=" + firstName + ", lastName=" + lastName
+ ", email=" + email + "]";
}
}
I am also using the same model provided in the demo. I didn't change anything in the model also not change related to jsp and controller. I don't understand why I am getting an error I am using the same way as like in a demo.
User profile
package com.websystique.springmvc.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@SuppressWarnings("serial")
@Entity
@Table(name="USER_PROFILE")
public class UserProfile implements Serializable{
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@Column(name="TYPE", length=15, unique=true, nullable=false)
private String type = UserProfileType.USER.getUserProfileType();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof UserProfile))
return false;
UserProfile other = (UserProfile) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
@Override
public String toString() {
return "UserProfile [id=" + id + ", type=" + type + "]";
}
}
user profile converter
package com.websystique.springmvc.converter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import com.websystique.springmvc.model.UserProfile;
import com.websystique.springmvc.service.UserProfileService;
/**
* A converter class used in views to map id's to actual userProfile objects.
*/
@Component
public class RoleToUserProfileConverter implements Converter<Object, UserProfile>{
static final Logger logger = LoggerFactory.getLogger(RoleToUserProfileConverter.class);
@Autowired
UserProfileService userProfileService;
/**
* Gets UserProfile by Id
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
*/
public UserProfile convert(Object element) {
Integer id = Integer.parseInt((String)element);
UserProfile profile= userProfileService.findById(id);
logger.info("Profile : {}",profile);
return profile;
}
}
Updated
one more thing while I printing the form data using model getter method getUserProfiles() I am getting blank data so I think it's not binding the selected value.but any other column I am printing it will perfectly bind.
After your comment I updated my reply:
Probably the problem is in JSP code. When application invokes the saveUser()
method in your controller, a new User object is created. But because you have UserProfile
type in User object the application has to know how to create UserProfile
from String (when passed from <form:select path="userProfiles">
).
Either you add a custom converter from String to UserProfile
or create an UserDTO
class with Java standard types and use it in your Controller save operation. Code will be something similar to:
public String saveUser(@Valid UserDTO dto, ...) {
User user = createUserFromDTO(dto);
userService.saveUser(user);
}
If you have a converter defined, check if it's added to the FormatterRegistry
during application configuration.
Also make sure, that you have the UserProfile
entity correctly defined with JPA annotations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With