I can see validation error on console but thymeleaf template not displaying error. It supposed to display error on thymeleaf template. I am using spring boot 2.5.4
Thanks in advance.
My Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.ttl</groupId>
<artifactId>cps-admission-portal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cps-admission-portal</name>
<description>CPS Admission Portal</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.0.0-2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My Controller
package com.ttl.cpsadmissionportal.controller;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.validation.Valid;
import javax.validation.executable.ValidateOnExecution;
import javax.xml.bind.annotation.XmlRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.ttl.cpsadmissionportal.model.AdmissionForm;
import com.ttl.cpsadmissionportal.service.CampusService;
import com.ttl.cpsadmissionportal.service.OfferProgramService;
import com.ttl.cpsadmissionportal.serviceimpl.AdmissionFormServiceImple;
@Controller
public class AdmissionFormController {
@Autowired
private OfferProgramService offerProgramService;
@Autowired
private AdmissionFormServiceImple admissionFormServiceImple;
@Autowired
private CampusService campusService;
@GetMapping("admissionform")
public String viewAdmissionForm(Model model) {
AdmissionForm admissionForm = new AdmissionForm();
model.addAttribute("admissionForm",admissionForm);
model.addAttribute("listCampuses",campusService.getAllCampuses());
return "admissionform";
}
@PostMapping("saveadmissionform")
public String saveAdmissionForm(@Valid @ModelAttribute("admissionForm") AdmissionForm admissionForm
,RedirectAttributes redirectAttributes
, BindingResult bindingResulted) {
if (bindingResulted.hasErrors()) {
System.out.println("ERROR IN VALIDATION");
return "admissionform";
}
admissionFormServiceImple.addAdmissionForm(admissionForm);
redirectAttributes.addAttribute("candidateName",admissionForm.getCandidateName());
redirectAttributes.addAttribute("refNbr",admissionForm.getRefNbr());
return "redirect:/thankyou";
}
@GetMapping("thankyou")
public String thankyou() {
return "thankyou";
}
}
Model
package com.ttl.cpsadmissionportal.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
import com.sun.istack.NotNull;
@Entity
@Table(name="ADMISSION_FORM", schema = "UCP")
public class AdmissionForm {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "af_id_gen")
@SequenceGenerator(name="af_id_gen", sequenceName="SEQ_AF_ID", schema = "UCP",allocationSize=1)
@Column(name="AF_ID")
private int afId;
@Column(name="OP_ID")
private int opId;
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ref_nbr_gen")
@SequenceGenerator(name="ref_nbr_gen", sequenceName="SEQ_REF_NBR", schema = "UCP",allocationSize=1)
@Column(name="REF_NBR")
private String refNbr;
@NotEmpty
@NotNull
@Size(min=10,max=50)
@Column(name="CANDIDATE_NAME")
private String candidateName;
@NotEmpty
@NotNull
@Column(name="GENDER_IND")
private String genderInd;
@NotEmpty
@NotNull
@Column(name="FATHER_NAME")
private String fatherName;
@NotEmpty
@NotNull
@Column(name="RELATIONSHIP_IND")
private String relationshipInd;
@NotEmpty
@NotNull
@Column(name="PARENT_CNIC_NBR")
private String parentCnicNbr;
@NotEmpty
@NotNull
@Column(name="PARENT_CONTACT_NBR")
private String parentContactNbr;
@NotEmpty
@NotNull
@Column(name="STUDENT_CNIC_NBR")
private String studentCnicNbr;
@NotEmpty
@NotNull
@Column(name="STUDENT_CONTACT_NBR")
private String studentContactNbr;
@NotEmpty
@NotNull
@Email
@Column(name="STUDENT_EMAIL_ADD")
private String studentEmailAdd;
@Column(name="ADDRESS")
private String address;
public int getAfId() {
return afId;
}
public void setAfId(int afId) {
this.afId = afId;
}
public int getOpId() {
return opId;
}
public void setOpId(int opId) {
this.opId = opId;
}
public String getRefNbr() {
return refNbr;
}
public void setRefNbr(String refNbr) {
this.refNbr = refNbr;
}
public String getCandidateName() {
return candidateName;
}
public void setCandidateName(String candidateName) {
this.candidateName = candidateName;
}
public String getGenderInd() {
return genderInd;
}
public void setGenderInd(String genderInd) {
this.genderInd = genderInd;
}
public String getFatherName() {
return fatherName;
}
public void setFatherName(String fatherName) {
this.fatherName = fatherName;
}
public String getRelationshipInd() {
return relationshipInd;
}
public void setRelationshipInd(String relationshipInd) {
this.relationshipInd = relationshipInd;
}
public String getParentCnicNbr() {
return parentCnicNbr;
}
public void setParentCnicNbr(String parentCnicNbr) {
this.parentCnicNbr = parentCnicNbr;
}
public String getParentContactNbr() {
return parentContactNbr;
}
public void setParentContactNbr(String parentContactNbr) {
this.parentContactNbr = parentContactNbr;
}
public String getStudentCnicNbr() {
return studentCnicNbr;
}
public void setStudentCnicNbr(String studentCnicNbr) {
this.studentCnicNbr = studentCnicNbr;
}
public String getStudentContactNbr() {
return studentContactNbr;
}
public void setStudentContactNbr(String studentContactNbr) {
this.studentContactNbr = studentContactNbr;
}
public String getStudentEmailAdd() {
return studentEmailAdd;
}
public void setStudentEmailAdd(String studentEmailAdd) {
this.studentEmailAdd = studentEmailAdd;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
my thymeleaf template
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Admission Form</title>
<link th:rel="stylesheet"
th:href="@{/webjars/bootstrap/4.0.0-2/css/bootstrap.min.css} " />
<link rel="stylesheet" href="sb-admin-2.css" />
<link th:href="@{/css/sb-admin-2.css}" rel="stylesheet" />
</head>
<body>
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<form action="#" role="form" th:action="@{/saveadmissionform}"
th:object="${admissionForm}" method="post">
<div class="container-fluid mt-n10">
<div class="card card-header-actions mb-4">
<div class="card-body">
<div class="row mt-2 mb-2">
<div class="row">
<div class="col-md-12">
<h2 class="heading">Personal Info</h2>
</div>
</div>
<div class="row mt-2 mb-2">
<div class="col-md-3">
<div class="form-group">
<label for=candidateName>Full Name <span style="color: red">
*</span></label> <input type="text" th:field="*{candidateName}"
class="form-control form-control-solid" id="candidateName"
placeholder="Enter Full Name" required>
<span th:if="${#fields.hasErrors('candidateName')}" th:errors="*{candidateName}">Full name error</span>
</div>
</div>
</form>
</body>
</html>
Following Error occur but it should display error in front of candidate name.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Sep 23 20:14:01 PKT 2021
There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='admissionForm'. Error count: 1
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'admissionForm' on field 'candidateName': rejected value [a]; codes [Size.admissionForm.candidateName,Size.candidateName,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [admissionForm.candidateName,candidateName]; arguments []; default message [candidateName],50,10]; default message [size must be between 10 and 50]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:175)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1064)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1726)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
CodePudding user response:
The BindingResult
must be directly following the ModelAttribute
parameter in your controller method.
This should work:
public String saveAdmissionForm(@Valid @ModelAttribute("admissionForm")
AdmissionForm admissionForm,
BindingResult bindingResulted,
RedirectAttributes redirectAttribute) {
See Cannot get validation working with Spring Boot and Thymeleaf