spring mvc module not updating record - java

In a spring mvc application that uses hibernate an jpa, I have a module for editing phone numbers which is not committing changes to the database when the user enters altered information for phone number and phone number type. I keep going over the code, but I cannot see where the problem is. Can someone show me what to change in the below?
Here are the relevant methods of PhoneNumberController.java:
#RequestMapping(value = "/patients/{patientId}/phonenumbers/{phonenumberId}/edit", method = RequestMethod.GET)
public String initUpdateForm(#PathVariable("phonenumberId") int phonenumberId, Map<String, Object> model) {
System.out.println("--------------------------------- made it into initUpdateForm() method");
PhoneNumber phonenumber = this.clinicService.findPhoneNumberById(phonenumberId);
model.put("phonenumber", phonenumber);
return "phonenumbers/createOrUpdatePhoneNumberForm";
}
#RequestMapping(value = "/patients/{patientId}/phonenumbers/{phonenumberId}/edit", method = {RequestMethod.PUT, RequestMethod.POST})
public String processUpdateForm(#ModelAttribute("phonenumber") PhoneNumber phonenumber, BindingResult result, SessionStatus status) {
// we're not using #Valid annotation here because it is easier to define such validation rule in Java
new PhoneNumberValidator().validate(phonenumber, result);
if (result.hasErrors()) {return "phonenumbers/createOrUpdatePhoneNumberForm";}
else {
this.clinicService.savePhoneNumber(phonenumber);
status.setComplete();
return "redirect:/patients?patientID={patientId}&type=phone";
}
}
Here is the PhoneNumber.java model:
#Entity
#Table(name = "patient_phone_numbers")
public class PhoneNumber {
#Id
#GeneratedValue
#Column(name="id")
private Integer id;
#ManyToOne
#JoinColumn(name = "client_id")
private Patient patient;
#Column(name="phonenumber")
private String number;
#ManyToOne
#JoinColumn(name = "type_id")
private PhoneNumberType type;
#Column(name = "preferred")
private boolean preferred;
#Column(name = "okmessages")
private boolean okmessages;
public Integer getId(){return id;}
public void setId(Integer i){id=i;}
protected void setPatient(Patient patient) {this.patient = patient;}
public Patient getPatient(){return this.patient;}
public String getNumber(){return number;}
public void setNumber(String pn){number=pn;}
public PhoneNumberType getType(){return this.type;}
public void setType(PhoneNumberType nt){this.type=nt;}
public boolean getPreferred(){return preferred;}
public void setPreferred(boolean p){preferred=p;}
public boolean getOkmessages(){return okmessages;}
public void setOkmessages(boolean m){okmessages=m;}
public boolean isNew() {return (this.id == null);}
}
And here is the createOrUpdatePhoneNumberForm.jsp:
<html lang="en">
<jsp:include page="../fragments/headTag.jsp"/>
<body>
<div class="container">
<jsp:include page="../fragments/bodyHeader.jsp"/>
<c:choose>
<c:when test="${phonenumber['new']}">
<c:set var="method" value="post"/>
</c:when>
<c:otherwise>
<c:set var="method" value="put"/>
</c:otherwise>
</c:choose>
<h2>
<c:if test="${phonenumber['new']}">New </c:if>
Phone Number
</h2>
<form:form modelAttribute="phonenumber" method="${method}" class="form-horizontal">
<div class="control-group" id="patient">
<label class="control-label">Patient </label>
<c:out value="${phonenumber.patient.firstName} ${phonenumber.patient.lastName}"/>
</div>
<petclinic:inputField label="PhoneNumber" name="number"/>
<div class="control-group">
<petclinic:selectField name="type" label="Type" names="${numtypes}" size="5"/>
</div>
Preferred number? <form:checkbox path="preferred"/><br>
OK to leave messages? <form:checkbox path="okmessages"/>
<td>
</td>
<div class="form-actions">
<c:choose>
<c:when test="${phonenumber['new']}">
<button type="submit">Add Phone Number</button>
</c:when>
<c:otherwise>
<button type="submit">Update Phone Number</button> <h3> Link to delete will go here.</h3>
</c:otherwise>
</c:choose>
</div>
</form:form>
<c:if test="${!phonenumber['new']}">
</c:if>
</div>
</body>
</html>
ClinicService.java is:
#Service
public class ClinicServiceImpl implements ClinicService {
private DocumentRepository documentRepository;
private PatientRepository patientRepository;
private AddressRepository addressRepository;
private PhoneNumberRepository phoneNumberRepository;
#Autowired
public ClinicServiceImpl(DocumentRepository documentRepository, PatientRepository patientRepository, AddressRepository addressRepository, PhoneNumberRepository phoneNumberRepository) {
this.documentRepository = documentRepository;
this.patientRepository = patientRepository;
this.addressRepository = addressRepository;
this.phoneNumberRepository = phoneNumberRepository;
}
#Override
#Transactional(readOnly = true)
public Collection<DocumentType> findDocumentTypes() throws DataAccessException {return documentRepository.findDocumentTypes();}
#Override
#Transactional(readOnly = true)
public Collection<Gender> findGenders() throws DataAccessException {return patientRepository.findGenders();}
#Override
#Transactional(readOnly = true)
public Collection<Race> findRaces() throws DataAccessException {return patientRepository.findRaces();}
#Override
#Transactional(readOnly = true)
public Patient findPatientById(int id) throws DataAccessException {return patientRepository.findById(id);}
#Override
#Transactional(readOnly = true)
public Collection<Patient> findPatientByLastName(String lastName) throws DataAccessException {return patientRepository.findByLastName(lastName);}
#Override
#Transactional
public void savePatient(Patient patient) throws DataAccessException {
System.out.println("-------------------------------------- inside clinicservice.savePatient()");
patientRepository.save(patient);}
#Override
#Transactional(readOnly = true)
public Document findDocumentById(int id) throws DataAccessException {
System.out.println("--------------- made it into clinicservice.findDocumentById() method");
return documentRepository.findById(id);}
#Override
#Transactional
public void saveDocument(Document doc) throws DataAccessException {documentRepository.save(doc);}
#Override
#Transactional
public void saveAddress(Address addr) throws DataAccessException {addressRepository.save(addr);}
#Override
#Transactional(readOnly=true)
public Address findAddressById(int id) throws DataAccessException {return addressRepository.findById(id);}
#Override
#Transactional(readOnly = true)
public Collection<State> findStates() throws DataAccessException {return addressRepository.findStates();}
#Override
#Transactional(readOnly = true)
public Collection<PhoneNumberType> findPhoneNumberTypes() throws DataAccessException {return phoneNumberRepository.findPhoneNumberTypes();}
#Override
#Transactional(readOnly = true)
public void savePhoneNumber(PhoneNumber pn) throws DataAccessException {
System.out.println("++++++++++++++++++++ inside savePhoneNumber(pn) : "+pn.getNumber()+" , "+pn.getType().getName());
phoneNumberRepository.save(pn);
}
#Override
#Transactional(readOnly=true)
public PhoneNumber findPhoneNumberById(int id) throws DataAccessException {return phoneNumberRepository.findById(id);}
}
JpaPhoneNumberRepository.java contains the following:
#PersistenceContext
private EntityManager em;
#Override
public void save(PhoneNumber phonenumber) {
System.out.println("------------------------------ inside save(phonenumber) : "+phonenumber.getNumber()+" , "+phonenumber.getType().getName());
if (phonenumber.getId() == null) {
System.out.println("phonenumber.getId() == null ");
this.em.persist(phonenumber);
}
else {
System.out.println("else");
this.em.merge(phonenumber);}
}
The correct new values for getNumber() and getType().getName() print out. And "else" prints out, but then the data is not updated in the database. Why not? (note that clinicservice calls this save() method of JpaPhoneNumberRepository.java.)

