Themeleaf issue with can not be null variable - spring

I was trying to send the posts to DB. However,when I tried to use themeleaf, it shows me the following error:
EL1007E: Property or field 'name' cannot be found on null Exception evaluating SpringEL expression: "name" (template: "StudentForm" - line 264, col 49) An error happened during template parsing (template: "class path resource [templates/StudentForm.html]")
This is what I tried below:
StudentForm.html
<div class="col-lg-10">
<div class="card">
<div class="card-header">
<strong>Basic Form</strong> Elements
</div>
<div class="card-body card-block">
<form th:action="#{/StudentForm}" th:Object="${student}" method="post" enctype="multipart/form-data" class="form-horizontal" role="form">
<div class="row form-group">
<div class="col col-md-3">
<label for="text-input" th:field="*{name}" class=" form-control-label">Ismi sharifi</label>
</div>
<div class="col-12 col-md-9">
<input type="text" id="text-input" placeholder="Iltimos ismni kiriting" class="form-control">
</div>
</div>
<div class="row form-group">
<div class="col col-md-3">
<label for="select" class=" form-control-label">Fakulteti</label>
</div>
<!-- <div class="col-12 col-md-9">
<select name="select" id="select" class="form-control">
<option value="0">Fakultetni tanlang</option>
<option value="1">Option #1</option>
<option value="2">Option #2</option>
<option value="3">Option #3</option>
</select>
</div>
</div> -->
<div class="row form-group">
<div class="col col-md-3">
<label for="email-input" class=" form-control-label">Email Input</label>
</div>
<div class="col-12 col-md-9">
<input type="email" id="email-input" th:field="*{email}" placeholder="Emailni kiriting" class="form-control">
<small class="help-block form-text"></small>
</div>
</div>
<div class="row form-group">
<div class="col col-md-3">
<label for="text-input" class=" form-control-label">To'langan summa</label>
</div>
<div class="col-12 col-md-9">
<input type="text" id="text-input" placeholder="Summani kiriting" class="form-control">
</div>
</div>
<div class="row form-group">
<div class="col col-md-3">
<label for="file-input" class=" form-control-label">File input</label>
</div>
<div class="col-12 col-md-9">
<input type="file" id="file-input" name="file-input" class="form-control-file">
</div>
</div>
</form>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary btn-sm">
<i class="fa fa-dot-circle-o"></i> Yuklash
</button>
<button type="reset" class="btn btn-danger btn-sm">
<i class="fa fa-ban"></i> Reset
</button>
</div>
</div>
StudentController.java
package io.javabrains;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import io.javabrains.Entities.Student;
import io.javabrains.repository.StudentRepository;
import io.javabrains.service.StudentService;
#Controller
public class StudentController {
#Autowired
private StudentRepository repository;
#Autowired
private StudentService service;
#RequestMapping(value= {"/student"},method=RequestMethod.GET)
public ModelAndView student(HttpServletRequest request) {
request.setAttribute("Student", service.findAll());
request.setAttribute("mode", "MODE_TASKS");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("student");
return modelAndView;
}
#RequestMapping(value="/StudentForm",method=RequestMethod.POST)
public ModelAndView studentForm(#Valid Student student,BindingResult bindingResult,ModelMap modelMap)
{
ModelAndView modelAndView = new ModelAndView();
service.addStudent(student);
modelAndView.addObject("student",new Student());
modelAndView.setViewName("studentForm");
return modelAndView;
}
#RequestMapping(value={"/StudentForm"},method=RequestMethod.GET)
public ModelAndView studentForm() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("StudentForm");
return modelAndView;
}
public List<Student>getAllEmployers(){
return service.findAll();
}
StudentEntity.java
package io.javabrains.Entities;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
#Entity
#Table(name = "student")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "studentId")
private int studentId;
#Column(name="name")
#NotNull(message = "Name is compulsort")
private String Name;
#Column(name="email")
#NotNull(message = "Email is compulsory")
private String Email;
#Column(name="department")
#NotNull(message = "department is compulsort")
private String Department;
#Column(name="amount")
#NotNull(message = "Amount is compulsort")
private double Amount;
#ManyToOne
#JoinColumn(name="studentId",referencedColumnName="id",insertable=false, updatable=false)
private DepartmentCategory departmentCategory;

First of all your controller should contain get method which returns Student object as a form to bind. You missed that. It should look something like this:
#RequestMapping(value={"/StudentForm"},method=RequestMethod.GET)
public ModelAndView studentForm() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("student", new Student()) //returns object to thymeleaf context
modelAndView.setViewName("StudentForm");
return modelAndView;
}
then you should change your naming convention in your student class, fields should start with lower case. You should notice that you have field Name in your Student class but you want to map th:field="*{name}" in thymeleaf view.
Read something about DTO and Models because you shouldn't use your entities directly in controller layer

