Thymeleaf + Spring MVC - Thymeleaf template parsing error on using checkbox input

主宰稳场 提交于 2020-12-13 11:31:41

问题


I'm following this tutorial which uses Spring MVC, Spring Boot and Thymeleaf as the view. I'm getting a Template Parsing Error when I use a checkbox input on the HTML form, and strangely, when I remove the checkbox input, everything works well.

Here is the HTML -

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head>
    <meta charset="UTF-8">
    <title>Home Page</title>
    <style>
       h1,h2 {
           color: rebeccapurple;
       }
    </style>
</head>
<body>
<h1>This is home page</h1>

<h2>Enter data below</h2>
<form action="/create" method="post" th:object="${userData}">
    <p><label>
        Full Name<input type="text" th:field="${userData.fullName}" />
    </label></p>

    <p><label>
        Age <input type="text" th:field="${userData.age}" />
    </label></p>


    <p><label>
        Employed? <input type="checkbox" th:field="${userData.isEmployed}"/>
    </label></p>

    <p> Gender
        <label>
            Male
            <input type="radio" th:field="${userData.gender}" th:value="Male"/>
        </label>
        <label>
            Female
            <input type="radio" th:field="${userData.gender}" th:value="Female"/>
        </label>
    </p>

    <input type="submit" value="Submit"/><br>
    <input type="reset" value="Reset"/>

</form>
</body>
</html>

Here is the controller class -

@Controller
public class HomeController {

    @RequestMapping("/home")
    public String showHomeForm(Model model) {
        model.addAttribute("userData", new User());
        return "index";
    }

    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public String processHomeForm(User user) {
        return "result";
    }
}

Here is the domain (User) class -

public class User {
    // these fields were private initially...
    public String fullName;
    public String age;
    public boolean isEmployed;
    public String gender;

    public User() {
        System.out.println("User default constructor");
    }

    public User(String fullName, String age, boolean isEmployed, String gender) {
        this.fullName = fullName;
        this.age = age;
        this.isEmployed = isEmployed;
        this.gender = gender;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public boolean isEmployed() {
        return isEmployed;
    }

    public void setEmployed(boolean employed) {
        isEmployed = employed;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

And finally, this is the error and the stacktrace -

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Fri May 22 11:58:42 EDT 2020
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/index.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/index.html]")
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:241)
    at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100)
    at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
    at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1072)
    at org.thymeleaf.spring5.view.ThymeleafView.renderFragment(ThymeleafView.java:362)
    at org.thymeleaf.spring5.view.ThymeleafView.render(ThymeleafView.java:189)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    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:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    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:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    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:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.attoparser.ParseException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputCheckboxFieldTagProcessor' (template: "index" - line 27, col 42)
    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)
    ... 48 more
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputCheckboxFieldTagProcessor' (template: "index" - line 27, col 42)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:117)
    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.handleStandaloneElement(ProcessorTemplateHandler.java:918)
    at org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler.handleStandaloneElementEnd(TemplateHandlerAdapterMarkupHandler.java:260)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler$InlineMarkupAdapterPreProcessorHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:256)
    at org.thymeleaf.standard.inline.OutputExpressionInlinePreProcessorHandler.handleStandaloneElementEnd(OutputExpressionInlinePreProcessorHandler.java:169)
    at org.thymeleaf.templateparser.markup.InlinedOutputExpressionMarkupHandler.handleStandaloneElementEnd(InlinedOutputExpressionMarkupHandler.java:104)
    at org.attoparser.HtmlElement.handleStandaloneElementEnd(HtmlElement.java:79)
    at org.attoparser.HtmlMarkupHandler.handleStandaloneElementEnd(HtmlMarkupHandler.java:241)
    at org.attoparser.MarkupEventProcessorHandler.handleStandaloneElementEnd(MarkupEventProcessorHandler.java:327)
    at org.attoparser.ParsingElementMarkupUtil.parseStandaloneElement(ParsingElementMarkupUtil.java:96)
    at org.attoparser.MarkupParser.parseBuffer(MarkupParser.java:706)
    at org.attoparser.MarkupParser.parseDocument(MarkupParser.java:301)
    ... 50 more
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'isEmployed' of bean class [com.jrp.springdemo.domain.User]: Bean property 'isEmployed' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:622)
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:612)
    at org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:104)
    at org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:228)
    at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:129)
    at org.springframework.web.servlet.support.RequestContext.getBindStatus(RequestContext.java:903)
    at org.thymeleaf.spring5.context.webmvc.SpringWebMvcThymeleafRequestContext.getBindStatus(SpringWebMvcThymeleafRequestContext.java:227)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatusFromParsedExpression(FieldUtils.java:306)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:258)
    at org.thymeleaf.spring5.util.FieldUtils.getBindStatus(FieldUtils.java:227)
    at org.thymeleaf.spring5.processor.AbstractSpringFieldTagProcessor.doProcess(AbstractSpringFieldTagProcessor.java:174)
    at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74)
    ... 63 more

The stacktrace includes a message about the isEmployed field of the User class being an invalid property -

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'isEmployed' of bean class [com.jrp.springdemo.domain.User]: Bean property 'isEmployed' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

I think this is what is causing the template parsing error, but I have it exactly the way its shown in the tutorial.

Any help would be appreciated.


回答1:


The th:field should employed rather than isEmployed.

<input type="checkbox" th:field="${userData.employed}" />

The relevant error from your stack tracec:

Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'isEmployed' of bean class [com.jrp.springdemo.domain.User]: Bean property 'isEmployed' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?

For boolean values, employed checks for getter isEmployed() and setter setEmployed(...). For any other types employed would check for getter getEmployed() and setter setEmployed(...). Since you tried to use isEmployed that means that Thymeleaf was looking for isIsEmployed() or getIsEmployed().



来源:https://stackoverflow.com/questions/61960054/thymeleaf-spring-mvc-thymeleaf-template-parsing-error-on-using-checkbox-inpu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!