Why #Valid Class it fails if I create a repository? - spring

I have this controller:
#RequestMapping(value="admin/departamento", method = RequestMethod.POST)
public ModelAndView departamentoGuardar(
#Valid Departamento departamento ,
BindingResult br
){
ModelAndView mav = new ModelAndView();
mav.setViewName("costos/departamento");
return mav;
}
...and it is working.
But, if I build a empty repository class:
#Repository("departamentoRepository")
public interface DepartamentoRepository extends JpaRepository<Departamento, Integer>{
}
My controller throws this when a put a String and only accepts int:
org.springframework.beans.TypeMismatchException: Failed to convert
value of type 'java.lang.String' to required type
'com.carrduci.gestionycontrol.model.Departamento'; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to
convert from type [java.lang.String] to type [java.lang.Integer] for
value 'asdf'; nested exception is java.lang.NumberFormatException: For
input string: "asdf" at
org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:80)
~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] at
org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:52)
~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] at
org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:692)
~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE] at
org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttributeFromRequestValue(ServletModelAttributeMethodProcessor.java:141)
~[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE
My Class:
#Entity
#Table(name = "departamento")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Departamento.findAll", query = "SELECT d FROM Departamento d")})
public class Departamento implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Column(name = "id_departamento")
private Integer idDepartamento;
#Size(max = 20)
#Column(name = "departamento")
private String departamento;
public Departamento() {
}
public Departamento(Integer idDepartamento) {
this.idDepartamento = idDepartamento;
}
public Integer getIdDepartamento() {
return idDepartamento;
}
public void setIdDepartamento(Integer idDepartamento) {
this.idDepartamento = idDepartamento;
}
public String getDepartamento() {
return departamento;
}
public void setDepartamento(String departamento) {
this.departamento = departamento;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idDepartamento != null ? idDepartamento.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Departamento)) {
return false;
}
Departamento other = (Departamento) object;
if ((this.idDepartamento == null && other.idDepartamento != null) || (this.idDepartamento != null && !this.idDepartamento.equals(other.idDepartamento))) {
return false;
}
return true;
}
#Override
public String toString() {
return "com.carrduci.gestionycontrol.model.Departamento[ idDepartamento=" + idDepartamento + " ]";
}
}
UPDATE
<th:block th:include="fragments/encabezados :: encabezados"></th:block>
<div class="container">
<div class="row">
<div class="col-md-offset-4 col-sm-offset-0">
<div class="row">
<div class="col-sm-12"> <h4>Departamento</h4></div>
</div>
<div class="row">
<div class="col-sm-12 col-md-8 ">
<form th:action="${departamento.idDepartamento>0}?
#{/costos/admin/departamento/modificar}:
#{/costos/admin/departamento}"
method="post" th:object="${departamento}">
<div class="row">
<div class="form-group col-xs-12">
<input type="hidden" th:field="*{idDepartamento}">
<div class="input-group">
<span class="input-group-addon">Nombre</i></span>
<input class="form-control input-lg" type="text" th:field="*{departamento}">
<div class="alert alert-danger" th:if="${#fields.hasErrors('departamento')}" th:errors="*{departamento}" ></div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12 text-right">
<a type="button" class="btn btn-danger BOTON_LIMPIAR" href="/index"> <span class=" glyphicon glyphicon-remove"></span> Cancelar</a>
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-floppy-save"></span>
<span th:text="${departamento.idDepartamento>0}?
#{Modificar}:
#{Guardar}">
</span>
</button>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-8 ">
<hr>
<th:block th:include="fragments/tabla :: tabla"></th:block>
</div>
</div>
</div>
</div>
</div>
<th:block th:include="fragments/pieDePagina :: pieDePagina"></th:block>

Related

Neither BindingResult nor plain target object for bean name 'reservationBinding' available as request attribute

