I am writing a SpringBoot application for an e-commerce website project where I’m creating a form to change the current password of the user account. I am getting the following two errors when the form gets submitted.
- ERROR-1
An error happened during template parsing (template: "class path resource [templates/myprofile.html]") Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "user.id" (template: "myprofile" - line 110, col 68) Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "user.id" (template: "myprofile" - line 110, col 68)
- ERROR-2
Property or field 'id' cannot be found on object of type 'java.lang.Boolean' - maybe not public or not valid?
HomeController
@RequestMapping(value = "/updateUserInfo", method = RequestMethod.POST) public String updateUserInfo( @ModelAttribute("user") user user, @ModelAttribute("newPassword") String newPassword, Model model ) throws Exception{ user currentUser = userService.findById(user.getId()); if(currentUser == null) { throw new Exception ("User not found."); } if(userService.findByEmail(user.getEmail())!=null) { if(userService.findByEmail(user.getEmail()).getId() != currentUser.getId()) { model.addAttribute("emailExists", true); return "myprofile"; } } if(userService.findByUsername(user.getUsername())!=null) { if(userService.findByUsername(user.getUsername()).getId() != currentUser.getId()) { model.addAttribute("usernameExists", true); return "myprofile"; } } if(newPassword != null && !newPassword.isEmpty() && !newPassword .equals("")) { BCryptPasswordEncoder passwordEncoder = SecurityUtility.passwordEncoder(); String dbPassword = currentUser.getPassword(); if(passwordEncoder.matches(user.getPassword(), dbPassword)) { currentUser.setPassword(passwordEncoder.encode(newPassword)); }else { model.addAttribute("invalidPassword", true); return "myprofile"; } } currentUser.setFirstName(user.getFirstName()); currentUser.setLastName(user.getLastName()); currentUser.setUsername(user.getUsername()); currentUser.setEmail(user.getEmail()); userService.save(currentUser); model.addAttribute("updateSuccess", true); model.addAttribute("user", true); model.addAttribute("classActiveEdit", true); UserDetails userDetails = userSecurityService.loadUserByUsername(currentUser.getUsername()); Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); return "myprofile"; }
myprofile.html
<form th:action="@{/updateUserInfo}" method="post" > <input type="hidden" name="id" th:value="${user.id}" /> <div class="bg-info" th:if="${updateUserInfo}">User info updated</div> <div class="form-group"> <div class="row"> <div class="col-xs-6"> <label for="firstName">First Name</label> <input type="text" class="form-control" id="firstName" name="firstName" th:value="${user.firstName}" /> </div> <div class="col-xs-6"> <label for="lastName">Last Name</label> <input type="text" class="form-control" id="lastName" name="lastName" th:value="${user.lastName}" /> </div> </div> </div> <div class="form-group"> <label for="userName">Username</label> <input type="text" class="form-control" id="userName" name="username" th:value="${user.username}" /> </div> <div class="form-group"> <label for="currentPassword">Current Password</label> <input type="password" class="form-control" id="currentPassword" name="password" th:value="${currentPassword}" /> </div> <p style="color: #828282">Enter your current password to change the email address or password</p> <div class="form-group"> <label for="email">Email Address</label> <input type="text" class="form-control" id="email" name="email" th:value="${user.email}" /> </div> <p style="color: #828282">A valid email address. All emails from the system will be sent to this address.The email address is not make public and will only be used if you wish to receive a new password or wish to receive certain notification</p> <div class="form-group"> <label for="txtNewPassword">Password</label> <span id="checkPasswordMatch" style="color:red;"></span> <input type="password" class="form-control" id="txtNewPassword" name="txtNewPassword" /> </div> <div class="form-group"> <label for="txtConfirmPassword">Confirm Password</label> <input type="password" class="form-control" id="txtConfirmPassword" /> </div> <p style="color: #828282">To change the current user password, enter new password in both fileds </p> <button id="updateUserInfobutton" type="submit" class="btn btn-primary">Save All</button> </form>
User Class
package com.eshop.domian; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; 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.OneToMany; import javax.persistence.OneToOne; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import com.eshop.security.UserRole; import com.eshop.security.auth; import com.fasterxml.jackson.annotation.JsonIgnore; @Entity public class user implements UserDetails{ @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id", nullable = false, updatable = false) private Long id; private String firstName; private String lastName; private String username; private String password; @Column(name="email", nullable = false, updatable = false) private String email; private String phone; private boolean enabled=true; @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") private ShoppingCart shoppingCart; @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") private List<UserShipping> userShippingList; @OneToMany(cascade = CascadeType.ALL, mappedBy = "user") private List<UserPayment> userPaymentList; @OneToMany(mappedBy = "user", cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JsonIgnore private Set<UserRole> userRoles= new HashSet<>(); public long getId() { return id; } public void setId(Long id) { this.id = id; } 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 getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public Set<UserRole> getUserRoles() { return userRoles; } public void setUserRoles(Set<UserRole> userRoles) { this.userRoles = userRoles; } public ShoppingCart getShoppingCart() { return shoppingCart; } public void setShoppingCart(ShoppingCart shoppingCart) { this.shoppingCart = shoppingCart; } public List<UserShipping> getUserShippingList() { return userShippingList; } public void setUserShippingList(List<UserShipping> userShippingList) { this.userShippingList = userShippingList; } public List<UserPayment> getUserPaymentList() { return userPaymentList; } public void setUserPaymentList(List<UserPayment> userPaymentList) { this.userPaymentList = userPaymentList; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { Set<GrantedAuthority> authorities = new HashSet<>(); userRoles.forEach(ur -> authorities.add(new auth(ur.getRole().getName()))); return authorities; } @Override public boolean isAccountNonExpired() { // TODO Auto-generated method stub return true; } @Override public boolean isAccountNonLocked() { // TODO Auto-generated method stub return true; } @Override public boolean isCredentialsNonExpired() { // TODO Auto-generated method stub return true; } @Override public boolean isEnabled() { return enabled; } }
User Service
package com.eshop.service; import java.util.Set; import com.eshop.domian.UserBilling; import com.eshop.domian.UserPayment; import com.eshop.domian.UserShipping; import com.eshop.domian.user; import com.eshop.security.PasswordResetToken; import com.eshop.security.UserRole; public interface UserService { PasswordResetToken getPasswordResetToken(final String token); void createPasswordResetTokenForUser(final user user, final String token); user findByUsername(String username); user findByEmail(String email); user findById(Long Id); user createUser(user user, Set<UserRole> userRoles) throws Exception; user save(user user); void updateUserBilling(UserBilling userBilling, UserPayment userPayment, user user); void setUserDefaultPayment(Long userPaymentId, user user); void updateUserShipping(UserShipping userShipping, user user); void setUserDefaultShipping(Long userShippingId, user user); }
User Service Implementation
package com.eshop.service.impl; @Service public class UserServiceImpl implements UserService{ private static final Logger LOG = LoggerFactory.getLogger(UserService.class); @Autowired private PasswordResetTokenRepository passwordResetTokenRepository; @Autowired private UserRepository userRepository; @Autowired private RoleRepository roleRepository; @Autowired private UserPaymentRepository userPaymentRepository; @Autowired private UserShippingRepository userShippingRepository; @Override public PasswordResetToken getPasswordResetToken(final String token) { return passwordResetTokenRepository.findByToken(token); } @Override public void createPasswordResetTokenForUser(final user user, final String token) { final PasswordResetToken myToken = new PasswordResetToken(token, user); passwordResetTokenRepository.save(myToken); } @Override public user findByUsername(String username) { // TODO Auto-generated method stub return userRepository.findByusername(username); } @Override public user findById(Long id) { return userRepository.findById(id).get(); } @Override public user findByEmail(String email) { // TODO Auto-generated method stub return userRepository.findByEmail(email); }
}
Advertisement
Answer
Here you try to access the id
field of the user
model attribute:
<input type="hidden" name="id" th:value="${user.id}" />
Here you set the user
model attribute to true
, therefore it’s of type boolean
:
model.addAttribute("user", true);
As a variable of type boolean
does not have a field called id
, trying to access it gives the error you see. I assume what’s going on is that you didn’t want to set that model attribute to true
(perhaps you wanted to set it to currentUser
?), or that the id
field that you want to access belongs to another model attribute.