The problem is that you have ClinicServiceImpl > savePhoneNumber method annotated as #Transactional(readOnly = true). Change it to #Transactional

Why is the savePhoneNumber method in your ClinicService.java as #Transactional(readOnly=True)?
That is the cause of the problem

Related

Property or field 'id' cannot be found on object of type 'java.lang.Boolean' - maybe not public or not valid?

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);
}
}
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.

Spring MVC: The request sent by the client was syntactically incorrect when creating a new entity record

Good afternoon,
I am newbie to Spring MVC. I'm stuck with the following error while running my project "The request sent by the client was syntactically incorrect."
My project has two entities, Team and Country which have a ManyToOne relationship. Both these entities map tables created in mysql database.
I started the project with only the Team entity, and sucessfuly created my classes (DAO, controller, services, etc) and jsp to create new teams.
Now, I created the class Country to relate both entities and I added a dropdown list in the "add-team-form.jsp" to select the country of the new team. This page is correctly displayed (all countries appear in the dropdown list), however, when I click "submit" to create the new team, I get the error "The request sent by the client was syntactically incorrect."
Can you please help me to identify my error? I'm guessing it's in the "add-team-form.jsp".
1 - Entity Team:
#Entity
#Table(name="teams")
public class Team implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "name", length = 40, nullable = false)
private String name;
#Column(name = "rating", length = 6, nullable = false)
private Integer rating;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "id_country", nullable = false)
private Country country;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getRating() {
return rating;
}
public void setRating(Integer rating) {
this.rating = rating;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
}
2 - Entity Country:
#Entity
#Table(name = "countries")
public class Country implements Serializable{
#Id
#Column(name= "id_country", length = 6)
private String idCountry;
#Column(name = "name", length = 255, nullable = false)
private String name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "country")
private List<Team> teams;
public String getIdCountry() {
return idCountry;
}
public void setIdCountry(String idCountry) {
this.idCountry = idCountry;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
My Team DAO
#Repository
public class TeamDAOImpl implements TeamDAO {
#Autowired
private SessionFactory sessionFactory;
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
#Override
public void addTeam(Team team) {
getCurrentSession().save(team);
}
}
My Team Service
#Service
#Transactional
public class TeamServiceImpl implements TeamService {
#Autowired
private TeamDAO teamDAO;
public void addTeam(Team team) {
teamDAO.addTeam(team);
}
My Team Controller
#Controller
#RequestMapping(value="/team")
public class TeamController {
#Autowired
private TeamService teamService;
#Autowired
private FilterService filterService;
#RequestMapping(value="/add", method=RequestMethod.GET)
public ModelAndView addTeamPage() {
ModelAndView modelAndView = new ModelAndView("add-team-form");
modelAndView.addObject("team", new Team());
return modelAndView;
}
#RequestMapping(value="/add", method=RequestMethod.POST)
public ModelAndView addingTeam(#ModelAttribute Team team) {
ModelAndView modelAndView = new ModelAndView("home");
teamService.addTeam(team);
String message = "Team was successfully added.";
modelAndView.addObject("message", message);
return modelAndView;
}
#ModelAttribute("countryList")
public Map<String, String> getCountryList(){
Map<String, String> countryList = filterService.getCountries();
return countryList;
}
...
}
My "add-team-form.jsp"
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Add team page</title>
</head>
<body>
<h1>Add team page</h1>
<form:form method="POST"
modelAttribute="team"
action="${pageContext.request.contextPath}/team/add.html">
<table>
<tbody>
<tr>
<td>Name:</td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td>Rating:</td>
<td><form:input path="rating" /></td>
</tr>
<tr>
<td><label>Country</label></td>
<td>
<form:select path="country.idCountry">
<form:options items="${countryList}" />
</form:select>
</td>
<tr>
<td><input type="submit" value="Add" /></td>
<td></td>
</tr>
</tbody>
</table>
</form:form>
</body>
</html>
There is no error showing in the console of eclipse, but here is the error im receiving from the browser:
HTTP Status 400 -
type Status report
message
description The request sent by the client was syntactically incorrect.
Apache Tomcat/7.0.47
There's a couple of problems I can see here - you are posting to add/team/add.html and not hitting your post handler. You don't need the action attribute as you're posting to the same endpoint;
<form:form method="POST" modelAttribute="team" >
Secondly your are injecting the countries as a map, so these are ID/display values which works great for key/value pairs and for binding a value to a string field. In this case, Spring is trying to bind your country ID (String) to the team.country(Country) field which will fail. To help Spring out you need a databinder; in your controller add;
#InitBinder
public void initBinder (WebDataBinder binder) {
binder.registerCustomEditor(Country.class, new CountryEditor());
}
and create the property editor class;
public class CountryEditor extends PropertyEditorSupport {
#Override
public void setValue(Object value) {
super.setValue(value);
}
public String getAsText() {
if (getValue() == null) return null;
return ((Country) getValue()).getName();
};
public void setAsText(String text) throws IllegalArgumentException {
if (text != null) {
Country country = // something like filterService.getCountryById(text);
setValue(country);
}
};
}
There's more information in the Spring documentation
The error you are receiving generally happens if a parameter is missing or is in a different format and cannot be converted to the expected type.Check the values being passed to the Team object.You can either log the request and response or set the log level to "DEBUG",this will display the exact error in logs.

Getting HTTP status 400 error while submitting a form in spring mvc

I have two webpages.One is "user.jsp" and "person.jsp".when i click on "Register" button it goes to "user.jsp" and when i click on submit button its showing "Http Status 400".
PersonController.java
#Controller
public class PersonController {
private PersonService personService;
private UserService userService;
#Autowired(required=true)
#Qualifier(value="personService")
public void setPersonService(PersonService ps){
this.personService = ps;
}
#RequestMapping(value = "/persons", method = RequestMethod.GET)
public String listPersons(Model model) {
model.addAttribute("person", new Person());
model.addAttribute("listPersons", this.personService.listPersons());
return "person";
}
//For add and update person both
#RequestMapping(value= "/person/add", method = RequestMethod.POST)
public String addPerson(#ModelAttribute("person") Person p,#ModelAttribute("user") User u){
String name = p.getName();
System.out.println("name is :"+name);
if(name == null || name == "") {
System.out.println("user is"+name);
return "user";
}
else{
//new person, add it
this.personService.addPerson(p);
}
return "redirect:/persons";
}
#RequestMapping(value = "/user/add", method = RequestMethod.POST)
public String addUser(#ModelAttribute("user") User user) {
// new user, add to DB
this.userService.addUser(user);
return "redirect:/persons";
}
PersonDAOImpl.java
#Repository
public class PersonDAOImpl implements PersonDAO {
private static final Logger logger = LoggerFactory.getLogger(PersonDAOImpl.class);
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#Override
public void addPerson(Person p) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(p);
logger.info("Person saved successfully, Person Details="+p);
}
#Override
public void updatePerson(Person p) {
Session session = this.sessionFactory.getCurrentSession();
session.update(p);
logger.info("Person updated successfully, Person Details="+p);
}
#SuppressWarnings("unchecked")
#Override
public List<Person> listPersons() {
Session session = this.sessionFactory.getCurrentSession();
List<Person> personsList = session.createQuery("from Person").list();
for(Person p : personsList){
logger.info("Person List::"+p);
}
return personsList;
}
#Override
public Person getPersonByName(String name) {
Session session = this.sessionFactory.getCurrentSession();
List<Person> usersList = session.createQuery(
"from Person ").list();
if (usersList.size() == 0)
return null;
Person usrObj1 = usersList.get(0);
return usrObj1;
}
UserDAOImpl.java
#Repository
public class UserDAOImpl implements UserDAO {
private static final Logger logger = LoggerFactory
.getLogger(UserDAOImpl.class);
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf) {
this.sessionFactory = sf;
}
#Override
public void addUser(User user) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(user);
logger.info("User saved successfully, User Details=" + user);
}
#Override
public void updateUser(User user) {
Session session = this.sessionFactory.getCurrentSession();
session.update(user);
logger.info("User updated successfully, User Details=" + user);
}
#SuppressWarnings("unchecked")
#Override
public List<User> listUsers() {
Session session = this.sessionFactory.getCurrentSession();
List<User> usersList = session.createQuery("from User").list();
for (User user : usersList) {
logger.info("User List::" + user);
}
return usersList;
}
#SuppressWarnings("unchecked")
#Override
public User getUserByName(String fullName) {
Session session = this.sessionFactory.getCurrentSession();
List<User> usersList = session.createQuery(
"from User ").list();
if (usersList.size() == 0)
return null;
User usrObj1 = usersList.get(0);
return usrObj1;
}
Person.java
#Entity
#Table(name="PERSON")
public class Person {
#Id
#Column(name="id")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private String country;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
#Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
User.java
#Entity
#Table(name = "user")
#XmlRootElement(name = "User")
public class User {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "fullname")
private String fullName;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "phone")
private Integer phone;
#XmlElement(name = "Id")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#XmlElement(name = "FullName")
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
#XmlElement(name = "Password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#XmlElement(name = "EmailId")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#XmlElement(name = "PhoneNo")
public Integer getPhone() {
return phone;
}
public void setPhone(Integer phone) {
this.phone = phone;
}
PersonServiceImpl.java
#Service
public class PersonServiceImpl implements PersonService {
private PersonDAO personDAO;
public void setPersonDAO(PersonDAO personDAO) {
this.personDAO = personDAO;
}
#Override
#Transactional
public void addPerson(Person p) {
this.personDAO.addPerson(p);
}
#Override
#Transactional
public void updatePerson(Person p) {
this.personDAO.updatePerson(p);
}
#Override
#Transactional
public List<Person> listPersons() {
return this.personDAO.listPersons();
}
#Override
#Transactional
public Person getPersonById(int id) {
return this.personDAO.getPersonById(id);
}
#Override
#Transactional
public Person getPersonByName(String name) {
return this.personDAO.getPersonByName(name);
}
#Override
#Transactional
public void removePerson(int id) {
this.personDAO.removePerson(id);
}
UserServiceImpl.java
#Service
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
#Override
#Transactional
public void addUser(User user) {
this.userDAO.addUser(user);
}
#Override
#Transactional
public void updateUser(User user) {
this.userDAO.updateUser(user);
}
#Override
#Transactional
public List<User> listUsers() {
return this.userDAO.listUsers();
}
#Override
#Transactional
public User getUserById(int id) {
return this.userDAO.getUserById(id);
}
#Override
#Transactional
public void removeUser(int id) {
this.userDAO.removeUser(id);
}
#Override
#Transactional
public User getUserByName(String fullName) {
return this.userDAO.getUserByName(fullName);
}
}
person.jsp
<c:url var="addAction" value="/person/add" ></c:url>
<form:form action="${addAction}" commandName="person">
<table>
<c:if test="${!empty person.name}">
<tr>
<td>
<form:label path="id">
<spring:message text="ID"/>
</form:label>
</td>
<td>
<form:input path="id" readonly="true" size="8" disabled="true" />
<form:hidden path="id" />
</td>
</tr>
</c:if>
<tr>
<td>
<form:label path="name">
<spring:message text="Name"/>
</form:label>
</td>
<td>
<form:input path="name" />
</td>
</tr>
<tr>
<td>
<form:label path="country">
<spring:message text="Country"/>
</form:label>
</td>
<td>
<form:input path="country" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit"
value="<spring:message text="Add Person"/>" />
<input type="submit"
value="<spring:message text="Register"/>" />
</td>
</tr>
</table>
</form:form>
user.jsp
<c:url var="addAction" value="/user/add"></c:url>
<form:form action="${addAction}" commandName="user">
<table width="400px" height="150px">
<c:if test="${!empty user.email}">
<tr>
<td><form:label path="id">
<spring:message text="ID" />
</form:label></td>
<td><form:input path="id" readonly="true" size="8"
disabled="true" /> <form:hidden path="id" /></td>
</tr>
</c:if>
<c:if test="${!empty user.email}">
</c:if>
<tr>
<td><form:label path="fullName">
<spring:message text="Full Name" />
</form:label></td>
<td><form:input path="fullName" /></td>
</tr>
<tr>
<td><form:label path="password">
<spring:message text="Password" />
</form:label></td>
<td><form:input type="password" path="password" /></td>
</tr>
<tr>
<td><form:label path="email">
<spring:message text="Email" />
</form:label></td>
<td><form:input path="email" /></td>
</tr>
<tr>
<td><form:label path="phone">
<spring:message text="Phone" />
</form:label></td>
<td><form:input path="phone" /></td>
</tr>
<tr>
<td colspan="2"><c:if test="${!empty user.email}">
<input type="submit"
value="<spring:message text="Update Details"/>" />
</c:if> <c:if test="${empty user.email}">
<input type="submit" value="<spring:message text="Submit"/>" />
</c:if></td>
</tr>
</table>
</form:form>
Any suggestion or advice in this it will be helpful for me
THanking You
I hope this helps!
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
400 Bad Request
The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing).
You have not defined the http method attribute of your form:
<form:form action="${addAction}" commandName="user">
Then, the default method is GET, therefore it wont never found a controller because your controller /user/add expects RequestMethod.POST
If you add the method attribute It will work:
<form:form action="${addAction}" commandName="user" method="POST">

how to databind list selected checkbox in spring mvc

Hi I am new to Spring Mvc i have 3 tables first is role,resources,roleresource tables respectively. I have a created a jsp in which a list of resources are shown along with check boxes and also rolename where user enters,my prob is i need to insert rolename to role table and generated roleid to roleresource table with selected resources ids. problem here is i am not able to bind selected checkbox values here is my controller
package com.steadyground.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.steadyground.constants.URLConstants;
import com.steadyground.entity.Organization;
import com.steadyground.entity.Resources;
import com.steadyground.form.RoleResourceForm;
import com.steadyground.service.ResourcesService;
#Controller
public class RoleResoucesMappingController {
#Autowired
private ResourcesService resourcesService;
#RequestMapping(value = URLConstants.ROLERESOURCEMAPPING_PAGE, method = RequestMethod.GET)
public String landRoleResourceMapping(ModelMap map)
{
map.addAttribute("roleResourceForm",new RoleResourceForm());
return "roleResourcesMapping";
}
#RequestMapping(value = URLConstants.ROLERESOURCEMAPPING_ADD, method = RequestMethod.POST)
public String createRoleResourceMapping(#ModelAttribute(value="roleResourceForm") RoleResourceForm roleResourceForm, BindingResult result, ModelMap map)
{
System.out.println(roleResourceForm.getResources());
System.out.println(roleResourceForm.getResources().size());
//System.out.println(roleResourceForm.getRole().getRoleResources());
return "roleResourcesMapping";
}
#ModelAttribute("resources")
public List<Resources> getAllResources() {
List<Resources> listResources = new ArrayList<Resources>();
listResources = resourcesService.getAllResources();
return listResources;
}
}
here is my role.java file
#Entity
#Table(name = "role", catalog = "steadyground")
public class Role implements java.io.Serializable {
private Integer roleId;
private String roleName;
private Set<RoleResource> roleResources = new HashSet<RoleResource>(0);
public Role() {
}
public Role(String roleName) {
this.roleName = roleName;
}
public Role(String roleName, String applicationName,
Set<RoleResource> roleResources) {
this.roleName = roleName;
this.roleResources = roleResources;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "role_id", unique = true, nullable = false)
public Integer getRoleId() {
return this.roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
#Column(name = "role_name", nullable = false, length = 100)
public String getRoleName() {
return this.roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "role")
public Set<RoleResource> getRoleResources() {
return this.roleResources;
}
public void setRoleResources(Set<RoleResource> roleResources) {
this.roleResources = roleResources;
}
}
here is my resources.java
#Entity
#Table(name = "resources", catalog = "steadyground")
public class Resources implements java.io.Serializable {
private Integer resourceId;
private String url;
private String urlName;
public Resources() {
}
public Resources(String url, String urlName) {
this.url = url;
this.urlName = urlName;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "resource_id", unique = true, nullable = false)
public Integer getResourceId() {
return this.resourceId;
}
public void setResourceId(Integer resourceId) {
this.resourceId = resourceId;
}
#Column(name = "url", length = 100)
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
#Column(name = "url_name", length = 200)
public String getUrlName() {
return this.urlName;
}
public void setUrlName(String urlName) {
this.urlName = urlName;
}
}
here is my roleresource.java
#Entity
#Table(name="role_resource"
,catalog="steadyground"
)
public class RoleResource implements java.io.Serializable {
private Integer roleResourceId;
private Role role;
private Integer resourceId;
public RoleResource() {
}
public RoleResource(Role role, Integer resourceId) {
this.role = role;
this.resourceId = resourceId;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="role_resource_id", unique=true, nullable=false)
public Integer getRoleResourceId() {
return this.roleResourceId;
}
public void setRoleResourceId(Integer roleResourceId) {
this.roleResourceId = roleResourceId;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="role_id")
public Role getRole() {
return this.role;
}
public void setRole(Role role) {
this.role = role;
}
#Column(name="resource_id")
public Integer getResourceId() {
return this.resourceId;
}
public void setResourceId(Integer resourceId) {
this.resourceId = resourceId;
}
}
and my jsp page
<springform:form method="post" action="createRoleResourcesMapping" class="form-horizontal" commandName="roleResourceForm" >
<div class="span12">
<div class="center">
<div class="control-group span6">
<label class="control-label" for="Role_Id">Role Id</label>
<div class="control-group span6">
<label class="control-label" for="url_Name">Role Name</label>
<div class="controls">
<div class="span12">
<springform:input path="role.roleName"/>
</div>
</div>
</div>
<div class="page-header position-relative"></div>
<table id="sample-table-2" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Resources</th>
</tr>
</thead>
<tbody>
<tr>
<td><springform:checkboxes path="resources" items="${resources}" itemLabel="urlName" itemValue="resourceId"/>
</td></tr></tbody>
</table>
<div class="controls">
<div class="span12">
<input type="submit" class="btn btn-primary" value="Submit">
<input type="button" class="btn " value="Cancel">
</div>
</div>
</div>
</div>
</springform:form>
could someone help me in how to receive the data and save it in two tables
<springform:checkboxes path="resources" items="${resources}" itemLabel="urlName" itemValue="resourceId"/>
From your code, what I've understood, the RoleResourcesForm is more like a wrapper of the 2 entities Resource & Role with another object resources.
I think, to use form:checkboxes you better give it an object List in the path.
And what's this variable resources?
If it's really an List object in the RoleResourcesForm wrapper, in the items, you should use
items="${roleResourceForm.resources}"
When you commit it, it will send the form model attribute with only checked checkbox values.

LazyInitialization Exception with Spring and Hibernate

I think i'm missing something fundamental about how Hibernate works, specifically with lazy loading. My problem is debugging, as I'm not sure if this is a Hibernate problem or a Spring problem in disguise. I thought I would ask here before doing some major refactoring.
I have two Entities. One holds a collection of the other in a OneToMany relationship. For my web page I wish to grab all of the first entity, and subsequently grab the set of associated entities for each and display them.
I believe my problem is this: I use a JpaTemplate to find all entities. This works fine, however because of Lazy loading I do not get the associated set of related entities. In my view (jsp) I want access to this set, but of course it is null because it is being lazy loaded. Now, i'm getting a LazyInitialization exception stating that the transaction has ended. To me this makes sense, of course the transaction should be over by now. The thing is, how can the assoicated set ever be lazy loaded if the transaction is over?
Entity Classes:
#Entity
public class LearningEntry implements Serializable {
private Long id;
String imagePath = "";
Set<Sample> samples = null;
//------------------------------
// Constructors
//------------------------------
public LearningEntry(){
imagePath = "";
samples = new HashSet<Sample>();
}
//------------------------------
// Instance Methods
//------------------------------
public void addSample(Sample s){
samples.add(s);
}
public void removeSample(Sample s){
samples.remove(s);
}
//------------------------------
// Setters and Getters
//------------------------------
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
//#Column(name = "wisi_LE_IMAGEPATH", length = 100, nullable = false)
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
// TODO - ONly works with fetch type EAGER
//#OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
public Set<Sample> getSamples() {
return samples;
}
public void setSamples(Set<Sample> samples) {
this.samples = samples;
}
}
Sample Entity
#Entity
public class Sample implements Serializable {
private Long id;
Date creationDate;
String audioFileLocation;
Integer votes;
String description;
public Sample(){
creationDate = new Date();
audioFileLocation = "";
votes = 0;
description = "";
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAudioFileLocation() {
return audioFileLocation;
}
public void setAudioFileLocation(String audioFileLocation) {
this.audioFileLocation = audioFileLocation;
}
#Temporal(TemporalType.DATE)
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getVotes() {
return votes;
}
public void setVotes(Integer votes) {
this.votes = votes;
}
}
DAO Classes:
LearningEntryDAO
#Transactional
public class JpaLearningEntryDAO implements LearningEntryDAO{
private JpaTemplate jpaTemplate;
public JpaLearningEntryDAO(){
}
public void setJpaTemplate(JpaTemplate jpaTemplate){
this.jpaTemplate = jpaTemplate;
}
#Override
//#Transactional
public void delete(Long leId) {
LearningEntry dp = jpaTemplate.find(LearningEntry.class, leId);
jpaTemplate.remove(dp);
}
#Override
#SuppressWarnings("unchecked")
//#Transactional
public List<LearningEntry> findAll() {
return jpaTemplate.find("from LearningEntry");
}
#Override
//#Transactional
public LearningEntry findById(Long leId) {
return jpaTemplate.find(LearningEntry.class, leId);
}
#Override
//#Transactional
public LearningEntry store(LearningEntry dp) {
return jpaTemplate.merge(dp);
}
#Override
#SuppressWarnings("unchecked")
//#Transactional
public void deleteAll(){
throw new RuntimeException("deleteAll not implemented");
}
}
Sample DAO
#Transactional
public class JpaSampleDAO implements SampleDAO{
private JpaTemplate jpaTemplate;
public JpaSampleDAO(){}
public void setJpaTemplate(JpaTemplate jpaTemplate){
this.jpaTemplate = jpaTemplate;
}
#Override
//#Transactional
public void delete(Long sampleId) {
Sample dp = jpaTemplate.find(Sample.class, sampleId);
jpaTemplate.remove(dp);
}
#Override
#SuppressWarnings("unchecked")
public List<Sample> findAll() {
return jpaTemplate.find("from Sample");
}
#Override
public Sample findById(Long sampleId) {
return jpaTemplate.find(Sample.class, sampleId);
}
#Override
public Sample store(Sample dp) {
return jpaTemplate.merge(dp);
}
#Override
#SuppressWarnings("unchecked")
public void deleteAll(){
throw new RuntimeException("deleteAll not implemented");
}
}
Controller
#RequestMapping(value = "/index.htm", method = RequestMethod.GET)
public ModelAndView sayHello(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
Map<String, Object> model = new HashMap<String, Object>();
List<LearningEntry> le = learningEntryService.getLearningEntries();
model.put("learningEntries", le);
return new ModelAndView("main", model);
}
View
<section id="content" class="body">
<ol id="posts-list" class="hfeed">
<c:forEach items="${learningEntries}" var="learningEntry">
<li>
<table class="wisiEntry">
<tr>
<td class="pictureCell">
<img class="wisiEntry-pic" src="${learningEntry.imagePath}" />
</td>
<td class="previousNextCell"
<div class="wisiEntry-nextSampleButton">Next</div>
<div class="wisiEntry-previousSampleButton">Previous</div>
<br />
<div class="wisiEntry-addTagButton">Tag</div>
<div class="wisiEntry-addCommentButton">Comment</div>
<br />
<div class="wisiEntry-uploadButton">Upload</div>
</td>
<td>
<!-- ERROR HAPPENS HERE. Samples should not be null -->
<c:forEach items="${learningEntry.samples}" var="sample" varStatus = "status">
<table class="sampleEntry" ${status.first ? '' : 'style = "display:none"'}>
<tr>
<td class="sampleCell">
<p class="description">
${sample.description}
</p>
<audio src="${sample.audioFileLocation}" controls>
Your browser does not support the <code>audio</code> element.
</audio>
</td>
<td class="voteCell">
<img class="upVote" src="/images/upArrow.jpeg" />
<span class="voteNumber">${sample.votes}</span>
<img class="downVote" src="/images/downArrow.jpeg" />
</td>
</tr>
</table>
</c:forEach>
</td>
</tr>
</table>
</li>
</c:forEach>
</ol><!-- /#posts-list -->
</section><!-- /#content -->
I hope you are using findAll() method down the call. You can load all the associated samples by modifying your method like below.
public List<LearningEntry> findAll() {
List<LearningEntry> entries = jpaTemplate.find("from LearningEntry");
for(LearningEntry entry : entries){
entry.getSamples().size();
}
return entries;
}
Or, as you already know, you can also achieve this by changing fetch to FetchType.EAGER. But this might not suit you in all cases. Therefore, former way is better.
Or you might like to do no change anywhere, and define another method to get all the samples based on LearningEntry, this way you will be able to fire up an AJAX call on some event. But that might not suit here in this case.
Thanks to Vinegar for providing a working answer (upvoted).
I decided to add this answer that has also worked for me. I took this approach because I may want to make separate ajax calls in the future. In other words, I can ask for the LearningEntry in one transaction, than ask for its samples some time down the road.
#Transactional
public Set<Sample> getSamplesForLearningEntry(LearningEntry le) {
// Reload the le from the database so it is not transient:
LearningEntry le = leDAO.store(le);
le.getSamples.size();
return le.getSamples();
}
Most frameworks offer the 'open session in view' pattern. See https://www.hibernate.org/43.html:
The solution, in two-tiered systems,
with the action execution, data access
through the Session, and the rendering
of the view all in the same virtual
machine, is to keep the Session open
until the view has been rendered.
For data that is read often and hardly ever updated, query caching can help too. This reduces the load on the database, but increases memory usage. Hibernate can be configured to do this for you.

Categories

Resources