I started to work with thymeleaf in a basic project. When I try to put th:field="*{name}" in form, comes error with thymeleaf parsing. Only with th:object="${reservationBinding}" without any th:fields works correctly. I can't understand why doesn't work with th:filed.
Here is my controller where I set the message:
#Controller
public class ReservationController {
#GetMapping("/reservation")
public String checkFOrReservationGet(Model model){
model.addAttribute ("reservationBinding",new ReservationBinding ());
return "index";
}
#PostMapping("/reservation")
public String checkForReservation(#Valid #ModelAttribute() ReservationBinding reservationBinding,
Model model,
BindingResult bindingResult,
RedirectAttributes redirectAttributes,
HttpSession httpSession){
// model.addAttribute ("reservationBinding",new ReservationBinding ());
if(bindingResult.hasErrors ()){
redirectAttributes.addFlashAttribute ("reservationBinding",reservationBinding);
redirectAttributes.addFlashAttribute ("org.springframework.validation.BindingResult.reservationBinding",bindingResult);
return "redirect:#book-a-table";
}
return "redirect:#book-a-table";
}
Here is my html form
<form action="#book-a-table" th:action="#{/reservation}" method="post" th:object="${reservationBinding}" >
<div class="row">
<div class="col-lg-4 col-md-6 form-group" >
<input type="text" name="name" class="form-control" id="name"
placeholder="name" data-rule="minlen:4"
th:field="*{name}"
data-msg="Please enter at least 4 chars">
<div class="validate"></div>
</div>
<div class="col-lg-4 col-md-6 form-group mt-3 mt-md-0">
<input type="email" class="form-control" name="email" id="email" placeholder="Your Email" data-rule="email"
data-msg="Please enter a valid email">
<div class="validate"></div>
</div>
<div class="col-lg-4 col-md-6 form-group mt-3 mt-md-0">
<input type="text" class="form-control" name="phone" id="phone" placeholder="Your Phone" data-rule="minlen:4"
data-msg="Please enter at least 4 chars">
<div class="validate"></div>
</div>
<div class="col-lg-4 col-md-6 form-group mt-3">
<input type="text" name="date" class="form-control" id="date" placeholder="Date" data-rule="minlen:4"
data-msg="Please enter at least 4 chars">
<div class="validate"></div>
</div>
<div class="col-lg-4 col-md-6 form-group mt-3">
<input type="text" class="form-control" name="time" id="time" placeholder="Time" data-rule="minlen:4"
data-msg="Please enter at least 4 chars">
<div class="validate"></div>
</div>
<div class="col-lg-4 col-md-6 form-group mt-3">
<input type="number" class="form-control" name="people" id="people" placeholder="# of people"
data-rule="minlen:1" data-msg="Please enter at least 1 chars">
<div class="validate"></div>
</div>
</div>
<div class="form-group mt-3">
<textarea class="form-control" name="message" rows="5"
placeholder="Message"></textarea>
<div class="validate"></div>
</div>
<div class="mb-3">
<div class="loading">Loading</div>
<div class="error-message"></div>
<div class="sent-message">Your booking request was sent. We will call back or send an Email to confirm your reservation. Thank you!</div>
</div>
<div class="text-center"><button type="submit" >Send Message</button></div>
</form>
This is my bindingModel
public class ReservationBinding {
private String name;
private String email;
private String phone;
private String date;
private String time;
private int People;
private String message;
public ReservationBinding(){
}
// #Length(min = 2, message = "Username length must be minimum two characters!.")
public String getName(){
return name;
}
public ReservationBinding setName(String name){
this.name = name;
return this;
}
#Column(name = "email", nullable = false)
#Email(message = "Enter valid email address.")
public String getEmail(){
return email;
}
public ReservationBinding setEmail(String email){
this.email = email;
return this;
}
#Column(name = "phone", nullable = false)
#Length(min = 9, message = "Enter valid phone number.")
public String getPhone(){
return phone;
}
public ReservationBinding setPhone(String phone){
this.phone = phone;
return this;
}
#Column(name = "date", nullable = false)
public String getDate(){
return date;
}
public ReservationBinding setDate(String date){
this.date = date;
return this;
}
#Column(name = "time")
#Length(min = 2, message = "Enter a valid time for check in.")
public String getTime(){
return time;
}
public ReservationBinding setTime(String time){
this.time = time;
return this;
}
#Min(value = 2, message = "What is the number of the guests")
public int getPeople(){
return People;
}
public ReservationBinding setPeople(int people){
People = people;
return this;
}
public String getMessage(){
return message;
}
public ReservationBinding setMessage(String message){
this.message = message;
return this;
}
}
Do you have any idea, why alone th:object map the properties and when I put th:field doesn't work and comes
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing
(template: "class path resource [templates/index.html]"
Error during execution of processor
'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor'
(template: "index" - line 564, col 17)

How to validate a form with binding result?

I have a simple form to save an User and I can't get it to show the error messages
I have the exact same structure for saving "Customer" and it works, but when I try to replicate it to User It doesn't work
My log error:
2019-08-21 17:07:14.521 WARN 11332 --- [nio-8080-exec-8]
.w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused
by handler execution: org.springframework.validation.BindException:
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'user' on field 'password': rejected value
[123]; codes
[Size.user.password,Size.password,Size.java.lang.String,Size];
arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [user.password,password]; arguments []; default message
[password],2147483647,6]; default message [A senha deve conter pelo
menos 6 caracteres.]
User controllers:
#GetMapping("/{customerId}/createUser")
public ModelAndView userForm(#PathVariable(value = "customerId", required
= false) Long customerId,
#RequestParam(value = "userId", required = false) Long userId,
Model model) {
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
Optional<Users> authenticatedUserOptional =
userRepository.findByEmail(authentication.getName());
model.addAttribute("userLogedIsAdmin",
authenticatedUserOptional.get().getIsAdmin());
if (authentication == null || !authentication.isAuthenticated()) {
ModelAndView mv = new ModelAndView("accessDenied");
return mv;
}
if (!authenticatedUserOptional.isPresent()) {
ModelAndView mv = new ModelAndView("accessDenied");
return mv;
}
if (customerId != null) {
Optional<Customers> customerOptional =
customerRepository.findById(customerId);
Customers customer = customerOptional.get();
model.addAttribute("customer", customer);
if (userId != null) {
Users existingUser = userRepository.findById(userId).get();
if (existingUser.getEnabled()) {
existingUser.setUserStatus(UserStatus.ATIVO);
} else {
existingUser.setUserStatus(UserStatus.INATIVO);
}
model.addAttribute("user", existingUser);
} else {
model.addAttribute("user", new Users());
}
ModelAndView mv = new ModelAndView("customerNewUser");
return mv;
} else {
ModelAndView mv = new ModelAndView("accessDenied");
return mv;
}
}
#PostMapping("/{customerId}/createUser")
public ModelAndView saveUser(#PathVariable(value = "customerId", required
= true) Long customerId,
#ModelAttribute(name = "user") #Valid Users user,
RedirectAttributes redirectAttributes,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return userForm(customerId, user.getId(), new Model() {
#Override
public Model mergeAttributes(Map<String, ?> attributes) {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean containsAttribute(String attributeName) {
// TODO Auto-generated method stub
return false;
}
#Override
public Map<String, Object> asMap() {
// TODO Auto-generated method stub
return null;
}
#Override
public Model addAttribute(String attributeName, Object
attributeValue) {
// TODO Auto-generated method stub
return null;
}
#Override
public Model addAttribute(Object attributeValue) {
// TODO Auto-generated method stub
return null;
}
#Override
public Model addAllAttributes(Map<String, ?> attributes) {
// TODO Auto-generated method stub
return null;
}
#Override
public Model addAllAttributes(Collection<?> attributeValues)
{
// TODO Auto-generated method stub
return null;
}
});
}
// Encrypt password
if (user.getPassword().equals(user.getMatchPassword())) {
user.setPassword(encoder.encode(user.getPassword()));
user.setCustomerId(customerId);
user.setEventDescription("User Admin creation");
Users returnedUser = userService.save(user);
List<Authorities> authorities = new ArrayList<Authorities>();
Authorities auth = new Authorities(new
AuthoritiesPK(returnedUser.getId(), "ROLE_CLI_ADM"), returnedUser,
"ROLE_CLI_ADM");
authorities.add(auth);
returnedUser.setAuthorities(authorities);
returnedUser.setEventDescription("Add Admin role");
for (int i = 0; i < returnedUser.getAuthorities().size(); i++) {
authorityService.save(returnedUser.getAuthorities().get(i));
}
userService.save(returnedUser);
ModelAndView mv = new ModelAndView("redirect:/customers/" +
customerId);
return mv;
} else {
ModelAndView mv = new ModelAndView("accessDenied");
return mv;
}
}
form html:
<div class="card mb-3">
<div class="card-header"
th:text="${user?.id} ? #{editUser} : #{newUser}">
<i class="fas fa-table"></i>
</div>
<div class="card-body">
<form
th:action="#{${user?.id} ? '/customers/' + ${customer.id} + '/createUser/' + ${user.id} : '/customers/' + ${customer.id} + '/createUser/'}"
th:object="${user}" action="#" method="post">
<div class="alert alert-danger" th:if="${#fields.hasAnyErrors()}">
<div th:each="detailedError : ${#fields.detailedErrors()}">
<span th:text="${detailedError.message}"></span>
</div>
</div>
<div class="form-group">
<div class="form-row">
<div class="col-md-5">
<label class="text-right label-control"
th:text="#{firstname} + ':'">Firstname:</label>
</div>
<div class="col-md-4">
<input type="text" id="firstname" name="firstname"
th:value="${user?.firstname} ? ${user?.firstname} : ''"
class="form-control" th:placeholder="#{firstname}"
required="required" autofocus="autofocus"
th:field="*{firstname}" />
</div>
</div>
</div>
<div class="form-group">
<div class="form-row">
<div class="col-md-5">
<label class="text-right label-control"
th:text="#{surname} + ':'">Surname:</label>
</div>
<div class="col-md-4">
<input type="text" id="surname" name="surname"
th:value="${user?.surname} ? ${user?.surname} : ''"
class="form-control" th:placeholder="#{surname}"
autofocus="autofocus" />
</div>
</div>
</div>
<div class="form-group">
<div class="form-row">
<div class="col-md-5">
<label class="text-right label-control"
th:text="#{email} + ':'">Email:</label>
</div>
<div class="col-md-4">
<input th:placeholder="#{email}" required="required"
autofocus="autofocus" id="email" class="form-control"
type="text" th:value="${user?.email} ? ${user?.email} : ''"
name="email" th:field="*{email}" />
</div>
</div>
</div>
<div class="form-group" th:if="!${user?.id}">
<div class="form-row">
<div class="col-md-5">
<label class="text-right label-control"
th:text="#{password} + ':'">Password:</label>
</div>
<div class="col-md-4">
<input type="password" id="password" name="password"
class="form-control" th:placeholder="#{password}"
required="required" autofocus="autofocus"
th:field="*{password}" />
</div>
</div>
</div>
<div class="form-group" th:if="!${user?.id}">
<div class="form-row">
<div class="col-md-5">
<label class="text-right label-control"
th:text="#{passwordConfirmation} + ':'">Password
confirmation:</label>
</div>
<div class="col-md-4">
<input type="password" id="matchPassword" name="matchPassword"
class="form-control" th:placeholder="#{password}"
required="required" autofocus="autofocus"
th:field="*{matchPassword}" />
</div>
</div>
</div>
<div class="form-group" th:if="${user?.id}">
<div class="form-row">
<div class="col-md-5">
<label class="text-right label-control"
th:text="#{userStatus} + ':'">Status:</label>
</div>
<div class="col-md-3">
<select class="form-control form-control" id="userStatus"
name="userStatus">
<option
th:each="userStatus : ${T(br.com.macrosul.stetho.entity.UserStatus).values()}"
th:text="${userStatus}" th:value="${userStatus}"
th:selected="${user.userStatus} eq ${userStatus}"></option>
</select>
</div>
</div>
</div>
<div class="form-group" id="saveDiv">
<div class="form-row">
<div class="col-md-5"></div>
<div class="col-md-2">
<a class="btn-nounderline" href="#"> <input type="submit"
class="btn btn-md btn-block" value="Save"
th:value="${user?.id} ? #{updateUser} : #{save}" id="save" />
</a>
</div>
</div>
</div>
</form>
</div>
</div>
part of my model:
#Entity
public class Users extends BaseEntity {
private static final long serialVersionUID = -1667698094711992210L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"users_seq")
#SequenceGenerator(name = "users_seq", sequenceName = "users_seq",
allocationSize = 50, initialValue = 1)
#JsonProperty(access = Access.READ_ONLY)
private Long id;
#NotBlank(message = "E-mail não pode estar em branco.")
#NotNull(message = "E-mail deve ser informado.")
#Email(message = "Formato inválido de E-mail.")
#Column(nullable = false, unique = true)
private String email;
#JsonProperty(access = Access.WRITE_ONLY)
#Size(min=6, message="A senha deve conter pelo menos 6 caracteres.")
#NotNull(message = "A senha deve ser informada.")
#NotBlank(message = "A senha não pode estar em branco.")
#NotEmpty(message = "A senha não pode estar vazia.")
#Column(nullable = false)
private String password;
#JsonIgnore
#Transient
private String matchPassword;
#JsonIgnore
#Column(nullable = false)
private Boolean enabled = true;
#NotNull(message = "O nome deve ser informada.")
#NotBlank(message = "O nome não pode estar em branco.")
#NotEmpty(message = "O nome não pode estar vazia.")
#Column(nullable = false)
private String firstname;
private String surname;
#Column(nullable = true)
private Long customerId;
#JsonIgnore
#Transient
private Boolean isAdmin;
#JsonIgnore
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
private List<Authorities> authorities = new ArrayList<>();
#Enumerated(EnumType.STRING)
#Transient
private UserStatus userStatus;
}
I simply can't understand why it does not show the error message, I'm pretty sure what's logged is not en error itself... Any help would be appreciated!
Might not be what is failing, but bindingresult has to follow the parameter it is validating. You can see more details on the answers here
So change:
public ModelAndView saveUser(#PathVariable(value = "customerId", required = true) Long customerId,
#ModelAttribute(name = "user") #Valid Users user, RedirectAttributes redirectAttributes,
BindingResult bindingResult) { ... }
To:
public ModelAndView saveUser(#PathVariable(value = "customerId", required = true) Long customerId,
RedirectAttributes redirectAttributes, #ModelAttribute(name = "user") #Valid Users user,
BindingResult bindingResult) { ... }

