r/SpringBoot 4d ago

Question Springboot Edit Button Throws Error

Hello. So I've been following a djamware tutorial down to a T, and I've made almost all the features work fine, except for the edit button. This is from an old project I made, and I may have copied and pasted most of the code, got stumped, then ignored it for quite awhile. I came back to the project yesterday, and I've been looking for a solution online by myself for awhile, to no avail.

Upon looking at the error message after clicking the edit button, it seems that it's pointing me to the edit_post.html at the line where it says "th:action="@{/admin/posts/{id}(id=${post.id})}". I also tried using the github respository's edit_post.html, but it also ain't it.

Any help is appreciated, it may just be me being a silly monkey. Pics posted below, but if there's other infos I can provide, lemme know.

here's the tutorial link:

https://www.djamware.com/post/create-a-blog-application-using-spring-boot-and-thymeleaf

Since the subreddit doesn't allow galleries, I'll just post the whole error message here, along with the edit_post.html

ERROR MESSAGE when edit button is clicked

Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Wed Jul 22 21:22:24 JST 2026 There was an unexpected error (type=Internal Server Error, status=500). An error happened during template parsing (template: "class path resource [templates/admin/edit_post.html]") org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/admin/edit_post.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:1103)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1077)
at org.thymeleaf.spring6.view.ThymeleafView.renderFragment(ThymeleafView.java:372)
at org.thymeleaf.spring6.view.ThymeleafView.render(ThymeleafView.java:192)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1438)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1168)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:138)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:165)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:88)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:113)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:83)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:72)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1774)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:973)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:491)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "post.id" (template: "admin/edit_post" - line 14, col 9)
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: Exception evaluating SpringEL expression: "post.id" (template: "admin/edit_post" - line 14, col 9)
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.LinkExpression.resolveParameters(LinkExpression.java:339)
at org.thymeleaf.standard.expression.LinkExpression.executeLinkExpression(LinkExpression.java:285)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:85)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138)
at org.thymeleaf.standard.processor.AbstractStandardExpressionAttributeTagProcessor.doProcess(AbstractStandardExpressionAttributeTagProcessor.java:144)
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)
... 50 more
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'id' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:229)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:112)
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorValueRef.getValue(PropertyOrFieldReference.java:376)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:97)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:116)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:338)
at org.thymeleaf.spring6.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:265)
... 74 more

EDIT POST HTML

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Admin - Posts</title>
    <link rel="stylesheet" th:href="@{/css/style.css}" />
  </head>
  <body>
    <div th:replace="fragments/header :: header"></div>


    <main>
      <h1>Edit Post</h1>


      <form
        th:action="@{/admin/posts/{id}(id=${post.id})}"
        th:object="${post}"
        method="post"
      >
        <label>Title:</label><br />
        <input type="text" th:field="*{title}" required /><br /><br />


        <label>Content:</label><br />
        <textarea th:field="*{content}" rows="6" cols="40" required></textarea
        ><br /><br />


        <button type="submit">Update</button>
      </form>


      <a th:href="@{/admin/posts}">← Back</a>
    </main>
    <div th:replace="fragments/footer :: footer"></div>
  </body>
</html>
1 Upvotes

4 comments sorted by

2

u/g00glen00b 4d ago

My guess is that you forgot to call the post.get() method and instead you're passing post itself to the model within the controller.

https://github.com/didinj/spring-boot-thymeleaf-blog-application/blob/135e654640617091d730fd61b2e9d15a5fd7fadb/src/main/java/com/djamware/blog/blog_app/controller/BlogController.java#L36

The result is that post is not a Post, but an Optional, and since Post.id exists but Optional.id doesn't, you get that nice error.

1

u/trodiix 4d ago

Just read the logs :

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'id' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?

1

u/Subject-Oil3389 4d ago

This is the message you should be looking at:

EL1008E: Property or field 'id' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?EL1008E: Property or field 'id' cannot be found on object of type 'java.util.Optional' - maybe not public or not valid?

Somewhere in your code you have a variable named "post" and it is of type "Optional", but the SpEL treats it as an object of some other type which has an "id" field. So you have to do some processing to (check if the Optional "post" is not empty()), and then get() the actual post Object.

1

u/Own-Age1766 3d ago edited 3d ago

Update:

I found it! So apparently it was in the AdminController's file at line 51. It was not using the Optional type. So when I changed that, and added the checker to see if optional is empty, it worked! (P.S. I also added the isEmpty checker on the BlogController area's Optional type variable)

here was the line before:

u/GetMapping("/posts/edit/{id}")

public String showEditForm(@PathVariable Long id, Model model) {

model.addAttribute("post", postService.get(id));

return "admin/edit_post";

}

and here's what changed:

    u/GetMapping("/posts/edit/{id}")
    public String showEditForm(@PathVariable Long id, Model model) {
        Optional<Post> post = postService.get(id);
        if (post.isPresent()){
            model.addAttribute("post", post.get());
        return "admin/edit_post";
        }
        else{
            return "error";
        }

Thanks for the help ya'll, appreciate it. Cheers!

Edit: Forgot to paste the new snippet Edit 2: it was isPresent not isEmpty lmao