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

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)

Related

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

I can not update my entity using Hibernate, Spring MVC, Thymleaf

Hello I want to update User entity, so in the form edit.html i'm using thymeleaf:
<form action="#" th:action="#{/{id}/edit(id=${user.id})}"
th:object="${user}" method="post">
<div class="md-form">
<input type="text" th:field="*{firstName}"
th:value="${user.firstName}" name="firstName" id="firstName"
class="form-control" /> <label class="active" for="firstName">Prénom</label>
</div>
<div class="md-form">
<input type="text" th:field="*{lastName}"
th:value="${user.lastName}" name="lastName" id="lastName"
class="form-control" /> <label class="active" for="lastName">Nom</label>
</div>
<div class="md-form">
<input type="text" th:field="*{email}" th:value="${user.email}"
name="email" id="email" class="form-control" /> <label
class="active" for="email">email</label>
</div>
<div class="md-form">
<input type="text" th:field="*{password}"
th:value="${user.password}" name="password" id="password"
class="form-control" /> <label class="active" for="password">mot
de passe</label>
</div>
<div class="md-form">
<input type="text" th:field="*{occupation}"
th:value="${user.occupation}" name="occupation" id="occupation"
class="form-control" /> <label class="active" for="occupation">profession</label>
</div>
<div class="md-form">
<input type="text" th:field="*{ville}" th:value="${user.ville}"
name="ville" id="ville" class="form-control" /> <label
class="active" for="ville">ville</label>
</div>
<div>
<input class="btn btn-sm btn-primary waves-effect btn-rounded"
type="submit" value="modifier" />
</div>
</form>
User.java:
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
private String userName;
private int age;
private String ville;
private String email;
private String password;
private String phone;
private String company;
private String occupation;
private String img_profil;
#ManyToMany(mappedBy = "users", cascade = { CascadeType.ALL })
private Set<Discussion> discussion;
UserController.java
#GetMapping("/{userName}/edit")
public String editUser(#PathVariable String userName, Model model) {
User user = ur.findByUserName(userName).get(0);
model.addAttribute(user);
return "edit";
}
#PostMapping("/{id}/edit")
public String updateUser(#ModelAttribute("user") User user, #PathVariable("id") Long id) {
user = ur.findOne(id);
ur.save(user);
return "redirect:/find/" + user.getUserName();
}
UserRepository.java
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByUserName(String userName);
}
PROBLEM is in the console I do not see update request (generated by Hibernate), nothing is changed on the database.
Make the following change in UserController.java:
#PostMapping("/{id}/edit")
public String updateUser(
#ModelAttribute("user") User user,
#PathVariable("id") Long id)
{
//user = ur.findOne(id);
user.setId(id);
ur.save(user);
return "redirect:/find/" + user.getUserName();
}

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>

Spring Validation - Errors not displayed

I'm using a combination of Annotation validation and a Custom Validator
Object:
#Entity
#Table(name = "monitoringsystems")
public class MonitoringSystem {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#NotNull(message = "Name must not be empty.")#Size(min=1, message="Name must not be empty.")
private String name;
#NotNull(message = "URL must not be empty.")#Size(min=1, message="Name must not be empty.")
private String url;
#NotNull(message = "Username must not be empty.")#Size(min=1, message="Name must not be empty.")
private String username;
#NotNull(message = "Password must not be empty.")#Size(min=1, message="Name must not be empty.")
private String password;
#NotNull(message = "Confirm Password must not be empty.")#Size(min=1, message="Name must not be empty.")
#Transient
private String passwordConfirm;
CustomValidator:
#Component
public class MonitoringSystemValidator implements Validator {
#Override
public boolean supports(Class<?> type) {
return MonitoringSystem.class.isAssignableFrom(type);
}
#Override
public void validate(Object o, Errors errors) {
MonitoringSystem monitoringSystem = (MonitoringSystem) o;
if(!monitoringSystem.getPassword().equals(monitoringSystem.getPasswordConfirm())){
errors.rejectValue("passwordConfirm", "Passwords are not equal.");
}
}
}
I initialize the custom validator in my controller and set the mapping for the form and the saving method.
Controller:
#Controller
public class MonitoringSystemController {
#Autowired
private MonitoringSystemValidator monitoringSystemValidator;
#InitBinder
public void dataBinding(WebDataBinder binder) {
binder.addValidators(monitoringSystemValidator);
}
#RequestMapping("/monitoringsystem/new")
public String newMonitoringSystem(Model model, HttpServletRequest request) {
MonitoringSystem monitoringSystem = new MonitoringSystem();
model.addAttribute("monitoringSystem", monitoringSystem);
request.getSession().setAttribute("anonymization", monitoringSystem.getAnonymization());
request.getSession().setAttribute("hosts", monitoringSystem.getHosts());
return "monitoringsystem/form";
}
#RequestMapping(value = "/monitoringsystem/save", method = RequestMethod.POST)
public String save(#Valid MonitoringSystem monitoringSystem, BindingResult result, HttpServletRequest request, Model model) {
if(result.hasErrors()){
model.addAttribute("monitoringSystem", monitoringSystem);
request.getSession().setAttribute("anonymization", request.getSession().getAttribute("anonymization"));
request.getSession().setAttribute("hosts", request.getSession().getAttribute("hosts"));
return "monitoringsystem/form";
}
//more code
In a first step I only want to change the CSS of my fields (I use bootstrap) so display the errors.
Form:
<form class="form-horizontal" th:modelAttribute="monitoringSystem" th:object="${monitoringSystem}" th:action="#{/monitoringsystem/save}" method="post">
<input type="hidden" th:field="*{id}"/>
<fieldset>
<legend>New Monitoring-System</legend>
<div class="form-group" th:classappend="${#fields.hasErrors('name')} ?: 'has-error has-danger'">
<label class="col-md-4 control-label" for="textinput">Systemname</label>
<div class="col-md-5">
<input th:field="*{name}" class="form-control input-md" type="text" />
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('url')} ?: 'has-error has-danger'">
<label class="col-md-4 control-label" for="textinput">URL</label>
<div class="col-md-5">
<input th:field="*{url}" class="form-control input-md" type="text" />
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('username')} ?: 'has-error has-danger'">
<label class="col-md-4 control-label" for="textinput">Username</label>
<div class="col-md-5">
<input th:field="*{username}" class="form-control input-md" type="text" />
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('password')} ?: 'has-error has-danger'">
<label class="col-md-4 control-label" for="textinput">Password</label>
<div class="col-md-5">
<input th:field="*{password}" class="form-control input-md" type="password" />
</div>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('passwordConfirm')} ?: 'has-error has-danger'">
<label class="col-md-4 control-label" for="textinput">Confirm Password</label>
<div class="col-md-5">
<input th:field="*{passwordConfirm}" class="form-control input-md" type="password" />
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label" for="singlebutton"></label>
<div class="col-md-4">
<a th:href="#{/monitoringsystem}" class="btn btn-default btn-small">Cancel</a> <button id="singlebutton" name="singlebutton" class="btn btn-primary btn-small">Submit</button>
</div>
</div>
</fieldset>
</form>
My validation is working correctly. The form is only saved if my fields are not null, the size is greater 1 and the password match. If not, my controller redirects me to the form.
The problem is, that my css don't change. So there must be a problem with my view-code or the errorBinding is not passed correctly to the view. But I can't find my mistake.
There was an error in my if condition which add the errorclasses. I had to change ${#fields.hasErrors('url')} ?: 'has-error has-danger' to ${#fields.hasErrors('*{name}')} ? 'has-error has-danger'

#ModelAttribute is not working in spring MVC with post

Hi I am developing my first spring mvc application. I am trying to add a form to db. For this I am using #ModelAttribute and it is not working.
My Controller:
#Controller
public class AddKPI {
#RequestMapping("/getAddKPIForm")
public ModelAndView addKPI(){
ModelAndView modelAndView = new ModelAndView("getAddKPIForm","kpi", new KPI());
String auditInfo = "User : "+getCurrentDateInStringFormat_YYYYMMDD_HHSSMM();
modelAndView.addObject("auditInfo",auditInfo);
return modelAndView;
}
#RequestMapping(value="/addKPITODB")
public ModelAndView add2DB(#ModelAttribute("kpi") KPI kpi){
System.out.println("In controller Method");
System.out.println("kpi.getKpi_name() = "+kpi.getKpi_name());
return new ModelAndView("adding_Success");
}
public static String getCurrentDateInStringFormat_YYYYMMDD_HHSSMM() {
String date_Str = null;
try {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
date_Str = sdf.format(date);
} catch (Exception pe) {
// TODO: Add catch code
pe.printStackTrace();
}
return date_Str;
}
}
My Form Code:
<div align="center">
<div style="width: 650px;">
<form:form class="form-horizontal" method="POST" modelAttribute="kpi" commandName="kpi" action="addKPITODB" >
<form:input type="hidden" name="id" value="122" path="id"></form:input>
<div class="form-group form-group-sm">
<label for="kpi_name" class="col-sm-2 control-label">KPI
Name</label>
<div class="col-sm-5">
<form:input type="text" class="form-control" id="kpi_name"
placeholder="KPI Name" name="kpi_name" required="required"
autofocus="autofocus" path="kpi_name"/>
</div>
</div>
<div class="form-group form-group-sm">
<label for="kpi_sql" class="col-sm-2 control-label">KPI SQL</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="K sql"
name="kpi_sql" id="kpi_sql" required="required">
</div>
</div>
<div class="form-group form-group-sm">
<label for="threshold" class="col-sm-2 control-label">Threshold</label>
<div class="col-sm-2">
<input type="text" class="form-control" placeholder="t"
name="threshold" id="threshold" required="required">
</div>
<label for="Operator" class="col-sm-3 control-label">Threshold
Operator</label>
<div class="col-xs-3">
<select class="form-control input-small" id="Operator"
name="Operator">
<option>G Than</option>
<option>L Than</option>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<label for="category" class="col-sm-2 control-label">Category</label>
<div class="col-xs-3">
<select class="form-control input-small" id="category"
name="category">
<option value="Business Health">Business Health</option>
<option value="Operations Health">Operations Health</option>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<label for="module" class="col-sm-2 control-label"> Module</label>
<div class="col-xs-3">
<select class="form-control input-small" id="module">
<option value="Finance">Finance</option>
<option value="Supply Chain">Supply Chain</option>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<label for="submodule" class="col-sm-2 control-label">Sub
Module</label>
<div class="col-xs-3">
<select class="form-control input-small" id="submodule"
name="submodule">
<option value="A/P (Accounts Payable)">A/P (Accounts
Payable)</option>
<option value="A/R (Accounts Receivable)">A/R (Accounts
Receivable)</option>
<option value="Inventory">Inventory</option>
<option value="Purchase">Purchase</option>
<option value="Sales">Sales</option>
<option value="Manufacturing">Manufacturing</option>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<label for="helptext" class="col-sm-2 control-label">Help
Text</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="helptext"
name="helptext" id="helptext" required="required">
</div>
</div>
<div class="form-group form-group-sm">
<label for="perf_reason" class="col-sm-2 control-label">Reason</label>
<div class="col-sm-10">
<input type="text" class="form-control" placeholder="Reason"
name="perf_reason" id="perf_reason" required="required">
</div>
</div>
<!-- category , module, submodule -->
<!-- Operator , AutoMoniter_Enabled, submodule -->
<div class="form-group form-group-sm">
<label for="Xaxis_Description" class="col-sm-2 control-label">Xaxis_Description</label>
<div class="col-sm-10">
<input type="text" class="form-control"
placeholder="Xaxis_Description" name="Xaxis_Description"
id="Xaxis_Description" required="required">
</div>
</div>
<div class="form-group form-group-sm">
<label for="Yaxis_Desciption" class="col-sm-2 control-label">Yaxis_Desciption</label>
<div class="col-sm-10">
<input type="text" class="form-control"
placeholder="Yaxis_Desciption" name="Yaxis_Desciption"
id="Yaxis_Desciption" required="required">
</div>
</div>
<div class="form-group form-group-sm">
<label for="toEmail" class="col-sm-2 control-label">To
Email</label>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="toEmail"
name="toEmail" id="toEmail" required="required">
</div>
<label for="cc_email" class="col-sm-2 control-label">CC
Email</label>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="cc_email"
name="cc_email" id="cc_email" required="required">
</div>
</div>
<div class="form-group form-group-sm">
<label for="DSchemaName" class="col-sm-2 control-label">Detailed
View</label>
<div class="col-sm-3">
<input type="text" class="form-control" placeholder="DSchemaName"
name="DSchemaName" id="DSchemaName">
</div>
<div class="col-sm-3">
<input type="text" class="form-control" placeholder="DTableName"
name="DTableName" id="DTableName">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="DFieldName"
name="DFieldName" id="DFieldName">
</div>
</div>
<div class="form-group form-group-sm">
<label for="ame" class="col-sm-2 control-label">Auto
Mointer Enabled</label>
<div class="col-xs-3">
<select class="form-control input-small" id="ame"
name="AutoMoniter_Enabled">
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<label for="Audit Info" class="col-sm-2 control-label">Audit
Info</label>
<div class="col-sm-5">
<input type="text" class="form-control" placeholder="Audit Info"
name="audit_info" id="Audit Info" readonly="readonly"
value="${auditInfo }">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div align="left">
<button type="submit" class="btn btn-primary btn-xs">Add
KPI</button>
</div>
</div>
</div>
</form:form>
</div>
</div>
MY KPI class:
#Entity
#Table(name="KPI")
public class KPI {
#Id
private int id;
public KPI(int id) {
super();
this.id = id;
}
public KPI(){
}
private String kpi_name;
private String kpi_sql;
private int threshold;
private String helptext;
private String perf_reason;
private String category;
private String module;
private String submodule;
private String status;
private String toEmail;
private String Operator;
private String AutoMoniter_Enabled;
private String cc_email;
private String audit_info;
private String Xaxis_Description;
private String Yaxis_Desciption;
private String DSchemaName;
private String DTableName;
private String DFieldName;
public String getXaxis_Description() {
return Xaxis_Description;
}
public void setXaxis_Description(String xaxis_Description) {
Xaxis_Description = xaxis_Description;
}
public String getYaxis_Desciption() {
return Yaxis_Desciption;
}
public void setYaxis_Desciption(String yaxis_Desciption) {
Yaxis_Desciption = yaxis_Desciption;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getKpi_name() {
return kpi_name;
}
public void setKpi_name(String kpi_name) {
this.kpi_name = kpi_name;
}
public String getKpi_sql() {
return kpi_sql;
}
public void setKpi_sql(String kpi_sql) {
this.kpi_sql = kpi_sql;
}
public int getThreshold() {
return threshold;
}
public void setThreshold(int threshold) {
this.threshold = threshold;
}
public String getHelptext() {
return helptext;
}
public void setHelptext(String helptext) {
this.helptext = helptext;
}
public String getPerf_reason() {
return perf_reason;
}
public void setPerf_reason(String perf_reason) {
this.perf_reason = perf_reason;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getModule() {
return module;
}
public void setModule(String module) {
this.module = module;
}
public String getSubmodule() {
return submodule;
}
public void setSubmodule(String submodule) {
this.submodule = submodule;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getToEmail() {
return toEmail;
}
public void setToEmail(String toEmail) {
this.toEmail = toEmail;
}
public String getOperator() {
return Operator;
}
public void setOperator(String operator) {
Operator = operator;
}
public String getAutoMoniter_Enabled() {
return AutoMoniter_Enabled;
}
public void setAutoMoniter_Enabled(String autoMoniter_Enabled) {
AutoMoniter_Enabled = autoMoniter_Enabled;
}
public String getCc_email() {
return cc_email;
}
public void setCc_email(String cc_email) {
this.cc_email = cc_email;
}
public String getAudit_info() {
return audit_info;
}
public void setAudit_info(String audit_info) {
this.audit_info = audit_info;
}
public String getDSchemaName() {
return DSchemaName;
}
public void setDSchemaName(String dSchemaName) {
DSchemaName = dSchemaName;
}
public String getDTableName() {
return DTableName;
}
public void setDTableName(String dTableName) {
DTableName = dTableName;
}
public String getDFieldName() {
return DFieldName;
}
public void setDFieldName(String dFieldName) {
DFieldName = dFieldName;
}
}
When I am hitting submit button it is not going to controller method "/addKPITODB" I am getting 404 error(URL is http://localhost:6006/EasyRUN/addKPITODB). If I remove #ModelAttribute it is going to controller method. What is the mistake I am doing. Please correct me.
Your help will be highly appreciate. Thank you.
I created a sample project with your code which works just fine:
git clone https://github.com/denis-zhdanov/spring-playground.git
cd spring-playground/
git checkout so-33429407
export GRADLE_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,address=9999,server=y,suspend=n"
./gradlew jettyRun
Wait until the following line is printed - ':jettyRun > Running at http://localhost:8080/spring-playground'
Connect by remote debugger to the localhost:9999
Set a breakpoint at the org.denis.test.spring.mvc.MyController.add2DB()
Open 'http://localhost:8080/spring-playground/form.html' at the browser
Type any text there and press
The breakpoint is hit

Resources