I'm struggling to get the validation work on simple web form in spring boot + thymeleaf project.
I've got these dependencies in my pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
That's my DTO with @NotEmpty and @Pattern annotated fields:
package com.example.randomtext.web;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
@Getter
@Setter
@ToString
public class MainPageForm {
@NotEmpty(message = "choose the source file")
private SourceFile sourceFile;
private String sourceText;
private boolean sourceTextSet;
private String generatedText;
@Pattern(regexp = "[0-9]+", message = "input the whole number")
private String lengthOfOutput;
@RequiredArgsConstructor
@Getter
public enum SourceFile {
ALICE("alice.txt"),
CONFUCIUS("confucius.txt"),
private static final SourceFile[] ALL_VALUES = SourceFile.values();
private final String fileName;
}
}
that's my main.html form
<html>
<head><title>RandomText</title></head>
<body>
<h3>Random text generator</h3>
<pre th:if="${!mainPageForm.sourceTextSet}" th:style="'color:red;'">
source text not set. Have you chosen the source file?</pre>
<form action="#" th:action="@{/random_text}" th:object="${mainPageForm}"
method="post">
<label>source file</label><br>
<div th:each="sourceFile : ${T(com.example.randomtext.web.MainPageForm.SourceFile).values()}">
<input type="radio" th:field="*{sourceFile}" th:value="${sourceFile}">
<label th:text="${sourceFile.getFileName()}">source file</label>
<pre th:style="'color:red;'"
th:if="${#fields.hasErrors('sourceFile')}"
th:errors="*{sourceFile}"></pre>
<br>
</div>
<label>length of string to be generated<br>
<input type="text" width="200" th:field="*{lengthOfOutput}">
<pre th:style="'color:red;'"
th:if="${#fields.hasErrors('lengthOfOutput')}"
th:errors="*{lengthOfOutput}"></pre>
</label><br><br>
<br><input type="submit" value="Submit"/><input type="reset" value="Reset"/>
</form>
<pre th:text="${mainPageForm.sourceText}" th:style="'color:black;'">
source text</pre>
</body>
</html>
my controller looks like
package com.example.randomtext.web;
import com.example.randomtext.RandomTextService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
import java.net.URISyntaxException;
import static com.example.randomtext.Constants.BASE_PATH;
import static com.example.randomtext.Constants.MAIN_TEMPLATE;
@Controller
@RequiredArgsConstructor
@Slf4j
public class MainPageController {
private final RandomTextService service;
@GetMapping(BASE_PATH)
public String doGet(MainPageForm form) {
return MAIN_TEMPLATE;
}
@PostMapping(BASE_PATH)
public String doPost(@Valid MainPageForm mainPageForm, BindingResult bindingResult) throws URISyntaxException {
log.info("got form data {}", mainPageForm.toString());
if (!bindingResult.hasErrors()) {
log.info("see no errors :E");
log.info(bindingResult.toString());
log.info("sourceFile {}", mainPageForm.getSourceFile().getFileName());
mainPageForm.setSourceText(service.readSourceString(mainPageForm.getSourceFile().getFileName()));
} else {
log.info("got errors");
bindingResult.getFieldErrors()
.forEach(e -> log.error("got validation error {} for field {}",
e.getDefaultMessage(),
e.getField()));
}
return MAIN_TEMPLATE;
}
}
and when I submitting the empty form the log output is:
2023-01-30T20:22:49.481+03:00 INFO 5464 --- [p-nio-80-exec-6] c.e.randomtext.web.MainPageController : got form data MainPageForm(sourceFile=null, sourceText=null, sourceTextSet=false, generatedText=null, lengthOfOutput=)
2023-01-30T20:22:49.481+03:00 INFO 5464 --- [p-nio-80-exec-6] c.e.randomtext.web.MainPageController : see no errors :E
2023-01-30T20:22:49.481+03:00 INFO 5464 --- [p-nio-80-exec-6] c.e.randomtext.web.MainPageController : org.springframework.validation.BeanPropertyBindingResult: 0 errors
2023-01-30T20:22:49.483+03:00 ERROR 5464 --- [p-nio-80-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "com.example.randomtext.web.MainPageForm$SourceFile.getFileName()" because the return value of "com.example.randomtext.web.MainPageForm.getSourceFile()" is null] with root cause
I've looked trough similar questions: Spring boot validation doesn't work Spring boot validation annotations @Valid and @NotBlank not working Validation form in Spring using @Valid not work DTO validation in Spring Boot not working
played with javax and hibernate validation dependencies versions, tried maven-clean but nothing of these helped
I'd appreciate any hint