load form Fragment thymelef ajax spring boot

I am working with spring boot and thymeleaf, I want to load a fragment with ajax. It loads well, but when sending it the fragment object is not sent with the main object.
Here is the code that I use.
Model
#Entity
#Table(name = "solicitudes")
public class Solicitud {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_solicitud")
private Integer id;
#Column(name = "descripcion")
private String descripcion;
#ManyToOne
#JoinColumn(name = "id_persona") //,nullable=false
private Persona persona;
.
.
.
}
#Entity
#Table(name = "personas")
public class Persona {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_persona")
private Long id;
#Column(name = "razon_social")
private String razonSocial;
#Column(name = "dni")
private Integer dni;
.
.
.
}
Controller
#RequestMapping(value = "/solicitudes/nuevo", method = RequestMethod.GET)
public ModelAndView newGet() {
ModelAndView modelAndView = new ModelAndView();
Solicitud solicitud = new Solicitud();
modelAndView.addObject("solicitud", solicitud);
modelAndView.setViewName("solicitudes/solicitudForm");
return modelAndView;
}
//Controller return fragment
#RequestMapping(value = "/solicitudes/{dni}", method = RequestMethod.GET)
public String showPersonaFragment(Model model, #PathVariable("dni") String dni) {
Persona persona = personaService.findPersonaByDni(Integer.parseInt(dni));
model.addAttribute("obraSociales", obraSocialService.listAllObraSocial());
model.addAttribute("pcias", pciaService.listAllProvincia());
model.addAttribute("localidades", localidadService.getAllLocalidades());
model.addAttribute("nivelesIntruccion", nivelIntruccionServices.listAllNivelInstruccion());
model.addAttribute("persona", persona);
return "solicitudes/formPersonaFrag:: header";
}
solicitudForm
<div class="form-group">
<div class="col-sm-5">
<label for="dni">Nro. de Documento</label>
<input type="number" id="dni" placeholder="Nro. de Documento."
class="form-control" required="required"/>
</div>
<div class="col-sm-5">
<br> <p id="mensajePersona" class="help-block"></p>
</div>
</div>
<div class="tab-pane" id="datosPersonales">
<div id="personaFragment">
<div class="alert alert-danger" role="alert">
<span>Debe ingresar el Nro. de Documento</span>
</div>
</div>
<div class="row margin-bottom"></div>
</div>
formPersonaFrag
<div th:fragment="formPersonaFrag">
<div th:fragment="header">
<div>
<fieldset id="datos_personales">
<div>
<input type="hidden" th:field="*{persona.id}" class="form-control" />
</div>
<div class="form-group">
<div class="col-sm-9">
<label for="razonSocial">Apellido y Nombre</label>
<div th:if="${persona.razonSocial==null}">
<input type="text" th:field="*{persona.razonSocial}" placeholder="Apellido y Nombre"
class="form-control" required="required" />
<div class="has-error">
<label th:if="${#fields.hasErrors('persona.razonSocial')}"
th:errors="*{persona.razonSocial}"
class="control-label"></label>
</div>
</div>
<div th:if="${persona.razonSocial!=null}">
<span th:text="*{persona.razonSocial}" ></span>
</div>
</div>
</div>
</fieldset>
</div>
</div> </div>
Ajax load fragment
$('#dni').change(function (e) {
var datos = $("#dni").val();
var url = '/solicitudes/' + datos;
console.log(url);
$("#personaFragment").load(url,$("#personaFragment").serialize());
$.ajax({
type: "GET",
contentType: "application/json",
url: "/api/persona/dni/" + datos,
data: JSON.stringify(datos),
dataType: 'json',
cache: false,
timeout: 600000,
success: function (data) {
$('#mensajePersona').empty();
},
error: function (e) {
$('#mensajePersona').empty();
console.log("ERROR : ", e);
}
});
in debug object solicitud.persona is null
debug app

Unable to bind thymeleaf template and spring boot correctly

I am working on registration in spring boot with spring security and thymeleaf but for some reason the userForm.getUsername() gives null value during POST (see code below)
Person.java
#Entity#Table(name = "person")
public class Person {
#Id#Column(name = "username")
private String username;
#Column(name = "mobile")
private String mobile;
#JsonIgnore#Column(name = "password")
private String password;
#Transient#JsonIgnore
private String passwordConfirm;
#ManyToMany(cascade = CascadeType.ALL)#JoinTable(name = "bookandperson", joinColumns = #JoinColumn(name = "username"), inverseJoinColumns = #JoinColumn(name = "bookName"))
private List < Book > listOfBooks = new ArrayList < Book > ();
}
PersonController.java
#Controller
public class PersonController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model, Principal user) {
if (user != null) {
return "redirect:/";
}
model.addAttribute("userForm", new Person());
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute Person userForm, BindingResult bindingResult, Model model) {
System.out.println(userForm.getUsername()); //This is giving null value
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
System.out.println("binding result has errors");
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/";
}
registration.html
<head>
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
</head>
<body>
<nav th:replace="common/navbar :: common-navbar"/>
<div class="container mt-4">
<div class="row justify-content-center">
<div class="col-md-6 col-md-offset-6">
<form th:action="#{/registration}" method="post">
<div class="form-group row">
<label for="inputUsername" class="col-sm-2 col-form-label">Username</label>
<div class="col-md-6">
<input type="text" class="form-control" th:field="${userForm.username}" id="inputUsername" value="" placeholder="Username">
</div>
</div>
<div class="form-group row">
<label for="mobile" class="col-sm-2 col-form-label">Mobile</label>
<div class="col-md-6">
<input type="text" class="form-control" th:field="${userForm.mobile}" id="inputMobile" placeholder="Mobile">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">Password</label>
<div class="col-md-6">
<input type="password" class="form-control" th:field="${userForm.password}" id="inputPassword" placeholder="Password">
</div>
</div>
<div class="form-group row">
<label for="inputPasswordConfirm" class="col-sm-2 col-form-label">Confirm Password</label>
<div class="col-md-6">
<input type="password" class="form-control" th:field="${userForm.passwordConfirm}" id="inputPasswordConfirm" placeholder="Password">
</div>
</div>
<div class="form-group row">
<div class="offset-2 col-sm-10">
<button type="submit" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" class="btn btn-primary">Submit</button>
</div>
</div>
<small th:text="${error}"></small>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</body>
I binded correctly using th:field="${userForm.username}" but unable to find what is the problem here.
you have to take the model object into the form as follows
<form action="#" th:action="#{/registration}" th:object="${userForm}" method="post">
and add the getters and setters to the Person class

th:if="${#fields.hasErrors()}" causes Exception evaluating SpringEL expression

I'm trying to do validation on 1 field of the form as you guys can see:
<div id ="EditModal" class="modal fade" role="dialog">
<form class="modal-dialog" th:action="#{/Edit}" th:object="${person1}" method="POST">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<input type="hidden" id="edit-modal-person-id" name="id" value=""/>
<input type="text" placeholder="Name" id="edit-modal-person-name" name="name"/>
<p th:if="${#fields.hasErrors('name')}" th:errors="*{name}" th:class="'error'">something</p>
<div>
<a class="btn btn-default pull-right" id="PhoneNumberEdit">Edit Phone Number</a>
</div>
</div>
<div class="modal-footer">
<button type="submit" id="SubmitEdit" class="btn btn-default" >Submit</button>
<button type="button" class = "btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</form>
</div>
the attribute th:if="${#fields.hasErrors('name')}" always causes the 500 error for me.
my controller:
#RequestMapping(value = "/Edit", method = RequestMethod.POST)
public String editPerson(#Valid #ModelAttribute(value="person1") PersonRequest person, BindingResult result) {
if(result.hasErrors()) {
return "redirect:All";
}
else {
personService.update(person.getId(), person.getName());
return "redirect:All";
}
}
my entity:
public class PersonRequest {
#NotNull
private long id;
#NotEmpty
#Name
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public PersonRequest() {
super();
}
}
the console return this following error:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'person1' available as request attribute.
But I think that doesnt have anything to do with this because if I remove p tag it runs normally.
The problem is that you make a redirect, (you make a "redirect:All").
Because of the redirect, you do not pass object person1 thus the error "java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'person1' available as request attribute".
If you want post the code of the /all requestMapping that you have
Probably you want something like this
#RequestMapping(value = "/Edit", method = RequestMethod.POST)
public String editPerson(#Valid #ModelAttribute(value="person1") PersonRequest person, BindingResult result) {
if(result.hasErrors()) {
return "edit";//change it to the name of the html page that you want to go
}
else {
//probably here you return in the page with all the persons
personService.update(person.getId(), person.getName());
return "redirect:All";
}
}

Resources