Related

org.springframework.beans.NotReadablePropertyException:Invalid property

Invalid property 'stCode' of bean class [java.lang.String]: Bean property 'stCode' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
Regist.jsp
<div class="container">
<div class="row centered-form">
<div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
</div>
<div class="panel-body">
<f:form action="registSave" modelAttribute="r" method="post">
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
State Name
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<f:input path="stCode" class="form-control input-sm"/>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
District Name
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<f:input path="distCode" class="form-control input-sm"/>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
Phone number
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<f:input path="phone" class="form-control input-sm"/>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
Name
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<f:input path="name" class="form-control input-sm"/>
</div>
</div>
</div>
<!-- <div class="form-group">
<input type="email" name="email" id="email" class="form-control input-sm" placeholder="Email Address">
</div>
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-sm" placeholder="Password">
</div>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<div class="form-group">
<input type="password" name="password_confirmation" id="password_confirmation" class="form-control input-sm" placeholder="Confirm Password">
</div>
</div>
</div> -->
<input type="submit" value="Register" class="btn btn-info btn-block">
</f:form>
</div>
</div>
</div>
</div>
</div>
RBean
package max.Bean;
public class RBean {
String stCode;
String distCode;
String phone;
String name;
public String getStCode() {
return stCode;
}
public void setStCode(String stCode) {
this.stCode = stCode;
}
public String getDistCode() {
return distCode;
}
public void setDistCode(String distCode) {
this.distCode = distCode;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Controller
package max;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import max.Bean.RBean;
#Controller
public class MainController {
#Autowired
RBean rBean;
#RequestMapping("home")
public String home()
{
return "registLayout";
}
#RequestMapping("regist")
public ModelAndView registration()
{
return new ModelAndView("reg","r","rBean");
}
#RequestMapping(value="registSave", method=RequestMethod.POST)
public ModelAndView registrationSave(#ModelAttribute("r") RBean rBean)
{
return new ModelAndView("reg","r","rBean");
}
}
if you are trying to set rBean into r variable which is available in view then you should remove the " used for rBean. Eg: return new ModelAndView("reg","r",rBean);

Neither BindingResult nor plain target object for bean name 'user' available as request attribute during form implemetntaion

I am getting this error when I run my Project and I tried all the fixes online but it did not work.
Neither BindingResult nor plain target object for bean name 'user' available as request attribute during form implementation
I am pasting the code below
Do I have to create a table in my database or how do I fix this?
I am trying to read the values entered from the form to another jsp page using spring mvc but without using annotations. And while doing so I am getting this error: Neither BindingResult nor plain target object for bean name 'user' available as request attribute My Controller Class code is as follows:
User.java
package User;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private Integer age;
private String gender;
private String email;
private String city;
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 getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
UserController.java
package Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import User.User;
#Controller
public class UserController {
#Autowired
private UserRepository userRepository;
#GetMapping("/greeting")
public String greetingForm(Model model) {
model.addAttribute("user", new User());
return "greeting";
}
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute User user , Model model) {
User newUser = new User();
newUser.setName(user.getName());
newUser.setAge(user.getAge());
newUser.setGender(user.getGender());
newUser.setEmail(user.getEmail());
newUser.setCity(user.getCity());
userRepository.save(user);
return "result";
}
#GetMapping("/all")
public String getMeassage(Model model ) {
Iterable<User> users = userRepository.findAll();
model.addAttribute("users", users);
return "all";
}
}
greeting.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Form Submission</title>
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<br><br>
<h2 style="color:green">Form</h2>
<br><br>
<form class="form-horizontal" role="form" action="#" th:action="#{/greeting}" th:object="${user}" modelAttribute="user" method="post">
<div class="form-group" style="width:300px">
<label for="name" class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
<input type="text" th:field="*{name}" class="form-control" id="name" placeholder="Enter name">
</div>
</div>
<div class="form-group" style="width:300px">
<label for="age" class="col-sm-2 control-label">Age</label>
<div class="col-sm-10">
<input type="text" th:field="*{age}" class="form-control" id="age" placeholder="Enter age">
</div>
</div>
<div class="form-group" style="width:300px">
<label for="gender" class="col-sm-2 control-label">Gender</label>
<div class="col-sm-10">
<input type="text" th:field="*{gender}" class="form-control" id="gender" placeholder="Enter gender(M or F)">
</div>
</div>
<div class="form-group" style="width:300px">
<label for="email" class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
<input type="text" th:field="*{email}" class="form-control" id="email" placeholder="Enter email">
</div>
</div>
<div class="form-group" style="width:300px">
<label for="city" class="col-sm-2 control-label">City</label>
<div class="col-sm-10">
<input type="text" th:field="*{city}" class="form-control" id="city" placeholder="Enter city">
</div>
</div>
<div class="form-group">
<div>
<button type="submit" class="btn btn-primary" id="btn">Submit</button>
<input type="reset" class="btn btn-warning" value="Reset" />
</div>
</div>
</form>
</body>
</html>
Thanks in advance for the help

How to use LocalDateTime

what is the right way to solve LocalDateTime error?
I am new to spring therefore I have tried to look for the way to solve this online but I cannot get around it.
This is my entity
package com.reserve.entities;
import java.time.LocalDateTime;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;
#Entity
public class Flight extends AbstractEntity {
private String flightNumber;
private String operatingAirlines;
private String departureCity;
private String arrivalCity;
#DateTimeFormat(iso=ISO.DATE)
private Date dateOfDeparture;
#Column(name="estimatedDepartureTime",columnDefinition="TIMESTAMP")
private LocalDateTime estimatedDepartureTime;
public String getFlightNumber() {
return flightNumber;
}
public void setFlightNumber(String flightNumber) {
this.flightNumber = flightNumber;
}
public String getOperatingAirlines() {
return operatingAirlines;
}
public void setOperatingAirlines(String operatingAirlines) {
this.operatingAirlines = operatingAirlines;
}
public String getDepartureCity() {
return departureCity;
}
public void setDepartureCity(String departureCity) {
this.departureCity = departureCity;
}
public String getArrivalCity() {
return arrivalCity;
}
public void setArrivalCity(String arrivalCity) {
this.arrivalCity = arrivalCity;
}
public Date getDateOfDeparture() {
return dateOfDeparture;
}
public void setDateOfDeparture(Date dateOfDeparture) {
this.dateOfDeparture = dateOfDeparture;
}
public LocalDateTime getEstimatedDepartureTime() {
return estimatedDepartureTime;
}
public void setEstimatedDepartureTime(LocalDateTime estimatedDepartureTime) {
this.estimatedDepartureTime = estimatedDepartureTime;
}
#Override
public String toString() {
return "Flight [flightNumber=" + flightNumber + ", operatingAirlines=" + operatingAirlines + ", departureCity="
+ departureCity + ", arrivalCity=" + arrivalCity + ", dateOfDeparture=" + dateOfDeparture
+ ", estimatedDepartureTime=" + estimatedDepartureTime + "]";
}
}
This is my controller.
I am not sure which information is required.
Please let me know if there are more information that could help.
package com.reserve.controllers;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.reserve.entities.Flight;
import com.reserve.repository.FlightRepository;
#Controller
public class FlightController {
#Autowired
private FlightRepository flightRepository;
#RequestMapping("findFlights")
public String findFlights(
#RequestParam("from")String from,
#RequestParam("to")String to,
#RequestParam("departureDate")
#DateTimeFormat(pattern = "MM-dd-yyyy")
Date departureDate,
Model model)
{
List<Flight> flights = flightRepository.findFlights(from,to,departureDate);
model.addAttribute("flights", flights);
return "displayFlights";
}
#RequestMapping("/ourFlights")
public String ourFlights() {
return "ourFlights";
}
#RequestMapping(value="/add", method=RequestMethod.POST)
public String addFlights(#ModelAttribute("flight")Flight flight,Model model) {
Flight save = flightRepository.save(flight);
String msg = save.getFlightNumber() + " from " + save.getDepartureCity() + " to "
+ save.getArrivalCity() + " has been added.";
model.addAttribute("msg", msg);
return "ourFlights";
}
}
This is my JSP file
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%#page isELIgnored="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Money Wise</title>
<link rel="stylesheet" href="/reserve/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/reserve/css/custom.css"/>
</head>
<body>
<div class="container">
<div id="body">
<nav class="navbar navbar-expand-lg navbar-light bg-lights">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="home">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Ideology</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Faq</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">News</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0 pull-right">
<input class="form-control mr-sm-2" type="search" placeholder="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
<!-- Site Body -->
<div id="content" class="container">
<div class="row">
<div id="leftMain" class="col-sm-3">
<img src="/reserve/images/jim.png"width=100%/>
</div>
<div id="mainBody" class="col-sm-9 ">
<h2>Add Flights</h2>
<form action="add" method="post">
<div class="form-group">
<label for="flightNumber">Flight number</label>
<input type="text" class="form-control" name="flightNumber" placeholder="Flight number"/>
</div>
<div class="form-group">
<label for="operatingAirlines">Operating airlines</label>
<input type="text" class="form-control" name="operatingAirlines" placeholder="Operating airlines"/>
</div>
<div class="form-group">
<label for="departureCity">Departure city</label>
<input type="text" class="form-control" name="departureCity" placeholder="Departure city"/>
</div>
<div class="form-group">
<label for="arrivalCity">Arrival city</label>
<input type="text" class="form-control" name="arrivalCity" placeholder="Arrival city"/>
</div>
<div class="form-group">
<label for="dateOfDeparture">Date of departure</label>
<input type="Date" class="form-control" name="dateOfDeparture" placeholder="Date of departure"/>
</div>
<div class="form-group">
<label for="estimatedDepartureTime">Estimated departure time</label>
<input type="datetime-local" class="form-control" name="estimatedDepartureTime" placeholder="Estimated departure time"/>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- JS, Popper.js, and jQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.0/dist/umd/popper.min.js"></script>
<script src="/reserve/js/bootstrap.min.js"></script>
</body>
</html>
This is the error I get
Field error in object 'flight' on field 'estimatedDepartureTime': rejected value [2020-06-20T17:35]; codes
[typeMismatch.flight.estimatedDepartureTime,typeMismatch.estimatedDepartureTime,typeMismatch.java.time.LocalDateTime,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [flight.estimatedDepartureTime,estimatedDepartureTime]; arguments []; default message [estimatedDepartureTime]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'estimatedDepartureTime';
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type
[java.lang.String] to type [#javax.persistence.Column java.time.LocalDateTime] for value '2020-06-20T17:35'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2020-06-20T17:35]]]
``````
You can try to use Spring The Formatter SPI to convert Date expressed as String to LocalDateTime and vice versa.
public class DateTimeFormatters {
public static class LocalDateTimeFormatter implements Formatter<LocalDateTime> {
#Override
public LocalDateTime parse(String pattern, Locale locale) throws ParseException {
return LocalDateTime.parse(pattern, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
#Override
public String print(LocalDateTime object, Locale locale) {
return object.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}
}
}
And register your Formatter e.g
public class ApplicationConfig implements WebMvcConfigurer {
...
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateTimeFormatters.LocalDateTimeFormatter());
}
...
}

select multiple not passing all the selected values

path="userRoles" is multi select field. Which is populated with the method "initializeRoles()" from the controller. I have a converter also to convert Roles to UserRoles object. When I submit the form even after selecting all the Roles, I get only the first selected one always to the converter class as shown below. Why I am not getting String[] from JSP?
Output in the Converter class:
1
string
JSP code:
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%# page isELIgnored="false" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>User Create Form</title>
<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link>
<link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
</head>
<body>
<div class="generic-container">
<%#include file="authheader.jsp" %>
<div class="well lead">User Create Form</div>
<form:form method="POST" modelAttribute="user" class="form-horizontal">
<form:input type="hidden" path="userid" id="userid"/>
<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="middleName">Middle Name</label>
<div class="col-md-7">
<form:input type="text" path="middleName" id="middleName" class="form-control input-sm" />
<div class="has-error">
<form:errors path="middleName" 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="username">Username</label>
<div class="col-md-7">
<c:choose>
<c:when test="${edit}">
<form:input type="text" path="username" id="username" class="form-control input-sm" disabled="true"/>
</c:when>
<c:otherwise>
<form:input type="text" path="username" id="username" class="form-control input-sm" />
<div class="has-error">
<form:errors path="username" class="help-inline"/>
</div>
</c:otherwise>
</c:choose>
</div>
</div>
</div>
<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>
<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="${roles}" multiple="true" itemValue="roleid" itemLabel="roleName" 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">
<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>
</div>
</body>
</html>
Controller code:
package com.rsa.tools.springmvc.web.controller;
import java.util.List;
import java.util.Locale;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.rsa.tools.springmvc.model.User;
import com.rsa.tools.springmvc.model.UserRoles;
import com.rsa.tools.springmvc.service.UserManagementService;
#Controller
#RequestMapping("/users")
public class UserController {
#Autowired
UserManagementService umService;
#Autowired
MessageSource messageSource;
#RequestMapping(value="/list", method=RequestMethod.GET)
public String listUsers(ModelMap model) {
List<User> users = umService.getAllUsersOrderedByUsername();
model.addAttribute("users", users);
return "userslist";
}
#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";
}
#RequestMapping(value = { "/newuser" }, method = RequestMethod.POST)
public String saveUser(#Valid User user, BindingResult result, ModelMap model) {
System.out.println(user);
System.out.println(result.getAllErrors());
if (result.hasErrors()) {
return "registration";
}
if(!umService.isUsernameUnique(user.getUsername())) {
FieldError usernameError = new FieldError("user","username",messageSource.getMessage("non.unique.username", new String[]{user.getUsername()}, Locale.getDefault()));
result.addError(usernameError);
return "registration";
}
umService.addUser(user);
model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " registered successfully");
//return "success";
return "registrationsuccess";
}
#RequestMapping(value = { "/edit-user-{username}" }, method = RequestMethod.GET)
public String editUser(#PathVariable String username, ModelMap model) {
User user = umService.findByUsername(username);
model.addAttribute("user", user);
model.addAttribute("edit", true);
return "registration";
}
#RequestMapping(value = { "/edit-user-{username}" }, method = RequestMethod.POST)
public String updateUser(#Valid User user, BindingResult result, ModelMap model, #PathVariable String username) {
if (result.hasErrors()) {
return "registration";
}
umService.editUser(user);
model.addAttribute("success", "User " + user.getFirstName() + " "+ user.getLastName() + " updated successfully");
return "registrationsuccess";
}
#RequestMapping(value = { "/delete-user-{username}" }, method = RequestMethod.GET)
public String deleteUser(#PathVariable String username) {
umService.deleteUser(username);
return "redirect:/list";
}
#ModelAttribute("roles")
public List<UserRoles> initializeRoles() {
return umService.getAllUserRoles();
}
}
Converter code:
package com.rsa.tools.springmvc.configuration.web.converter;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import com.rsa.tools.springmvc.dao.UserDao;
import com.rsa.tools.springmvc.model.UserRoles;
#Component
public class UserRolesConverter implements Converter<Object, List<UserRoles>> {
#Autowired
UserDao userDao;
#Override
public List<UserRoles> convert(Object roles) {
List<UserRoles> userRoles = new ArrayList<UserRoles>();
System.out.println(roles);
if (roles instanceof String) {
System.out.println("string");
String sRoles = (String)roles;
UserRoles ur = userDao.findByRoleid(Long.parseLong(sRoles));
userRoles.add(ur);
} else if (roles instanceof String[]) {
System.out.println("string[]");
for (String role : (String[])roles) {
UserRoles ur = userDao.findByRoleid(Long.parseLong(role));
userRoles.add(ur);
}
}
return userRoles;
}
}
Web Configuration:
package com.rsa.tools.springmvc.configuration.web;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.format.FormatterRegistry;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import com.rsa.tools.springmvc.configuration.web.converter.UserRolesConverter;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.rsa.tools.springmvc.web.controller", "com.rsa.tools.springmvc.configuration.web.converter" })
public class ApplicationWebConfiguration extends WebMvcConfigurerAdapter {
#Autowired
UserRolesConverter userRolesConverter;
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(JstlView.class);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("messages");
return source;
}
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(userRolesConverter);
}
#Override
public Validator getValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource());
return validator;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
Added one more converter class for String[]. Then I started getting multiple values which were selected in in UI. Why I have to write two Converter classes. Is there a way to combine both the classes.
public class UserRolesConverter1 implements Converter<String[], List<UserRoles>> {
...
#Override
public List<UserRoles> convert(String[] roles) {

How to Bind the list data thymeleaf html from to spring controller?

This is my Controller class
package com.myblog.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import com.myblog.model.User;
#Controller
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
#GetMapping(value="/user")
public String getUser(Model model){
model.addAttribute("user", new User());
return "user";
}
#PostMapping(value="/user")
public String postUser(#ModelAttribute("user") User user){
log.info("user :"+user);
return "user";
}
}
This is My Model class
user.java
package com.myblog.model;
import java.util.ArrayList;
import java.util.List;
public class User {
private int id;
private String name;
private List<Address> address=new ArrayList<Address>();
#Override
public String toString() {
return "User [name=" + name + ", address=" + address + "]";
}
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 List<Address> getAddress() {
return address;
}
public void setAddress(List<Address> address) {
this.address = address;
}
}
address.java
package com.myblog.model;
public class Address {
private int id;
private String street;
private String city;
public int getAddid() {
return addid;
}
public void setAddid(int addid) {
this.addid = addid;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
This is my thymeleaf HTML page
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Page Title</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet" media="screen" th:href="#{css/bootstrap.min.css}"/>
<script src="/static/js/bootstrap.min.js" th:src="#{js/bootstrap.min.js}"></script>
</head>
<body>
<div class="container">
<h1> User Account</h1>
<form class="form-horizontal" th:action="#{/user}" method="POST" th:object="${user}">
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Full Name</label>
<div class="col-sm-5">
<input type="text" class="form-control" name="name" placeholder="Full name"/>
</div>
</div>
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Address</label>
<div class="col-sm-5">
<input type="text" class="form-control" name="address.city" placeholder="City"/>
</div>
</div>
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Street</label>
<div class="col-sm-5">
<input type="text" class="form-control" name="address.street" placeholder="street" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<input type="submit" class="btn btn-primary" value="Add"/>
</div>
</div>
</form>
</div>
</body>
</html>
in controller user object does not bind the data into address model object.
output is user :user[name="name",address[]]
Your form seems to only manage one adress, but your domain model specifies a list of adresses. In this case you would need to name your input fields like address[0].street for the first address and so on.
So I'd consider to use a thymleaf iterator (th:each) to make all addresses manageable in your form. Then use th:field instead of defining name attributes. This should solve your problem.
<form class="form-horizontal" th:action="#{/user}" method="POST" th:object="${user}">
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Full Name</label>
<div class="col-sm-5">
<input type="text" class="form-control" th:field="*{name}" placeholder="Full name"/>
</div>
</div>
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Address</label>
<div class="col-sm-5">
<input type="text" class="form-control" th:field="*{address[0].city}" placeholder="City"/>
</div>
</div>
<div class="form-group">
<label for="inputDescription" class="col-sm-2 control-label">Street</label>
<div class="col-sm-5">
<input type="text" class="form-control" th:field="*{address[0].street}" placeholder="street" />
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<input type="submit" class="btn btn-primary" value="Add"/>
</div>
</div>
</form>

Resources