Spring form data is not received in controller with mustache - spring

I'm using a simple Spring form with mustache. However the data is not received in Spring controller. login.getId(), login.getPass() are always received as null in controller. Any clues if something have to be fixed in template or controller?
My template and controller code as below.
<form class="form-signin" id="loginForm" action="{{{appCtxt}}}/login" method="post">
<label for="inputEmail" class="sr-only">Email address</label>
<input type="email" name="{{id}}" id="id" class="form-control" placeholder="Email address" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="{{pass}}" id="pass" class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
Controller
#Controller
public class LoginController {
private LoginService loginService;
#Autowired
public void setLoginService(LoginService loginService) {
this.loginService = loginService;
}
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView index(HttpServletRequest request, Model model) {
ModelAndView result = new ModelAndView();
model.addAttribute("login", new Login());
result.addObject("resources", request.getContextPath() + "/resources");
result.addObject("appCtxt", request.getContextPath());
// return "redirect:/users";
result.setViewName("home");
return result;
}
#RequestMapping(value = "login", method = RequestMethod.POST)
public String login(Login login, HttpServletRequest request){
boolean status = loginService.verifyLogin(login.getId(), login.getPass());
if(status == true) {
return "redirect:/users";
}
else
{
return "error";
}
}
}

Instead of the name="{{pass}}" you can use name="pass" assuming you Login class contains a field with the very same name. Another thing is that you need '#ModelAttribute' annotation near the Login parameter.
For easier understanding how it works, please consider following example:
Student.java
package me.disper.model;
public class Student {
private String name;
private String surname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
student.html
<!DOCTYPE html>
<html lang="en" xmlns:form="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>Create new student</title>
</head>
<body>
<form name="student" action="add" method="post">
Name: <input type="text" name="name" /><br/>
Surname: <input type="text" name="surname" /><br/>
<input type="submit" value="Save" />
</form>
</body>
</html>
MyMustacheController.java
package me.disper;
import me.disper.model.Student;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class MyMustacheController {
#GetMapping("/student")
public ModelAndView createStudent(){
ModelAndView modelAndView = new ModelAndView("student", "student", new Student());
return modelAndView;
}
#PostMapping("/add")
public ModelAndView addStudent(#ModelAttribute Student student){
ModelAndView modelAndView = new ModelAndView("created", "student", student);
return modelAndView;
}
}
created.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Student created</title>
</head>
<body>
{{#student}}
Hello {{name}} {{surname}}
{{/student}}
</body>
</html>

Take a look at the following tutorial: A guide to forms in Spring MVC. There are some helpful hints like #ModelAttribute.

Related

Request method 'GET' not supported Spring Boot

I'm a beginer full stack developer. I need help.
I have the following code:
Controller:
#Controller
public class GreetingController {
#Autowired
private MessageRepos messageRepos;
#GetMapping("/")
public String greeting(Map<String, Object> model) {
return "greeting";
}
#GetMapping("/main")
public String main(Map<String, Object> model) {
Iterable<Message> messages = messageRepos.findAll();
model.put("messages", messages);
return "main";
}
#PostMapping("/main")
public String add(#RequestParam String text, #RequestParam String tag, Map<String, Object> model) {
Message message = new Message(text, tag);
messageRepos.save(message);
Iterable<Message> messages = messageRepos.findAll();
model.put("messages", messages);
return "main";
}
#PostMapping("filter")
public String filter(#RequestParam String filter, Map<String, Object> model) {
Iterable<Message> messages;
if (filter != null && !filter.isEmpty()) {
messages = messageRepos.findByTag(filter);
} else {
messages = messageRepos.findAll();
}
model.put("messages", messages);
return "main";
}
HTML:
</div>
<div>
<form method="post">
<input type="text" name="text" placeholder="Message" />
<input type="text" name="tag" placeholder="Tag">
<button type="submit">Add</button>
</form>
</div>
<div>
<form method="post" action="filter">
<input type="text" name="filter">
<button type="submit">Find</button>
</form>
</div>
When I click on the buttons add and find I get the problem.
Problem:
Request method 'GET' not supported.

Spring tags form do not show validation errors in jsp

I am writing a page with user registration. Faced a display problem in the form of validation errors
My Controller:
#Controller
public class UIController {
private final Logger log = LoggerFactory.getLogger(getClass());
#Autowired
private UserService service;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator validator;
#PostMapping(value = "/login")
public String signIn(#ModelAttribute("userForm") UserTo userForm, BindingResult bindingResult, Model model) {
validator.validate(userForm, bindingResult);
User user = service.findByLogin(UserUtil.createNewFromTo(userForm).getLogin());
if (!userForm.getPassword().equals(user.getPassword())) {
log.info("invalid password {}", user);
return "redirect:/login";
}
log.info("signIn {}", user);
securityService.autologin(user.getLogin(), user.getPassword());
return "redirect:/welcome";
}
}
My Validator:
#Component
public class UserValidator implements Validator {
#Autowired
private UserRepositoryImpl userRepository;
#Override
public boolean supports(Class<?> aClass) {
return UserTo.class.equals(aClass);
}
#Override
public void validate(Object o, Errors errors) {
UserTo user = (UserTo) o;
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "login", "NotEmpty");
if (user.getLogin().length() < 6 || user.getLogin().length() > 32) {
errors.rejectValue("login", "Size.userForm.login");
}
if (userRepository.findByLogin(user.getLogin()) != null) {
errors.rejectValue("login", "Duplicate.userForm.login");
}
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "NotEmpty");
if (user.getPassword().length() < 8 || user.getPassword().length() > 32) {
errors.rejectValue("password", "Size.userForm.password");
}
}
}
My jsp form :
<div id="wrapper">
<!--SLIDE-IN ICONS-->
<div class="user-icon"></div>
<div class="pass-icon"></div>
<!--END SLIDE-IN ICONS-->
<!--LOGIN FORM-->
<form:form name="login-form" modelAttribute="userForm" class="login-form" method="post" id="form">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<!--CONTENT-->
<div class="content">
<!--USERNAME-->
<spring:bind path="login">
<div class="form-group ${status.error ? 'has-error' : ''}">
<form:input name="login" id="login" type="text" path="login" class="input username"
placeholder="Login"></form:input>
<form:errors path="login"></form:errors>
</div>
</spring:bind>
<!--END USERNAME-->
</div>
<!--END CONTENT-->
<!--FOOTER-->
<div class="footer">
<button class="button" type="submit">Login</button>
<button class="register" type="button" name="submit" onclick=" register_url('${contextPath}/registration')">
Register
</button>
</div>
<!--END FOOTER-->
</form:form>
</div>
When debugging in chrome when sending a POST request, a 302 HTTP error appears.
Accordingly, if I set a breakpoint in the controller, then the debug is not processed.
Tell me what could be the problem?
The "form" tag in your jsp does not have "action" attribute.
You should not redirect on errors, because the redirect will erase the binding result. Instead do :
if (!userForm.getPassword().equals(user.getPassword())) {
log.info("invalid password {}", user);
return "login";
}

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

I'm facing an issue with spring and thymeleaf, i'm trying to fill a form with data from an entity called cliente, but i'm getting a Whitelabel Error Page message in the browser and this message in the console
Neither BindingResult nor plain target object for bean name 'cliente' available as request attribute
this is the Cliente
package com.bolsadeideasspringboot.app.models.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import org.springframework.format.annotation.DateTimeFormat;
#Entity
#Table(name="clientes")
public class Cliente implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotEmpty
private String nombre;
#NotEmpty
private String apellido;
#NotEmpty
#Email
private String email;
#Column(name="create_at")
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern="dd/MM/yyyy")
private Date createAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellido() {
return apellido;
}
public void setApellido(String apellido) {
this.apellido = apellido;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getCreateAt() {
return createAt;
}
public void setCreateAt(Date createAt) {
this.createAt = createAt;
}
}
this is the controller method
#RequestMapping(value="/form/{id}")
public String editar(#ModelAttribute("form") #PathVariable(value="id")Long id, Map<String, Object>model) {
Cliente cliente = null;
if(id > 0) {
clientedao.findOne(id);
model.put("cliente", cliente);
model.put("titulo", "Editar Cliente");
return "form";
}
else {
return "redirect:/listar";
}
}
this is the ClienteDaoImpl.java method
#Override
public Cliente findOne(Long id) {
// TODO Auto-generated method stub
return em.find(Cliente.class, id);
}
this is the Dao interface method
public Cliente findOne(Long id);
and this is the form
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title th:text="${titulo}">Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-4 col-md-offset-3">
<h1 class="text-success" th:text="${titulo}"></h1>
<form th:action="#{/form}" th:object="${cliente}" method="post">
<div class="form-group">
<label>Nombre</label>
<input class="form-control" type="text" th:field="*{nombre}" placeholder="Nombre"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('nombre')}" th:errors="*{nombre}"></small>
</div>
<div class="form-group">
<label>Apellido</label>
<input class="form-control" type="text" th:field="*{apellido}" placeholder="Apellido"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('apellido')}" th:errors="*{apellido}"></small>
</div>
<div class="form-group">
<label>Email</label>
<input class="form-control" type="text" th:field="*{email}" placeholder="correo#ejemplo.com"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></small>
</div>
<div class="form-group">
<label>Fecha</label>
<input class="form-control" type="text" th:field="*{createAt}" placeholder="DD/MM/YYYY"/>
<small class="form-text text-danger" th:if="${#fields.hasErrors('createAt')}" th:errors="*{createAt}"></small>
</div>
<div class="form-group">
<input class="btn btn-primary" type="submit" value="Crear Cliente" />
</div>
<input type="hidden" th:field="*{id}" />
</form>
</div>
</div>
</div>
</body>
</html>
i'm setting the cliente in the controller method and i'm using th:object in the form, so i don't know what i'm doing wrong, any help would be helpul, thanks in advice
Instead of put(), try using the recommended approach to adding an object to your model with
model.addAttribute("cliente", clientedao.findOne(id));
You typically want to use #GetMapping as well for your requests to populate the form. And use #PostMapping for submissions.
Aside: also take a look at Project Lombok to make your beans less error-prone and more readable. You could remove all those getters and setters and just annotate the class with #Data.
While not deprecated, you'll also want to move away from using java.util.Date and use the newer date/time classes.

