Number data is not binding in Spring MVC - java

While working on a spring MVC based project I am trying to bind data from JSP to model.
While the string data is binding perfectly for some reason the number data is not binding at all.
I have checked the parameter name it's same in POJO and JSP
Below is my controller code
#RequestMapping(value = "/investor-signup", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("investor", new InvestorRegister());
return "investor-signup";
}
#RequestMapping(value = "/investor-signup", method = RequestMethod.POST)
public String registration(#ModelAttribute("investor") InvestorRegister investor, BindingResult bindingResult, Model model) {
System.out.println(investor.getFULL_NAME());
System.out.println(investor.getMOB_NO());
investorRegisterService.save(investor);
return "redirect:/login";
}
Below is my JSP code
<form:form method="post" action="investor-signup"
modelAttribute="investor" id="contact-form"
style="padding-top: 40px;" role="form" class="formcss" align="left">
<div class="controls">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="col-md-2 ">
<label for="user_name">Full Name *</label>
</div>
<div class="col-md-10 p0">
<input id="user_name" type="text" name="FULL_NAME" class="form-control" required="required" data-error="Full Name is required.">
</div>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-12">
<div class="form-group">
<div class="col-md-2">
<label for="user_mobile">Mobile *</label>
</div>
<div class="col-md-6 ">
<input id="user_mobile" type="number" name="MOB_NO" class="form-control" required="required" data-error="Mobile No is required.">
</div>
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-12" align="center">
<input type="submit" class="btn btn-success btn-send" value="Register">
</div>
</div>
</form:form>
Below is my model POJO
#Entity
#Table(name = "InvestorRegister")
public class InvestorRegister {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
#SequenceGenerator(name = "SEQ_GEN", sequenceName = "IID_SEQ")
#Column(name = "ID")
private int ID;
#NotEmpty
#Column(name = "FULL_NAME")
private String FULL_NAME;
#Column(name = "MOB_NO")
private int MOB_NO;
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getFULL_NAME() {
return FULL_NAME;
}
public void setFULL_NAME(String fULL_NAME) {
FULL_NAME = fULL_NAME;
}
public int getMOB_NO() {
return MOB_NO;
}
public void setMOB_NO(int mOB_NO) {
MOB_NO = mOB_NO;
}
}
While the string data is binding perfectly for some reason the number data is not binding at all
I have checked the parameter name it's same in POJO and JSP
Any help is appreciated.

#abhi314, Have you just tried by extracting field separately ?
I mean have you tried any of these just to check value comes from view side or not?
public String registration(#RequestParam("FULL_NAME") String FULL_NAME, #RequestParam("MOB_NO") int MOB_NO) {
//check value comes or not
}
OR
public String registration(#RequestBody InvestorRegister ir) {
//check value comes or not
}
Please do let me know if you get value or not by checking this way

You need to use Wrapper Integer instead of int.
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
#SequenceGenerator(name = "SEQ_GEN", sequenceName = "IID_SEQ")
#Column(name = "ID")
private Integer ID;
Also I would suggest to use naming convention standards. Instead of ID declare id or most preferred as investorRegisterId.
After changing from int to Integer please regenerate the getter/setters for the same.
Your actual issue is failing on the concept of Java auto-boxing/unboxing.

Related

Why got Invalid property 'district' of bean class

