2
votes

Simple Spring Boot POST request not working and returns: "Request method 'POST' not supported" error message.

The code itself looks fine to me, but I'm not so sure about the pom.xml. If the problem relies in the pom.xml, then this case is hopeless since I don't even know what all those dependencies do nor why there are duplicates.

Here is my controller class:

@Controller
public class StudentController {

@Autowired
private StudentRepository studentRepository;


@GetMapping("/")
public String list(Model model) {
    model.addAttribute("students", studentRepository.findAll());
    return "index";
}


@PostMapping("/")
public String add(@RequestParam String name) {
    Student student = new Student(name);
    this.studentRepository.save(student);
    return "redirect:/";
}
}

Index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Test</title>
</head>
<body>
    <p>List all students </p>

    <p>Add a Student</p>

 <form th:action="@{/}" method="POST">
    <input type="text" name="name"/>
    <input type="submit"/>
</form>

<p>Students</p>

<p th:each="student : ${students}">
    <span th:text="${student.name}">student name</span>
</p>

</body>
</html>

Pom.xml

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>        
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>

    <dependency>
        <groupId>org.fluentlenium</groupId>
        <artifactId>fluentlenium-junit</artifactId>
        <version>3.7.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.fluentlenium</groupId>
        <artifactId>fluentlenium-assertj</artifactId>
        <version>3.7.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>htmlunit-driver</artifactId>
    </dependency>  

</dependencies>

<build>
    <plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    <resources>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
    </resources>
</build>
</project>

The code is supposed to add a student to studentRepository and redirect back to index.html and display the added student instantly.

Error Message from soapUI:

"timestamp": "2019-05-24T09:02:36.088+0000",
"status": 405,
"error": "Method Not Allowed",
"message": "Request method 'POST' not supported",
"trace": "org.springframework.web.HttpRequestMethodNotSupportedException: 
"path": "/"

Full trace:

> "trace":
> "org.springframework.web.HttpRequestMethodNotSupportedException: 
> Request method 'POST' not supported\r\n\tat 
> org.springframework.web.servlet.support.WebContentGenerator.checkRequest(WebContentGenerator.java:380)\r\n\tat
> org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:163)\r\n\tat
> org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52)\r\n\tat
> org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)\r\n\tat
> org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)\r\n\tat
> org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)\r\n\tat
> org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)\r\n\tat
> javax.servlet.http.HttpServlet.service(HttpServlet.java:660)\r\n\tat
> org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)\r\n\tat
> javax.servlet.http.HttpServlet.service(HttpServlet.java:741)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat
> org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat
> org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)\r\n\tat
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat
> org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)\r\n\tat
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat
> org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)\r\n\tat
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat
> org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)\r\n\tat
> org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)\r\n\tat
> org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)\r\n\tat
> org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)\r\n\tat
> org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)\r\n\tat
> org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)\r\n\tat
> org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)\r\n\tat
> org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\r\n\tat
> org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)\r\n\tat
> org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)\r\n\tat
> org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)\r\n\tat
> org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)\r\n\tat
> org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)\r\n\tat
> org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747)\r\n\tat
> org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\r\n\tat
> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)\r\n\tat
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)\r\n\tat
> org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\r\n\tat
> java.lang.Thread.run(Thread.java:745)\r\n"

application.properties

server.port=8083
[email protected]@
spring.datasource.url=jdbc:h2:file:./database;create=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect

Tutorial which is working fine:

Controller class

@Controller
public class ItemDatabaseController {

@Autowired
private ItemRepository itemRepository;

@GetMapping("/")
public String list(Model model) {
    model.addAttribute("items", this.itemRepository.findAll());
    return "index";
}

@PostMapping("/")
public String add(@RequestParam String name) {
    this.itemRepository.save(new Item(name));
    return "redirect:/";
}

}

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Item Database</title>
</head>

<body>
    <h1>Item Database</h1>

    <table>
        <tr>
            <th>Items</th>
        </tr>

        <tr th:each="item : ${items}">
            <td th:text="${item.name}">Item name</td>
        </tr>
    </table>

    <h2>Add an item</h2>

    <form th:action="@{/}" method="POST">
        <span>Name:</span>
        <input type="text" name="name"/>
        <input type="submit" value="Add!"/>
    </form>
</body>
</html>

pom.xml

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>        
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>

    <dependency>
        <groupId>org.fluentlenium</groupId>
        <artifactId>fluentlenium-junit</artifactId>
        <version>3.7.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.fluentlenium</groupId>
        <artifactId>fluentlenium-assertj</artifactId>
        <version>3.7.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>htmlunit-driver</artifactId>
    </dependency>  
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

These two are virtually the same, except this tutorial was downloaded and my own project was created in Eclipse as a Spring Boot: Spring Starter Project. Which is an Eclipse plugin.

3
What are you getting back if you try to hit the endpoint with Postman? So you know if the problem is the Controller or your html.burm87
added the error message to the end of the postwillberthos
@PostMapping(path = "/", consumes = "application/json", produces = "application/json") public void add(@RequestBody String name) { ...}, could resolveHasanuzzaman Rana
your controller seems fine no Issue with a controller, just check from UI are you calling an expected method, the issue seems like the method you are calling have difrrent mapping on controllerRavat Tailor
none of these workedwillberthos

3 Answers

0
votes

Use @RestController instead of @Controller Annotation or

simply use

@PostMapping("/")
@ResponseBody
0
votes

I suggest few tweaks in existing code. Please see if it works.

@Controller
@RequestMapping(path = "/", produces = MediaType.APPLICATION_JSON_VALUE)
public class StudentController {

@Autowired
private StudentRepository studentRepository;


@GetMapping("/")
public String list(Model model) {
    model.addAttribute("students", studentRepository.findAll());
    return "index";
}


@PostMapping(path = "/", produces = MediaType.APPLICATION_XML_VALUE)
public String add(@RequestBody String name) {
    Student student = new Student(name);
    this.studentRepository.save(student);
    return "redirect:/";
}
}

Hope it solves the problem.

0
votes

I think that, if you are performing the request from a form, the annotation @RequestParam may be wrong. That is used to get a parameter from the url (?name=myname). You may want to try @RequestBody.