Thymeleaf - th:method="delete/put" leads to: Request method 'POST' not supported
Asked Answered
H

1

7

I use Spring Boot v2.7.0, installed from "start.spring.io" and from there I installed Thymeleaf, and as I searched in the parent-pom I found out that: thymeleaf-spring5 (v3.0.15.RELEASE), thymeleaf-extras-java8time (v3.0.4.RELEASE)

Lately, I needed to apply the pattern <form th:method="put/delete".../>. After googling in verious places, I found the solution, which was reffered in the book as well: "Taming Thymeleaf Practical Guide to building a web application with Spring Boot and Thymeleaf - Wim Deblauwe" which is the top/excellent books of Thymeleaf, and from which I learn Thymeleaf. Acoording to these, I did:

Step 1:

Added this property in application.properties:

spring.mvc.hiddenmethod.filter.enabled=true

and I tried it in the application.yaml (as a 2nd solution, because the previous did not work), like this way:

spring:
  mvc:
    hiddenmethod:
      filter:
        enabled: true

Step 2:

I used:

<form th:method="put".../>
<form th:method="delete".../>

Step 3:

Finally I used the: "@PutMapping, @DeleteMapping" in my controller handler methods.

The result was the error message:

There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:253)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:442)

After googling I found this solution, to add the needed bean by myself with the following way, which DID WORKED:

@Bean
public FilterRegistrationBean<HiddenHttpMethodFilter> hiddenHttpMethodFilter() {
    FilterRegistrationBean<HiddenHttpMethodFilter> filterRegistrationBean = new FilterRegistrationBean<>(new HiddenHttpMethodFilter());
    filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
    return filterRegistrationBean;
}

I wonder why this configuration "spring.mvc.hiddenmethod.filter.enabled=true", does not add the needed bean in my case, and I have to add it by myself.

Anyone can help me on this, please? Thanks a lot in advance

Hooge answered 24/6, 2022 at 12:50 Comment(0)
D
4

I just did a test myself and this worked fine.

  1. Create a new project on start.spring.io selecting Spring Boot 2.7.1 with dependencies Spring Web and Thymeleaf
  2. Create a controller:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@RequestMapping
@Controller
public class TestController {
    @GetMapping
    public String index(Model model) {
        model.addAttribute("formData", new TestFormData());
        return "index";
    }

    @PutMapping
    public String doPut(@ModelAttribute("formData") TestFormData formData) {
        System.out.println("formData.getSomeString() = " + formData.getSomeString());
        return "redirect:/";
    }
}

With this form data class:

public class TestFormData {
    private String someString;

    public String getSomeString() {
        return someString;
    }

    public void setSomeString(String someString) {
        this.someString = someString;
    }
}
  1. Create an index.html file in src/main/resources/templates:
<!DOCTYPE html>
<html lang="en"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form th:action="@{/}" th:method="put" th:object="${formData}">
    <input th:field="*{someString}">
    <button>Save</button>
</form>
</body>
</html>
  1. Update application.properties to contain:
spring.mvc.hiddenmethod.filter.enabled=true
  1. Start the application and go to http://localhost:8080 and enter something in the input field. When pressing save, it is printed to the console, showing that the @PutMapping works.
Dehlia answered 26/6, 2022 at 7:50 Comment(3)
Hello @Deblauwe, sir. Thank you for your reply. I tried your steps in a new project. It works fine to me also. I changed the properties to yaml, and the "new" operator you used in Component/Autowired. Works nice as well. I accept it as solution, but I need to find in my project's code/configuration, what breaks this funtionality. As soon as I find out, what went wrong in my case, I will right it down here in a comment in your reply. Thanks a lot againHooge
After some changes, I found out what causes the problem, but I don't know why... In spring boot I came from "simple" spring mvc. There my project has in IntelliJ "webapp/WEB-INF", and there in the "webapp/WEB-INF/views" I put my thymeleaf views. For that reason, I put code in the WebConfig to resolve the: Bean public ITemplateResolver htmlTemplateResolver() { /*...*/ resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".html"); /*...*/} I tried to make the stucture in the demo project you made @Deblauwe, like my straucture I wrote before, I this gave me: "POST is not supported"Hooge
I am studding to understand why this structure "webapp/WEB-INF/views", cuses this problemHooge

© 2022 - 2024 — McMap. All rights reserved.