While run spring boot project, got error in home page Invalid property 'district' of bean class.
I know why this error is coming because district is property of child entity and i can pass parent entity from Home()method in controller. I could pass Person entity in model in Home() method. but district and city property is from Address entity I am working with OneToOne relationship mapping.
My question are below:
Can we get two entity together in th:object in thymeleaf
Can we send Address and Person entity together using Model from controller to view
Stacktrace:
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'district' of bean class [com.rest.RestApiPojo.Entity.Person]: Bean property 'district' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
Here down is my code:
Entity
#Entity
#Table(name = "person_master")
public class Person {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long p_id;
private String name;
private String surname;
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Address address;
// getter setter
}
#Entity
#Table(name = "address_master")
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long a_id;
private String district;
private String city;
#OneToOne(cascade = CascadeType.ALL, mappedBy = "address")
#JoinColumn(name = "p_id")
private Person person;
// getter setter
}
service
#Override
public Person addPersonAddress(Person person) {
return personRepo.save(person);
}
controller
#RequestMapping(value = "/", method = RequestMethod.GET)
public String Home(Model mdl)
{
mdl.addAttribute("persons", new Person());
return "register";
}
#RequestMapping(value = "/personaddress", method = RequestMethod.POST)
public String addPersonAddress(Model mdl, #ModelAttribute("person") Person person, HttpServletRequest req)
{
Address address = person.getAddress(); // get reference of person from parent table and store in child table
address.setDistrict(req.getParameter("district"));
address.setCity(req.getParameter("city"));
address.setPerson(person);
pojoService.addPersonAddress(person);
return "listofperson";
}
Thymeleaf
<form th:action="#{/personaddress}" th:object="${persons}" method="post">
<div class="container">
<h1 style="text-align: center">Add Person</h1>
<div class="row">
<div class="col-sm-12">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Person name</label>
<input type="text" class="form-control" name="name" th:field="*{name}">
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Person surname</label>
<input type="text" class="form-control" name="surname" th:field="*{surname}">
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">District</label>
<input type="text" class="form-control" name="district" th:field="*{district}">
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">City</label>
<input type="text" class="form-control" name="city" th:field="*{city}">
</div>
<input class="btn btn-primary" type="submit" value="Submit">
</div>
</div>
</div>
</form>
Two entities are not required as they have already been mapped in the person class just write 'address.district' and 'address.city' in the thymeleaf, you will get it
This is regarding boilerplate code. you could add #Data to the class coming from Lombok library.
If you are not using lombok add setter and getter
public String getDistrict() {
return district;
}
public void setDistrict(String district) {
this.district= district;
}

Hibernate saveOrUpdate-method creates new entry/row instead of updating the existing one

I'm currently making a website to provide product management for a registered user. It uses spring + hibernate + mysql + jsp. Hibernates saveOrUpdate-method creates always a new entry/row to the database for the ProductDetail-entity instead of updating the already existing one. I have done the mapping according to the tutorials out there and I cannot understand what makes it to create a new row, because I have established the relationships to the Product- and ProductDetail-entity (OneToOne) in the Controller layer before the use. Someone save me from this struggle, I have been stuck here for more than 3 months... Below I will provide pictures of the Entities, Controller and DAO.
Product Entity (nvm commented annotations)
#Entity
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#NotNull(message = "Product name is required")
#Size(min = 1, message = "is required")
#Column(name = "product_name")
private String productName;
#DecimalMin(value = "0.01", inclusive = true, message = "Price must be a minimum of 0.01$")
#Digits(integer = 6, fraction = 2, message = "Price out of bounds, limit <6 digits>.<2 digits>")
#Column(name = "price")
private float price;
#NotNull(message = "Quantity is required")
#Min(value = 1, message = "Must be greater than zero")
#Column(name = "qty")
private Integer quantity;
#NotNull(message = "Email is required")
#Email(message = "Provide a valid email address")
#Pattern(regexp = ".+#.+\\..+", message = "Provide a valid email address")
#Column(name = "added_by")
private String addedBy;
#Column(name = "creation_datetime")
private Date createDateTime;
//#Version
#Column(name = "last_updated")
private Date updateDateTime;
//#Valid
#OneToOne(mappedBy = "product", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private ProductDetail productDetail;
#Column(name = "value_in_stock")
private float valueInStock;
public Product() {
this.createDateTime = new Date();
this.updateDateTime = this.createDateTime;
}
public Product(String productName, float price, Integer quantity, String addedBy) {
this.productName = productName;
this.price = price;
this.quantity = quantity;
this.addedBy = addedBy;
this.valueInStock = this.price * this.quantity;
}
public void setProductDetail(ProductDetail productDetail) {
if (productDetail == null) {
if (this.productDetail != null) {
this.productDetail.setProduct(null);
}
} else {
productDetail.setProduct(this);
}
this.productDetail = productDetail;
}
// getters and setters
ProductDetail entity
#Entity
#Table(name = "product_detail")
public class ProductDetail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#NotNull(message = "A descriptionis required")
#Column(name = "description")
private String description;
#NotNull(message = "Category is required")
#Column(name = "category")
private String category;
#DecimalMin(value = "0.001", inclusive = true, message = "Must a minimum of 0.001g")
#Digits(integer = 7, fraction = 2, message = "Weight out of bounds, limit <7 digits>.<2 digits>")
#Column(name = "weight_g")
private float weight;
#NotNull(message = "Manufacturer is required")
#Column(name = "manufacturer")
private String manufacturer;
#NotNull(message = "Provide a country")
#Column(name = "made_in_country")
private String countryMadeIn;
#OneToOne(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "product_id")
private Product product;
public ProductDetail() {
}
public ProductDetail(String description, String category, String manufacturer, String madeIn) {
this.description = description;
this.category = category;
this.manufacturer = manufacturer;
this.countryMadeIn = madeIn;
}
// Getters and setters...
ProductController
Method to fetch form for adding a new product (GET request)
#GetMapping("/add")
public String getAddForm(Model model) {
// create model attribute to bind all form data
Product product = new Product();
ProductDetail productDetail = new ProductDetail();
// associating product and product details
product.setProductDetail(productDetail);
product.getProductDetail());
model.addAttribute("categoryMap", categoryOptions);
model.addAttribute("countryMap", countryOptions);
model.addAttribute("product", product);
return "product-form";
}
Method to fetch product by id from productService (delegates data fetching to productDAO) (GET request)
#GetMapping("/updateProduct")
public String getUpdateForm(#RequestParam("productId") int productId, Model model) {
// get product from db
Product product = productService.getProduct(productId);
product.getProductDetail());
// set product as a model to pre-populate the form
model.addAttribute("categoryMap", categoryOptions);
model.addAttribute("countryMap", countryOptions);
model.addAttribute("product", product);
return "product-form";
}
Method to process saving/updating the Product and its ProductDetail (POST request)
#PostMapping("/save")
public String saveOrUpdate(#Valid #ModelAttribute("product") Product product, BindingResult bindingResult,
Model model) {
// if result set has errors, return to product form with errors
if (bindingResult.hasErrors()) {
model.addAttribute("categoryMap", categoryOptions);
model.addAttribute("countryMap", countryOptions);
return "product-form";
} else {
// calculate value in stock to product before saving
product.setValueInStock();
productService.saveProduct(product);
return "redirect:/";
}
}
ProductDAOImpl
Method to saveOrUpdate given product
#Override
public void saveProduct(Product product) {
// get current hibernate session
Session session = sessionFactory.getCurrentSession();
// save or update given product
session.saveOrUpdate(product);
}
Method to fetch product by its id
#Override
public Product getProduct(int id) {
// get current hibernate session
Session session = sessionFactory.getCurrentSession();
Query<Product> query =
session.createQuery("SELECT p FROM Product p "
+ "JOIN FETCH p.productDetail "
+ "WHERE p.id=:productId",
Product.class);
// set parameters in query
query.setParameter("productId", id);
// execute and get product
Product product = query.getSingleResult();
return product;
}
And finally here is the JSP form itself
<form:form action="save" modelAttribute="product" method="POST">
<!-- associate data with product id -->
<form:hidden path="id" />
<div class="form-group row">
<label for="nameInput" class="col-sm-2 col-form-label">Product name *:</label>
<div class="col-sm-10">
<form:input path="productName" cssClass="form-control" id="nameInput" placeholder="Enter name" />
<form:errors path="productName" cssClass="errors" />
</div>
</div>
<div class="form-group row">
<label for="priceInput" class="col-sm-2 col-form-label">Price($) *:</label>
<div class="col-sm-10">
<form:input path="price" cssClass="form-control" id="priceInput" placeholder="Enter price" />
<form:errors path="price" cssClass="errors" />
</div>
</div>
<div class="form-group row">
<label for="quantityInput" class="col-sm-2 col-form-label">Quantity *:</label>
<div class="col-sm-10">
<form:input path="quantity" cssClass="form-control" id="quantityInput" placeholder="Enter qty" />
<form:errors path="quantity" cssClass="errors" />
</div>
</div>
<div class="form-group row">
<label for="emailInput" class="col-sm-2 col-form-label">Added by(email) *:</label>
<div class="col-sm-10">
<form:input path="addedBy" cssClass="form-control" id="emailInput" placeholder="example.address#email.com" />
<form:errors path="addedBy" cssClass="errors" />
</div>
</div>
<div id="separator" > </div>
<h5 id="header" >Product Details (Can be updated later)</h5>
<div class="form-group row">
<label for="categoryInput" class="col-sm-2 col-form-label">Category *:</label>
<div class="col-sm-3">
<form:select path="productDetail.category" id="categoryInput" cssClass="form-control">
<form:option value="" label="Select Product Category" />
<form:options items="${categoryMap}"/>
</form:select>
<form:errors path="productDetail.category" cssClass="errors" />
</div>
</div>
<div class="form-group row">
<label for="manufacturerInput" class="col-sm-2 col-form-label">Manufacturer *:</label>
<div class="col-sm-4">
<form:input path="productDetail.manufacturer" cssClass="form-control" id="manufacturerInput" placeholder="Enter manufacturer" />
<form:errors path="productDetail.manufacturer" cssClass="errors" />
</div>
<label for="madeInInput" class="col-sm-2 col-form-label">Country *:</label>
<div class="col-sm-3">
<form:select path="productDetail.countryMadeIn" id="madeInInput" cssClass="form-control">
<form:option value="" label="Country manufactured in" />
<form:options items="${countryMap}"/>
</form:select>
<form:errors path="productDetail.countryMadeIn" cssClass="errors" />
</div>
</div>
<div class="form-group row">
<label for="descriptionInput" class="col-sm-2 col-form-label">Description *:</label>
<div class="col-sm-10">
<form:textarea path="productDetail.description" cssClass="form-control" id="descriptionInput" placeholder="Short description of product..." />
<form:errors path="productDetail.description" cssClass="errors" />
</div>
</div>
<div class="form-group row">
<label for="weightInput" class="col-sm-2 col-form-label">Weight(g):</label>
<div class="col-sm-10">
<form:input path="productDetail.weight" cssClass="form-control" id="weightInput" placeholder="Enter weight" />
</div>
</div>
<input type="submit" value="Add" class="btn btn-primary" />
</form:form>
So the user should be able to add and update a product. At the moment this just adds and when the user wants to update the product, it just creates a new ProductDetail-entity instead of updating the ProductDetail on the fetched Product-entity.
This is because you are using primitive data type int. Update it to Integer and it should work fine.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
Update it to,
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Integer id;
NOTE : Regenerate the corresponding getter/setters for this field.
You need to add a hidden key for productDetail.id or else it considers product detail object to be a transient one and saves it as a new object instead of updating it.