spring-security:HTTP Status 405 - Request method 'POST' not supported

I have checked so many answers here for the same but it seems nothing worked for me. I have spring security with spring mvc. when my user is trying to sign up I am sending post data to my controller. but it is giving me 405 post not supported I have disabled csrf token in security config. please let me know where did I go wrong?
Here's my webSecurityConfigureDapter:
package org.pkb.springlogin.config;
import org.pkb.springlogin.authentication.MyDBAuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
// #EnableWebSecurity = #EnableWebMVCSecurity + Extra features
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
MyDBAuthenticationService myDBAauthenticationService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Users in memory.
auth.inMemoryAuthentication().withUser("user1").password("12345").roles("USER");
auth.inMemoryAuthentication().withUser("admin1").password("12345").roles("USER, ADMIN");
// For User in database.
auth.userDetailsService(myDBAauthenticationService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// The pages does not require login
http.authorizeRequests().antMatchers("/", "/welcome", "/login", "/logout","/signUp").permitAll();
// /userInfo page requires login as USER or ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers("/userInfo").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers("/admin").access("hasRole('ROLE_ADMIN')");
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will throw.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/login")//
.defaultSuccessUrl("/userInfo")//
.failureUrl("/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
// Config for Logout Page
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/logoutSuccessful");
}
}
Here's my sign up page
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%# page isELIgnored="false"%>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<html lang="en">
<head>
<link rel="stylesheet" href="<c:url value="/resources/css/bootstrap-theme.min.css"/>">
<link rel="stylesheet" href="<c:url value="/resources/css/bootstrap.min.css"/>">
<title>Sign Up Form</title>
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
</head>
<body>
<div class="jumbotron page-header">
<h2>Login</h2>
</div>
<form:form class="form-horizontal" method="post"
name="userReg" id="userReg" modelAttribute="userForm" action="${contextPath}/login">
<div class="container">
<label class="col-sm-2 control-label">Name</label>
<div class="col-sm-4">
<input name="userName" type="text" class="form-control" id="userName" placeholder="Name" />
</div>
</div>
<br>
<div class="container">
<label class="col-sm-2 control-label">Email</label>
<div class="col-sm-4">
<input name="email" class="form-control" id="email" placeholder="Email" />
</div>
</div>
<br>
<div class="container">
<label class="col-sm-2 control-label">Date of Birth(dd-mm-yyyy)</label>
<div class="col-sm-4">
<input name="dob" type="text" class="form-control" id="dob" placeholder="Date of birth" />
</div>
</div>
<br>
<div class="container">
<label class="col-sm-2 control-label">Password</label>
<div class="col-sm-4">
<input name="password" type="password" class="form-control" id="password" placeholder="password" />
</div>
</div>
<br>
<div class="container">
<label class="col-sm-2 control-label">Confirm Password</label>
<div class="col-sm-4">
<input name="confirmPassword" type="password" class="form-control" id="cpassword" placeholder="confirm password" />
<span id='message'></span>
</div>
</div>
<br>
<div class="container">
<label class="col-sm-2 control-label">User type</label>
<div class="col-sm-4">
<select class="form-control" name="type" >
<option selected="selected">--select--</option>
<option value="user" >User</option>
<option value="admin">Admin</option>
</select>
</div>
</div>
<br>
<br>
<div class="col-md-6 center-block">
<input type="submit" class="btn-lg btn-primary center-block" value="save">
</div>
</form:form>
</body>
<script type = "text/javascript"
src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.validation/1.15.1/jquery.validate.min.js"></script>
<script src="<c:url value="/resources/js/form-validation.js"/>"></script>
<script src="<c:url value="/resources/js/passwordVerification.js"/>"></script>
</html>
Here's my MainController
package org.pkb.springlogin.controller;
import java.security.Principal;
import org.pkb.springlogin.manager.SignUpHandler;
import org.pkb.springlogin.model.SignUpInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class MainController {
#Autowired
SignUpHandler signupHandler;
private static final Logger logger =LoggerFactory.getLogger(MainController.class);
#RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
public String welcomePage(Model model) {
model.addAttribute("title", "Welcome");
model.addAttribute("message", "Hello friend!");
return "welcomePage";
}
#RequestMapping(value = "/admin", method = RequestMethod.GET)
public String adminPage(Model model) {
return "adminPage";
}
#RequestMapping(value="/signUp",method=RequestMethod.POST)
public String userLogin(#ModelAttribute("userForm") SignUpInfo user,ModelMap model){
System.out.println(user);
Integer id=signupHandler.process(user);
if(id!=null){
logger.debug("ID in controller:"+id);
return "success";
}
logger.error("error in controller");
return "Failure";
}
#RequestMapping(value="/signUp",method=RequestMethod.GET)
public String register(Model model){
SignUpInfo user=new SignUpInfo();
model.addAttribute("userForm", user);
return "signUp";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Model model ) {
return "loginPage";
}
#RequestMapping(value = "/logoutSuccessful", method = RequestMethod.GET)
public String logoutSuccessfulPage(Model model) {
model.addAttribute("title", "Logout");
return "logoutSuccessfulPage";
}
#RequestMapping(value = "/userInfo", method = RequestMethod.GET)
public String userInfo(Model model, Principal principal) {
// After user login successfully.
String userName = principal.getName();
System.out.println("User Name: "+ userName);
return "userInfoPage";
}
#RequestMapping(value = "/403", method = RequestMethod.GET)
public String accessDenied(Model model, Principal principal) {
if (principal != null) {
model.addAttribute("message", "Hi " + principal.getName()
+ "<br> You do not have permission to access this page!");
} else {
model.addAttribute("msg",
"You do not have permission to access this page!");
}
return "403Page";
}
}
Here's my signUpInfo
package org.pkb.springlogin.model;
public class SignUpInfo {
private String userName;
private String password;
private String confirmPassword;
private Type type;
private Byte enabled;
public Byte getEnabled() {
return enabled;
}
public void setEnabled(Byte enabled) {
this.enabled = enabled;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getConfirmPassword() {
return confirmPassword;
}
public void setConfirmPassword(String confirmPassword) {
this.confirmPassword = confirmPassword;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
#Override
public String toString() {
return "SignUpInfo [userName=" + userName + ", password=" + password + ", confirmPassword=" + confirmPassword
+ ", type=" + type + "]";
}
}
Form is POST-ed to /login
action="${contextPath}/login"
but login is annotated to support only GET
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Model model ) {
return "loginPage";
}
maybe you should post to /signUp

Spring Boot multiple controllers with same mapping

My problem is very similar with this one: Spring MVC Multiple Controllers with same #RequestMapping
I'm building simple Human Resources web application with Spring Boot. I have a list of jobs and individual url for each job:
localhost:8080/jobs/1
This page contains job posting details and a form which unauthenticated users -applicants, in this case- can use to apply this job. Authenticated users -HR Manager-, can see only posting details, not the form. I have trouble with validating form inputs.
What I tried first:
#Controller
public class ApplicationController {
private final AppService appService;
#Autowired
public ApplicationController(AppService appService) {
this.appService = appService;
}
#RequestMapping(value = "/jobs/{id}", method = RequestMethod.POST)
public String handleApplyForm(#PathVariable Long id, #Valid #ModelAttribute("form") ApplyForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "job_detail"; //HTML page which contains job details and the application form
}
appService.apply(form, id);
return "redirect:/jobs";
}
#RequestMapping(value = "/applications/{id}", method = RequestMethod.GET)
public ModelAndView getApplicationPage(#PathVariable Long id) {
if (null == appService.getAppById(id)) {
throw new NoSuchElementException(String.format("Application=%s not found", id));
} else {
return new ModelAndView("application_detail", "app", appService.getAppById(id));
}
}
}
As you guess this didn't work because I couldn't get the models. So I put handleApplyForm() to JobController and changed a little bit:
#Controller
public class JobController {
private final JobService jobService;
private final AppService appService;
#Autowired
public JobController(JobService jobService, AppService appService) {
this.jobService = jobService;
this.appService = appService;
}
#RequestMapping(value = "/jobs/{id}", method = RequestMethod.POST)
public ModelAndView handleApplyForm(#PathVariable Long id, #Valid #ModelAttribute("form") ApplyForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return getJobPage(id);
}
appService.apply(form, id);
return new ModelAndView("redirect:/jobs");
}
#RequestMapping(value = "/jobs/{id}", method = RequestMethod.GET)
public ModelAndView getJobPage(#PathVariable Long id) {
Map<String, Object> model = new HashMap<String, Object>();
if (null == jobService.getJobById(id)) {
throw new NoSuchElementException(String.format("Job=%s not found", id));
} else {
model.put("job", jobService.getJobById(id));
model.put("form", new ApplyForm());
}
return new ModelAndView("job_detail", model);
}
}
With this way, validations works but I still can't get the same effect here as it refreshes the page so that all valid inputs disappear and error messages don't appear.
By the way, job_detail.html is like this:
<h1>Job Details</h1>
<p th:inline="text"><strong>Title:</strong> [[${job.title}]]</p>
<p th:inline="text"><strong>Description:</strong> [[${job.description}]]</p>
<p th:inline="text"><strong>Number of people to hire:</strong> [[${job.numPeopleToHire}]]</p>
<p th:inline="text"><strong>Last application date:</strong> [[${job.lastDate}]]</p>
<div sec:authorize="isAuthenticated()">
<form th:action="#{/jobs/} + ${job.id}" method="post">
<input type="submit" value="Delete this posting" name="delete" />
</form>
</div>
<div sec:authorize="isAnonymous()">
<h1>Application Form</h1>
<form action="#" th:action="#{/jobs/} + ${job.id}" method="post">
<div>
<label>First name</label>
<input type="text" name="firstName" th:value="${form.firstName}" />
<td th:if="${#fields.hasErrors('form.firstName')}" th:errors="${form.firstName}"></td>
</div>
<!-- and other input fields -->
<input type="submit" value="Submit" name="apply" /> <input type="reset" value="Reset" />
</form>
</div>
Check thymeleaf documentation here
Values for th:field attributes must be selection expressions (*{...}),
Also ApplyForm is exposed then you can catch it in the form.
Then your form should looks like this:
<form action="#" th:action="#{/jobs/} + ${job.id}" th:object="${applyForm}" method="post">
<div>
<label>First name</label>
<input type="text" name="firstName" th:value="*{firstName}" />
<td th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"></td>
</div>
<!-- and other input fields -->
<input type="submit" value="Submit" name="apply" /> <input type="reset" value="Reset" />
</form>

Resources