У меня есть этот объект:
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NatalChartDataPayload {
String langCode;
@NotEmpty(message = "Email cannot be empty")
@Email(message = "Invalid email format")
String email;
String city;
String place;
}
Контроллер выглядит так:
@GetMapping({"/data"})
public String data (Model model) {
model.addAttribute("months", Month.values());
model.addAttribute("data", NatalChartDataPayload.builder().build());
return "natalChartData";
}
@PostMapping("/create")
public String createNatalChart (
@Valid @ModelAttribute NatalChartDataPayload data,
BindingResult result,
Model model
) {
if (result.hasErrors()) {
return "natalChartData";
}
User user = new User();
user.setEmail(data.getEmail());
if (data.getPlace() == null ||
data.getPlace().isEmpty() ||
data.getEmail() == null ||
data.getEmail().isEmpty()) {
return "redirect:/natalchart/data";
}
Однако, когда адрес электронной почты неверен, у меня возникает эта ошибка:
aused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "#fields.hasErrors('email')" (template: "natalChartData" - line 142, col 20)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:393)
at org.attoparser.MarkupParser.parse(MarkupParser.java:257)
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:230)
... 101 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "#fields.hasErrors('email')" (template: "natalChartData" - line 142, col 20)
at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:292)
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:125)
at org.thymeleaf.standard.processor.StandardIfTagProcessor.isVisible(StandardIfTagProcessor.java:59)
at org.thymeleaf.standard.processor.AbstractStandardConditionalVisibilityTagProcessor.doProcess(AbstractStandardConditionalVisibilityTagProcessor.java:61)
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95)
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633)
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314)
at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleOpenElementEnd(TemplateHandlerAdapterMarkupHandler.java:304)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:278)
at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleOpenElementEnd(OutputExpressionInlinePreProcessorHandler.java:186)
at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleOpenElementEnd(InlinedOutputExpressionMarkupHandler.java:124)
at org.attoparser.HtmlElement.handleOpenElementEnd(HtmlElement.java:109)
at org.attoparser.HtmlMarkupHandler.handleOpenElementEnd(HtmlMarkupHandler.java:297)
at org.attoparser.MarkupEventProcessorHandler.handleOpenElementEnd(MarkupEventProcessorHandler.java:402)
at org.attoparser.ParsingElementMarkupUtil.parseOpenElement(ParsingElementMarkupUtil.java:159)
at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:710)
at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
... 103 more
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'data' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153)
at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:926)
at org.thymeleaf.spring6.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:232)
at org.thymeleaf.spring6.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306)
at org.thymeleaf.spring6.util.FieldUtils.getBindStatus(FieldUtils.java:253)
at org.thymeleaf.spring6.util.FieldUtils.getBindStatus(FieldUtils.java:227)
at org.thymeleaf.spring6.util.FieldUtils.checkErrors(FieldUtils.java:212)
вот шаблон:
<form method = "post" th:action = "@{/natalchart/create}" th:object = "${data}">
<div class = "row">
<div class = "col-lg-8">
<h4>Enter your birth details to create your natal chart</h4>
<p> </p>
<p> </p>
<div th:if = "${#fields.hasErrors('email')}" th:errors = "*{email}">Email Error</div>
<div>
<label for = "language">PDF Report Language</label>
<select th:field = "*{langCode}">
<option value = "en">English</option>
<option value = "es">Spanish</option>
<option value = "fr">French</option>
<option value = "pt">Portuguese</option>
</select><br><br>
<label for = "email">Email</label>
<input id = "email" name = "email" placeholder = "email" th:field = "*{email}" /><br><br>
<!-- Label and select fields for day, month, and year of birth -->
<label for = "dayOfBirth">Date of Birth:</label>
<select id = "dayOfBirth" th:field = "*{dayOfBirth}">
<option th:each = "day : ${#numbers.sequence(1, 31)}" th:text = "${day}" th:value = "${day}"></option>
</select>
<select id = "monthOfBirth" th:field = "*{monthOfBirth}">
<option th:each = "month : ${months}" th:text = "${month}" th:value = "${month.getValue()}"></option>
</select>
<select id = "yearOfBirth" th:field = "*{yearOfBirth}">
<option th:each = "year : ${#numbers.sequence(1900, 2025)}" th:text = "${year}" th:value = "${year}"></option>
</select>
<br><br>
<!-- Label and select fields for hour and minute of birth -->
<label for = "hourOfBirth">Time of Birth:</label>
<select id = "hourOfBirth" th:field = "*{hourOfBirth}">
<option th:each = "hour : ${#numbers.sequence(0, 23)}" th:text = "${hour}" th:value = "${hour}"></option>
</select>
<select id = "minuteOfBirth" th:field = "*{minuteOfBirth}">
<option th:each = "minute : ${#numbers.sequence(0, 59)}" th:text = "${minute}" th:value = "${minute}"></option>
</select>
<br><br>
<label for = "hint">Place of birth (Select one of the list)</label>
<input id = "hint" name = "hint" th:field = "*{city}" /><br><br>
<input id = "place" name = "place" th:field = "*{place}" type = "hidden"/>
</div>
</div>
<div class = "col-lg-4">
<div class = "blog-sidbar">
<div class = "d-flex justify-content-between mt-20">
<button class = "fill-btn" data-text = "Send Message" type = "submit">create PDF Natal Chart Report</button>
</div>
</div>
</div>
</div>
</form>




Попробуйте использовать условный оператор в своем классе, чтобы оценить, следует ли использовать «класс ошибки».
Пример:
<p th:if = "${#fields.hasErrors('email')}" th:class = "${#fields.hasErrors('email')}? error">Invalid Email</p>
<style>
.error {
color: red;
}
</style>
Другой атрибут Thymeleaf th:errors дает нам возможность отображать все ошибки в указанном селекторе, скажем, по электронной почте:
<div>
<label for = "email">Email</label> <input type = "text" th:field = "*{email}" />
<p th:if = "${#fields.hasErrors('email')}" th:errorclass = "error" th:errors = "*{email}" />
</div>
Дополнительная ссылка:
Я пробовал с той же ошибкой
Согласно последней причине в вашей трассировке ошибок:
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'data' available as request attribute
проблема, с которой вы столкнулись, может быть вызвана отсутствием атрибута data в запросе.
По словам вашего контроллера, в случае ошибок проверки вы даете Spring указание снова перенаправить запрос на страницу вашего шаблона HTML, но не предоставляете обязательный атрибут data.
Вероятно, проблему можно решить разными способами, но попробуйте следующее, я думаю, все должно работать правильно:
@PostMapping("/create")
public String createNatalChart (
@Valid @ModelAttribute NatalChartDataPayload data,
BindingResult result,
Model model
) {
if (result.hasErrors()) {
// Add data to the returned model. Probably you will need
// to add the attribute months as well
model.addAttribute("data", data);
return "natalChartData";
}
User user = new User();
user.setEmail(data.getEmail());
if (data.getPlace() == null ||
data.getPlace().isEmpty() ||
data.getEmail() == null ||
data.getEmail().isEmpty()) {
return "redirect:/natalchart/data";
}
Как выглядит ваш HTML?