Why is my redirectAttributes.addFlashAttribute and data Re-populating not working after validation fails?

I have spent the whole day and night trying to find why my form data disappears when validation fails. I also added a redirectAttributes.addFlashAttribute which is suppose to indicate that an error occurred and also survive one redirect. So far none of these are working. I have done my research on stack over and other forums and i seem to be doing the right thing but it is not working for me.
I am not getting an error so i can not even debug to find what is wrong.
<div class="form-group" th:if="${exams.size() lt 6}">
<form method="post" th:object="${newExam}" th:action="#{/exams}" class="inline new-item">
<div th:classappend="${#fields.hasErrors('indexNumber')}? 'error' : ''">
<input type="text" th:field="*{indexNumber}" placeholder="Index Number" />
<div class="error-message" th:if="${#fields.hasErrors('indexNumber')}" th:errors="*{indexNumber}"></div>
</div>
<div th:classappend="${#fields.hasErrors('grade')}? 'error' : ''">
<select th:field="*{grade}" class="form-control input-lg">
<option value="">[Select Grade]</option>
<option th:each="grade : ${grades}" th:value="${grade.values}" th:text="${grade.name}">Grade
</option>
</select>
<div class="error-message" th:if="${#fields.hasErrors('grade')}" th:errors="*{grade}"></div>
</div>
<div th:classappend="${#fields.hasErrors('courseOffered')}? 'error' : ''">
<input type="text" th:field="*{courseOffered}" placeholder="CourseOffered" />
<div class="error-message" th:if="${#fields.hasErrors('courseOffered')}" th:errors="*{courseOffered}"></div>
</div>
<div th:classappend="${#fields.hasErrors('examType')}? 'error' : ''">
<input type="text" th:field="*{examType}" placeholder="ExamType" />
<div class="error-message" th:if="${#fields.hasErrors('examType')}" th:errors="*{examType}"></div>
</div>
<div th:classappend="${#fields.hasErrors('subject')}? 'error' : ''">
<input type="text" th:field="*{subject}" placeholder="Subject" />
<div class="error-message" th:if="${#fields.hasErrors('subject')}" th:errors="*{subject}"></div>
</div>
<div th:classappend="${#fields.hasErrors('gradeYear')}?'error' : ''">
<input type="text" th:field="*{gradeYear}" placeholder="ExamYear" />
<div class="error-message" th:if="${#fields.hasErrors('gradeYear')}" th:errors="*{gradeYear}"></div>
</div>
<button type="submit" class="btn btn-primary">Add</button>
</form>
</div>
Controller
#RequestMapping(value = "/cert_prog", method = RequestMethod.GET)
public String examsList(Model model){
Iterable<Exams> exams = examService.findAll();
if(!model.containsAttribute("newExam")){
model.addAttribute("newExam", new Exams()); }
model.addAttribute("grades", Grade.values());
model.addAttribute("regions", Region.values()); model.addAttribute("schools",schools);
if(!model.containsAttribute("newSchool")){
model.addAttribute("newSchool",new School()); }
model.addAttribute("regions", Region.values());
return "cert_prog"; }
#RequestMapping(value = "/exams", method = RequestMethod.POST) public String addTask(#Valid
#ModelAttribute("newExam") Exams exams, BindingResult result, RedirectAttributes redirectAttributes, Principal principal){
User user = (User)((UsernamePasswordAuthenticationToken)principal).getPrincipal(); exams.setUser(user);
if(result.hasErrors()){
redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.exams", result);
redirectAttributes.addFlashAttribute("exams",exams); return "redirect:/cert_prog"; }
examService.save(exams);
return "redirect:/cert_prog"; }
Model
#Entity
public class Exams {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull(message = "The above field must not be blank.")
private String courseOffered;
#NotNull(message = "The above field must not be blank.")
private String examType;
#NotNull(message = "The above field must not be blank.")
private String subject;
#NotNull(message = "The above field must not be blank.")
private String grade;
#NotNull(message = "The above field must not be blank.")
private Long indexNumber;
#NotNull(message = "The above field must not be blank.")
private Long gradeYear;
private boolean isComplete;
In your addTask controller method you have
redirectAttributes.addFlashAttribute("exams",exams)
attribute name as "exams" and you are checking as "newExam" in examsList controller method. This might be the problem.
try this,
redirectAttributes.addFlashAttribute("newExam",exams)

Not able to persist the role mapped to the user

I am creating an application with Spring 4, Hibernate 4 having Spring security
Users have roles assigned to them, but when I tried to create the user, it not able to save the user it is giving me exception on Browser below the field of role
Failed to convert property value of type [java.lang.String[]] to required type [java.util.Set] for property userRoles; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type
[#org.hibernate.validator.constraints.NotEmpty #javax.persistence.ManyToMany #javax.persistence.JoinTable com.himanshu.blogger.model.Role] for value 2; nested exception is java.lang.StackOverflowError
My User model class
#Entity
#Table(name = "BLOG_USER")
public class User {
#Id
#Column(name = "USER_ID")
private String userId;
#NotEmpty
#Column(name = "PASSWORD")
private String password;
#NotEmpty
#Column(name = "FIRST_NAME")
private String firstName;
#NotEmpty
#Column(name = "MIDDLE_NAME")
private String middleName;
#NotEmpty
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "EMAIL")
private String email;
#Column(name = "PHONE")
private String phone;
#NotNull
#Column(name = "STATE")
private Integer state = State.ACTIVE.getState();
#Transient
private String stateName;
#NotEmpty
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "USER_ROLE_MAP", joinColumns = { #JoinColumn(name = "USER_ID") }, inverseJoinColumns = {
#JoinColumn(name = "ROLE_ID") })
private Set<Role> userRoles = new HashSet<>();
/*skipped getter, setters and some utility methods*/
Role model class
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="ROLE_ID")
private Integer roleId;
#Column(name="ROLE_TYPE", length=20, nullable=false, unique=true)
private String roleType=RoleType.USER.getRoleType();
/*skipped getters and setters*/
My controller methods for registering new user here I have added a model attribute also to load the roles in registration form
/**
* This method will provide the medium to add a new user.
* By GET method it will identify that it has to load registration page
*/
#RequestMapping(value = { "/newuser" }, method = RequestMethod.GET)
public String newUser(ModelMap model) {
User user = new User();
model.addAttribute("user", user);
model.addAttribute("edit", false);
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) {
System.out.println("save user : "+user);
if (result.hasErrors()) {
return "registration";
}
if(!userService.isUniqueUser(user.getUserId())){
FieldError userIdError =new FieldError("user","userId",messageSource.getMessage("non.unique.ssoId", new String[]{user.getUserId()}, Locale.getDefault()));
result.addError(userIdError);
return "registration";
}
userService.saveUser(user);
model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " registered successfully");
//return "success";
return "registrationsuccess";
}
#ModelAttribute("blogRoleList")
public List<Role> initializeProfiles() {
return roleService.findAll();
}
I have registered a convertor to convert role id to Role object
#Component
public class RoleIdtoRoleConverter implements Converter<Object, Role> {
#Autowired
RoleService roleService;
public Role convert(Object roleIdObj) {
System.out.println("covertor called with id " + roleIdObj.toString());
Integer roleId = -1;
try {
roleId = Integer.parseInt((String) roleIdObj);
} catch (NumberFormatException e) {
throw new ConversionFailedException(TypeDescriptor.valueOf(String.class),
TypeDescriptor.valueOf(Role.class), roleIdObj, null);
}
System.out.println("covertor called with id " + roleIdObj.toString());
Role role = roleService.findRoleById(roleId);
System.out.println("Role = " + role);
return role;
}
Registered this convertor in my config class
#Autowired
RoleIdtoRoleConverter roleIdToRoleConverter;
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(roleIdToRoleConverter);
}
Registration JSP file registration.jsp
<form:form method="POST" modelAttribute="user" class="form-horizontal">
<%-- <form:input type="hidden" path="userId" id="useId"/> --%>
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3 control-lable" for="firstName">First Name</label>
<div class="col-md-7">
<form:input type="text" path="firstName" id="firstName" class="form-control input-sm"/>
<div class="has-error">
<form:errors path="firstName" class="help-inline"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3 control-lable" for="lastName">Last Name</label>
<div class="col-md-7">
<form:input type="text" path="lastName" id="lastName" class="form-control input-sm" />
<div class="has-error">
<form:errors path="lastName" class="help-inline"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3 control-lable" for="userId">User ID</label>
<div class="col-md-7">
<c:choose>
<c:when test="${edit}">
<form:input type="text" path="userId" id="userId" class="form-control input-sm" disabled="true"/>
</c:when>
<c:otherwise>
<form:input type="text" path="userId" id="userId" class="form-control input-sm" />
<div class="has-error">
<form:errors path="userId" class="help-inline"/>
</div>
</c:otherwise>
</c:choose>
</div>
</div>
</div>
<c:if test="${!edit}">
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3 control-lable" for="password">Password</label>
<div class="col-md-7">
<form:input type="password" path="password" id="password" class="form-control input-sm" />
<div class="has-error">
<form:errors path="password" class="help-inline"/>
</div>
</div>
</div>
</div>
</c:if>
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3 control-lable" for="email">Email</label>
<div class="col-md-7">
<form:input type="text" path="email" id="email" class="form-control input-sm" />
<div class="has-error">
<form:errors path="email" class="help-inline"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label class="col-md-3 control-lable" for="userRoles">Roles</label>
<div class="col-md-7">
<form:select path="userRoles" items="${blogRoleList}" multiple="true" itemValue="roleId" itemLabel="roleType" class="form-control input-sm" />
<div class="has-error">
<form:errors path="userRoles" class="help-inline"/>
</div>
</div>
</div>
</div>
<div class="row">
<div class="form-actions floatRight" style="margin-left: 25px">
<c:choose>
<c:when test="${edit}">
<input type="submit" value="Update" class="btn btn-primary btn-sm"/> or Cancel
</c:when>
<c:otherwise>
<input type="submit" value="Register" class="btn btn-primary btn-sm"/> or Cancel
</c:otherwise>
</c:choose>
</div>
</div>
</form:form>
But am not able to figure out it is not able to save the data, I have printed the user object in controller it is showing Roles as blank array, did I am missing some things here, not able to get, any help and suggestions will be got.
Adding Code for saving user
Abstract dao class
public class AbstractDao <PK extends Serializable, T>{
private final Class<T> persistantClass;
#Autowired
SessionFactory sessionFactory;
#SuppressWarnings("unchecked")
public AbstractDao() {
this.persistantClass=(Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()).getActualTypeArguments()[1];
}
public void persistEntity(T entity) {
this.getSession().persist(entity);
}
/* mor emethods to load data on based on object type */
}
User Dao implimentation calss
#Repository("userDao")
public class UserDaoImpl extends AbstractDao<String, User> implements UserDao{
#Override
public void saveUser(User user) {
persistEntity(user);
}
/* more methods for fetching data from db*/
}
Thanks.
I got the problem with my application.
The problem was with the dao method which was there to get role object from DB,
by mistake while writing the code I did made the call to same method, which executing recursively, so convertor was not able to get the role object from DB.

Spring form validation on dependent object

I faced this problem while I was validating my forms, For single entities it worked fine. But when I try to validate a object with nested objects I get this error.
HTTP Status 500 - Request processing failed; nested exception is javax.validation.ConstraintViolationException: Validation failed for classes [com.poultry.jp.model.PaymentRequest] during persist time for groups [javax.validation.groups.Default, ]
Following is my controller
#RequestMapping(value = {"user/addMedicineOrder","admin/addMedicineOrder"}, method = RequestMethod.GET)
public String addMedicineOrderGET(#ModelAttribute("medicineOrder") MedicineOrder medicineOrder,Model model) {
List<SupplierReport> supplierReport = supplierService.getSupplierNames();
List<MedicineOrderReport> medicineOrderReport = medicineOrderService.getMedicineOrderDetails();
List<PaymentRequestReport> paymentRequestReport = paymentRequestSerivice.getPaymentRequestDates();
List<MedicineReport> medicineReport = medicineService.getMedicineDetails();
model.addAttribute("medicineOrderReport",medicineOrderReport);
model.addAttribute("supplierReport", supplierReport);
model.addAttribute("paymentRequestReport", paymentRequestReport);
model.addAttribute("medicineReport", medicineReport);
return "addMedicineOrder";
}
#RequestMapping(value = {"user/addMedicineOrder","admin/addMedicineOrder"}, method = RequestMethod.POST)
public String addMedicineOrderPOST(#Valid #ModelAttribute("medicineOrder") MedicineOrder medicineOrder,BindingResult result) {
if (result.hasErrors()) {
return "addMedicineOrder";
} else {
medicineOrderService.save(medicineOrder);
return "redirect:addMedicineOrder.html";
}
}
Following is my Medicine Order Model
public class MedicineOrder {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long medicineOrderId;
#OneToMany(mappedBy = "medicineOrder", cascade = CascadeType.ALL,fetch = FetchType.EAGER,orphanRemoval=true)
private List<MedicineOrderDetails> medicineOrderDetails = new ArrayList<MedicineOrderDetails>();
#ManyToOne
private Supplier supplier;
#DateTimeFormat(pattern = "yyyy-MM-dd")
#Temporal(TemporalType.DATE)
private Date date;
private double total;
private double discount;
private boolean inStock;
#OneToOne(cascade={CascadeType.MERGE , CascadeType.PERSIST})
#JoinColumn(name="paymentRequest_id")
private PaymentRequest paymentRequest;
private boolean isDeleted;
private Date created;
private Date updated;
// Getters and Setters
}
Following is the dependent class Payment Request
public class PaymentRequest{
public static final String FIND_PAYMENT_REQUEST_DATES = "findPaymentReequestDates";
public static final String FIND_PAYMENT_REQUEST_BY_ID = "findPaymentReequestById";
public static final String FIND_PAYMENT_REQUEST_REPORT = "findPaymentRequestReport";
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long paymentId;
private double amount;
#Type(type = "text")
#NotEmpty
private String description;
private String chequeID;
private String status;
#DateTimeFormat(pattern = "yyyy-MM-dd")
#Temporal(TemporalType.DATE)
private Date date;
private boolean isDeleted;
private boolean isPaid;
private Date created;
private Date updated;
//Getters and Setters
}
and Following is where I persist Medicine Order which persist the payment request with it.
#Repository("MedicineOrderRepository")
public class MedicineOrderRepositoryImp implements MedicineOrderRepository{
#PersistenceContext
private EntityManager entityManager;
public MedicineOrder save(MedicineOrder medicineOrder){
for(MedicineOrderDetails order : medicineOrder.getMedicineOrderDetails())
{
order.setMedicineOrder(medicineOrder);
}
medicineOrder.getPaymentRequest().setStatus("Pending");
entityManager.persist(medicineOrder);
entityManager.flush();
return medicineOrder;
}
}
And Finally following the jsp code.
<div class=".col-md-6">
<form:form commandName="medicineOrder" class="form-horizontal"
autocomplete="off">
<form:errors path="*" Class="alert alert-danger" element="div" />
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Description</label>
<div class="col-sm-3">
<form:textarea path="paymentRequest.description" type="text"
class="form-control" id="inputDescription"
placeholder="Enter Short Description" rows="3" />
</div>
</div>
<div class="form-group">
<label for="inputAmount" class="col-sm-2 control-label">Amount</label>
<div class="col-sm-3">
<form:input path="paymentRequest.amount" type="text"
class="form-control" id="inputAmount" placeholder="Enter Amount" />
</div>
</div>
<div class="form-group">
<label for="supplierId" class="col-sm-2 control-label">Supplier</label>
<div class="col-sm-5">
<form:select path="supplier.supplierId" id="supplierId"
class="form-control">
<form:options items="${supplierReport}" itemLabel="name"
itemValue="supplierId" id="" />
</form:select>
</div>
</div>
<div class="form-group">
<label for="inputTotal" class="col-sm-2 control-label">Total</label>
<div class="col-sm-5">
<form:input path="total" type="text" class="form-control"
id="inputTotal" name="inputTotal" />
</div>
</div>
<div class="form-group">
<label for="inputDiscount" class="col-sm-2 control-label">Discount
</label>
<div class="col-sm-5">
<form:input path="discount" type="text" class="form-control"
id="inputDiscount" />
</div>
</div>
<input type="submit" value="Save Medicine Order"
class="btn btn-primary">
</form:form>
</div>
I was able to resolve this.
Credit goes to this forum, http://forum.spring.io/forum/spring-projects/web/87783-jsr-303-validation-on-child-objects
what I had to do was just add #Valid annotation in my parent class's child object
EX:
#Valid
private PaymentRequest paymentRequest;

Categories